diff --git a/pscheduler-test-dns64/Makefile b/pscheduler-test-dns64/Makefile new file mode 100644 index 000000000..413b49797 --- /dev/null +++ b/pscheduler-test-dns64/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Any Package +# + +AUTO_TARBALL := 1 + +include unibuild/unibuild.make diff --git a/pscheduler-test-dns64/README.md b/pscheduler-test-dns64/README.md new file mode 100644 index 000000000..cd6bb53c3 --- /dev/null +++ b/pscheduler-test-dns64/README.md @@ -0,0 +1 @@ +Documentation on how to write a test for pScheduler can be found in the main directory of the PDK in the file test.md (https://github.com/perfsonar/pscheduler/blob/pdk-docs/scripts/PDK/test.md) diff --git a/pscheduler-test-dns64/dns64/Makefile b/pscheduler-test-dns64/dns64/Makefile new file mode 100644 index 000000000..47cfddf6c --- /dev/null +++ b/pscheduler-test-dns64/dns64/Makefile @@ -0,0 +1,47 @@ +# +# Makefile for any test class +# + +NAME=dns64 + +# TODO: Everything below this should be made into a template that can +# be included. + +FILES=\ + cli-to-spec \ + enumerate \ + participants \ + result-format \ + spec-format \ + spec-is-valid \ + spec-to-cli + +MODULES=\ + validate \ + + +PYS=$(MODULES:%=%.py) +PYCS=$(MODULES:%=__pycache__/%.pyc) + +$(PYCS): +ifndef DESTDIR + @echo No PYTHON specified for build + @false +endif + $(PYTHON) -m compileall . +TO_CLEAN += $(PYCS) + + +install: $(FILES) $(PYS) $(PYCS) +ifndef DESTDIR + @echo No DESTDIR specified for installation + @false +endif + mkdir -p $(DESTDIR) + install -m 555 $(FILES) $(DESTDIR) + install -m 444 $(PYS) $(DESTDIR) + cp -r __pycache__ $(DESTDIR) + + +clean: + rm -f $(TO_CLEAN) *~ diff --git a/pscheduler-test-dns64/dns64/cli-to-spec b/pscheduler-test-dns64/dns64/cli-to-spec new file mode 100755 index 000000000..b0b63f224 --- /dev/null +++ b/pscheduler-test-dns64/dns64/cli-to-spec @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +# +# Development Order #4: +# +# This file encodes CLI arguments as JSON data in a test spec, +# as defined by the datatypes in validate.py +# +# This can be tested directly using the following syntax: +# ./cli-to-spec --option argument +# + +import re +import argparse +import pscheduler +import sys + +if len(sys.argv) > 1: + + # Args are on the command line + args = sys.argv[1:] + +else: + + # Args are in a JSON array on stdin + json_args = pscheduler.json_load(exit_on_error=True) + args = [] + + if not isinstance(json_args,list): + pscheduler.fail("Invalid JSON for this operation") + for arg in json_args: + if not ( isinstance(arg, str) + or isinstance(arg, int) + or isinstance(arg, float) ): + pscheduler.fail("Invalid JSON for this operation") + args = [ str(arg) for arg in json_args ] + + + +# Gargle the arguments + +arg_parser = argparse.ArgumentParser(epilog= +""" + This test validates DNS64 IPv4 and IPv6 conversion +""" +) + +# Add all potential command line options here + + +arg_parser.add_argument("--query", + help="Hostname to look up.") + +arg_parser.add_argument("--nameserver", + help="Nameserver to query.") + +arg_parser.add_argument("--host", + help="Host to run the test.") + +arg_parser.add_argument("--host-node", + help="Hostname to run the test.", dest="host_node") + +arg_parser.add_argument("--translation-prefix", + help="Translation prefix to expect for converted results.", + dest="translation_prefix") + +arg_parser.add_argument("--timeout", + help="Timeout for each query attempt", + dest="timeout") + + +arguments = arg_parser.parse_args(args) + + +# Call .set(n) on this object to indicate that a parameter requires +# schema level n or higher. The object will return the highest-set +# value when .value() is called. +# +# For example, if the 'foo' parameter was introduced in schema level 2: +# +# if options.foo is not None: +# result['foo'] = options.foo +# schema.set(2) +# +# If this is a brand-new test, you won't need to call .set() since the +# default is 1. + +schema = pscheduler.HighInteger(1) + + +# Build the test specification. All we do here is build and set +# schema levels. Validation happens elsewhere. + +result = { } + +if arguments.query is not None: + result['query'] = arguments.query + +if arguments.nameserver is not None: + result['nameserver'] = arguments.nameserver + +if arguments.host is not None: + result['host'] = arguments.host + +if arguments.host_node is not None: + result['host-node'] = arguments.host_node + +if arguments.translation_prefix is not None: + result['translation-prefix'] = arguments.translation_prefix + +if arguments.timeout is not None: + result['timeout'] = arguments.timeout + +result['schema'] = schema.value() + + +pscheduler.succeed_json(result) diff --git a/pscheduler-test-dns64/dns64/enumerate b/pscheduler-test-dns64/dns64/enumerate new file mode 100644 index 000000000..f1fdea1fb --- /dev/null +++ b/pscheduler-test-dns64/dns64/enumerate @@ -0,0 +1,21 @@ +#!/bin/sed -e 1d;/^#/d + +# +# Development Order #2: +# +# This JSON data describes the test, and will be shown when 'pscheduler +# plugins tests' is run. This is the first file which should be edited. +# + +{ + "schema": 1, + "name": "dns64", + "description": "Test that checks for the correct functioning of a DNS64 server", + "version": "1.0", + "maintainer": { + "name": "perfSONAR Development Team", + "email": "perfsonar-developer@internet2.edu", + "href": "http://www.perfsonar.net" + }, + "scheduling-class": "background" +} diff --git a/pscheduler-test-dns64/dns64/inputs/result-format b/pscheduler-test-dns64/dns64/inputs/result-format new file mode 100644 index 000000000..7202fa726 --- /dev/null +++ b/pscheduler-test-dns64/dns64/inputs/result-format @@ -0,0 +1,13 @@ +{ + "succeeded": true, + "result": { + "schema": 1, + "time": "PT0.071234S", + "succeeded": true, + "translated": true, + "ipv4": ["27.173.202.254", "190.173.250.206", "222.173.190.239"], + "ipv6": ["64:ff9b::1bad:cafe", "64:ff9b::bead:face", "64:ff9b::dead:beef"] + }, + "error": "", + "diags": "" +} diff --git a/pscheduler-test-dns64/dns64/inputs/spec-format b/pscheduler-test-dns64/dns64/inputs/spec-format new file mode 100644 index 000000000..cc2e104b7 --- /dev/null +++ b/pscheduler-test-dns64/dns64/inputs/spec-format @@ -0,0 +1,7 @@ +{ + "query": "ipv4.me", + "nameserver": "2001:4860:4860::64", + "host": "foo.example.com", + "translation-prefix": "64:ff9b::/96", + "timeout": "PT15S" +} diff --git a/pscheduler-test-dns64/dns64/participants b/pscheduler-test-dns64/dns64/participants new file mode 100644 index 000000000..d3940e756 --- /dev/null +++ b/pscheduler-test-dns64/dns64/participants @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 + +# +# Development Order #7: +# +# Participant list generator for 'dns64' task spec +# +# Input is an unvalidated dns64 test specification. +# + +# Output is a JSON object: +# +# { +# "participants": [ "host-1", ..., "host-n" ] +# "null-reason": "Optional reason why participants[0] is null" +# } +# +# The first element of "participants" array may be null to +# signify that local host is the first participant. +# + +import pscheduler +import sys + +from validate import spec_is_valid + +# Validate the input + +json = pscheduler.json_load(exit_on_error=True) + +valid, message = spec_is_valid(json) +if not valid: + pscheduler.fail(message) + + +# Determine the list of participants + +# This test only has a single participant, which can be determined by +# looking up the 'host-node' or 'host' item in the specification. +host = json.get('host-node', json.get('host', None)) + +participants = [ host ] + +result = { "participants": participants } + + +# Explain why the first participant is null + +if host is None: + result["null-reason"] = "No host specified" + + +pscheduler.succeed_json(result) diff --git a/pscheduler-test-dns64/dns64/result-format b/pscheduler-test-dns64/dns64/result-format new file mode 100755 index 000000000..856937084 --- /dev/null +++ b/pscheduler-test-dns64/dns64/result-format @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 + +# +# Development Order #8: +# +# This will format a test result into something that is human readable. +# +# To test this file, a spec is needed. You can generate one by pulling +# a result out of the pScheduler API or modifying inputs/result-format +# to suit your format. +# +# Invoke this program as follows: +# +# +# ./result-format text/plain < inputs/result-format +# ./result-format text/html < inputs/result-format +# + +import pscheduler + +from validate import result_is_valid +from validate import MAX_SCHEMA + +# This is a Jinja2 template with the contents of the test +# specification provided as variables. +# +# Input provided to the template will be the original test spec in +# spec.* and the result to bef formatted in result.*. +# +# See the documentation for spec_result_method() in +# python-pscheduler/pscheduler/pscheduler/text.py for a list of +# variables and functions provided. + +TEMPLATE = ''' +{% if _mime_type == 'text/plain' %} + +Elapsed Time ... {{ unspec(result.time) }} +{% for record in result.ipv4 -%} +IPv4 address ... {{ record }} +{% endfor -%} + +{%- for record in result.ipv6 -%} +IPv6 address ... {{ record }} +{% endfor -%} + +Translated ..... {{ result.translated }} + +{% elif _mime_type == 'text/html' %} + + + + + + +
Elapsed Time{{ unspec(result.time) }}
IPv4
  • {{ result.ipv4 | join('
  • ') }}
IPv6
  • {{ result.ipv6 | join('
  • ') }}
Translated{{ result.translated }}
+ +{% else %} + +{{ error('Unsupported MIME type "' + _mime_type + '"') }} + +{% endif %} +''' + +pscheduler.result_format_method(TEMPLATE, max_schema=MAX_SCHEMA, validator=result_is_valid) diff --git a/pscheduler-test-dns64/dns64/spec-format b/pscheduler-test-dns64/dns64/spec-format new file mode 100755 index 000000000..7c1956653 --- /dev/null +++ b/pscheduler-test-dns64/dns64/spec-format @@ -0,0 +1,64 @@ +#!/usr/bin/env python3 +# +# Development Order #9: +# +# This will format a test spec into something that is human readable. +# +# To test this file, a spec is needed. You can generate one with +# cli-to-spec or modify inputs/spec-format after you've written +# it. +# +# Invoke this program as follows: +# +# +# ./spec-format text/plain < inputs/spec-format +# ./spec-format text/html < inputs/spec-format +# + +import pscheduler + +from validate import spec_is_valid +from validate import MAX_SCHEMA + +# This is a Jinja2 template with the contents of the test +# specification provided as variables. +# +# See the documentation for spec_result_method() in +# python-pscheduler/pscheduler/pscheduler/text.py for a list of +# variables and functions provided. + +TEMPLATE=''' +{# If dealing with a spec that has multiple schemas, do this: + {%- set schema = 1 if schema is undefined else schema -%} +#} + +{% if _mime_type == 'text/plain' %} + +Query ............. {{ unspec(query) }} +Nameserver ........ {{ unspec(nameserver) }} +Host ............. {{ unspec(host) }} +Host node ............. {{ unspec(hostnode) }} +Translation prefix ......... {{ unspec(translationprefix) }} +Timeout .......... {{ unspec(timeout) }} + + +{% elif _mime_type == 'text/html' %} + + + + + + + + + +
Query{{ unspec(query) }}
Nameserver{{ unspec(nameserver) }}
Host{{ unspec(host) }}
Host node{{ unspec(hostnode) }}
Translation prefix{{ unspec(translationprefix) }}
Timeout{{ unspec(timeout) }}
+ +{% else %} + +{{ error('Unsupported MIME type "' + _mime_type + '"') }} + +{% endif %} +''' + +pscheduler.spec_format_method(TEMPLATE, max_schema=MAX_SCHEMA, validator=spec_is_valid) diff --git a/pscheduler-test-dns64/dns64/spec-is-valid b/pscheduler-test-dns64/dns64/spec-is-valid new file mode 100755 index 000000000..0656e8705 --- /dev/null +++ b/pscheduler-test-dns64/dns64/spec-is-valid @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +# +# Development Order #6: +# +# This file accepts a test spec through stdin and outputs whether +# or not it was validated through stdout. +# +# This can be tested directly using the following syntax: +# ./cli-to-spec --option argument | ./spec-is-valid +# +# NOTE: In most cases, there should be no need to modify this file. +# + +import pscheduler + +from validate import spec_is_valid + +try: + json = pscheduler.json_load() +except ValueError as ex: + pscheduler.succeed_json({ + "valid": False, + "error": str(ex) + }) + +valid, message = spec_is_valid(json) + +result = { + "valid": valid +} + +if not valid: + result["error"] = message + +pscheduler.succeed_json(result) diff --git a/pscheduler-test-dns64/dns64/spec-to-cli b/pscheduler-test-dns64/dns64/spec-to-cli new file mode 100755 index 000000000..7a68433fc --- /dev/null +++ b/pscheduler-test-dns64/dns64/spec-to-cli @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 + +# +# Development Order #5: +# +# This file will convert a test specification to command-line options. +# +# This can be tested directly using the following syntax: +# ./cli-to-spec --option argument | ./spec-to-cli + +import pscheduler + +from validate import spec_is_valid + +spec = pscheduler.json_load(exit_on_error=True) + +# First, validate the spec +valid, message = spec_is_valid(spec) + +if not valid: + pscheduler.fail(message) + +result = pscheduler.speccli_build_args(spec, + strings=[ + + # Add all argument strings here, as tuples + + ( 'query', 'query' ), + ( 'nameserver', 'nameserver' ), + ( 'host', 'host' ), + ( 'host-node', 'host_node' ), + ( 'translation-prefix', 'translation_prefix'), #should this be _ or -? + ( 'timeout', 'timeout' ) + ]) + +pscheduler.succeed_json(result) diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/changelog b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/changelog new file mode 100644 index 000000000..b8a37a9ed --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/changelog @@ -0,0 +1,12 @@ +pscheduler-test-dns64 (5.2.0~a1.0-1) perfsonar-5.2-snapshot; urgency=low + + * New upstream version. + + -- perfSONAR developers Tue, 11 Jun 2024 18:29:36 +0200 + +pscheduler-test-dns64 (5.1.0~a1.0-1) perfsonar-5.1-snapshot; urgency=low + + * Initial release + + -- perfSONAR developers Tue, 13 Oct 2020 17:48:12 +0000 + diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/compat b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/compat new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/compat @@ -0,0 +1 @@ +10 diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/control b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/control new file mode 100644 index 000000000..ab4da06e7 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/control @@ -0,0 +1,16 @@ +Source: pscheduler-test-dns64 +Section: net +Priority: optional +Maintainer: perfSONAR developers +Build-Depends: debhelper (>= 10) +Standards-Version: 3.9.8 +Homepage: https://github.com/perfsonar/pscheduler +Vcs-Git: git://github.com/perfsonar/pscheduler +Vcs-Browser: https://github.com/perfsonar/pscheduler/tree/master + +Package: pscheduler-test-dns64 +Architecture: all +Depends: ${misc:Depends}, python3, python3-pscheduler, + pscheduler-server +Description: pScheduler dns64 test + dns64 test class for pScheduler diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/copyright b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/copyright new file mode 100644 index 000000000..fc651d8d1 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/copyright @@ -0,0 +1,23 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: pscheduler-test-dns64 +Source: https://github.com/perfsonar/pscheduler + +Files: * +Copyright: 2020-2023 perfSONAR project +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/rules b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/rules new file mode 100755 index 000000000..db75d9a7e --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#DH_VERBOSE = 1 + +# main packaging script based on dh7 syntax +%: + dh $@ + +DEB_SOURCE_PACKAGE ?= $(strip $(shell egrep '^Source: ' debian/control | cut -f 2 -d ':')) +CLASS ?= $(shell echo $(DEB_SOURCE_PACKAGE) | sed 's/^pscheduler-//; s/-.*//') +NAME ?= $(shell echo $(DEB_SOURCE_PACKAGE) | sed 's/^[^-]*-[^-]*-//') +ROOT ?= $(CURDIR)/debian/$(DEB_SOURCE_PACKAGE) +PYTHON := $(shell which python3) + +override_dh_auto_build: + +override_dh_auto_test: + +override_dh_auto_install: + make -C $(NAME) install \ + PYTHON=$(PYTHON) \ + DOCDIR=$(ROOT)/usr/share/doc/pscheduler/$(CLASS) \ + DESTDIR=$(ROOT)/usr/lib/pscheduler/classes/$(CLASS)/$(NAME) \ + CONFDIR=$(ROOT)/etc/pscheduler/$(CLASS)/$(NAME) + + if [ -f $(CURDIR)/debian/sudoers ]; then \ + install -D -m 0440 $(CURDIR)/debian/sudoers \ + $(ROOT)/etc/sudoers.d/$(DEB_SOURCE_PACKAGE); \ + fi + +override_dh_auto_clean: + make -C $(NAME) clean diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/source/format b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/deb/triggers b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/triggers new file mode 100644 index 000000000..b44d62bb8 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/deb/triggers @@ -0,0 +1 @@ +activate-noawait pscheduler-warmboot diff --git a/pscheduler-test-dns64/dns64/unibuild-packaging/rpm/pscheduler-test-dns64.spec b/pscheduler-test-dns64/dns64/unibuild-packaging/rpm/pscheduler-test-dns64.spec new file mode 100644 index 000000000..89f369bc6 --- /dev/null +++ b/pscheduler-test-dns64/dns64/unibuild-packaging/rpm/pscheduler-test-dns64.spec @@ -0,0 +1,68 @@ +# +# RPM Spec for pScheduler dns64 Test +# + +# +# Development Order #1: +# +# This file is significant for building the test into pScheduler. +# If additional libraries or parts of pScheduler are required, +# they should be added here after line 25. +# + +%define short dns64 +%define perfsonar_auto_version 5.2.0 +%define perfsonar_auto_relnum 0.a1.0 + +Name: pscheduler-test-%{short} +Version: %{perfsonar_auto_version} +Release: %{perfsonar_auto_relnum}%{?dist} + +Summary: dns64 test for pScheduler +BuildArch: noarch +License: Apache 2.0 +Group: Unspecified + +Source0: %{short}-%{version}.tar.gz + +Provides: %{name} = %{version}-%{release} + +# Include all required libraries here +Requires: pscheduler-server +Requires: %{_pscheduler_python}-pscheduler >= 1.3 +Requires: rpm-post-wrapper + +BuildRequires: pscheduler-rpm + + +%description +dns64 test class for pScheduler + + +%prep +%setup -q -n %{short}-%{version} + + +%define dest %{_pscheduler_test_libexec}/%{short} + +%build +make \ + PYTHON=%{_pscheduler_python} \ + DESTDIR=$RPM_BUILD_ROOT/%{dest} \ + install + + + +%post +rpm-post-wrapper '%{name}' "$@" <<'POST-WRAPPER-EOF' +pscheduler internal warmboot +POST-WRAPPER-EOF + + +%postun +pscheduler internal warmboot + + +%files +%defattr(-,root,root,-) +%{dest} diff --git a/pscheduler-test-dns64/dns64/validate.py b/pscheduler-test-dns64/dns64/validate.py new file mode 100644 index 000000000..6b243a309 --- /dev/null +++ b/pscheduler-test-dns64/dns64/validate.py @@ -0,0 +1,137 @@ +# +# Validator for a pScheduler test and its result. +# + +# IMPORTANT: +# +# 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_standard_template +from pscheduler import json_validate +import pscheduler + +MAX_SCHEMA = 1 + +log = pscheduler.Log(prefix='test-dns64') + +# +# Test Specification +# + +# NOTE: A large dictionary of existing, commonly-used datatypes used +# throughout pScheduler is defined in +# pscheduler/python-pscheduler/pscheduler/pscheduler/jsonval.py. +# Please use those where possible. + +SPEC_SCHEMA = { + + "local": { + + # Define any local types used in the spec here + + }, + + "versions": { + + # Initial version of the specification + "1": { + "type": "object", + # schema, host, host-node, and timeout are standard and + # should be included in most single-participant tests. + "properties": { + "schema": { "$ref": "#/pScheduler/Cardinal", "enum": [ 1 ] }, + "query": { "$ref": "#/pScheduler/URL" }, + "nameserver": { "$ref": "#/pScheduler/Host" }, + "host": { "$ref": "#/pScheduler/Host" }, + "host-node": { "$ref": "#/pScheduler/Host" }, + "translation-prefix": { "$ref": "#/pScheduler/String" }, + "timeout": { "$ref": "#/pScheduler/Duration" }, + }, + # If listed here, these parameters MUST be in the test spec. + "required": [ + "query" + ], + # Treat other properties as acceptable. This should + # ALWAYS be false. + "additionalProperties": False + }, + + # Second and later versions of the specification + # "2": { + # "type": "object", + # "properties": { + # "schema": { "type": "integer", "enum": [ 2 ] }, + # ... + # }, + # "required": [ + # "schema", + # ... + # ], + # "additionalProperties": False + #}, + + } + +} + + + +def spec_is_valid(json): + + (valid, errors) = json_validate_from_standard_template(json, SPEC_SCHEMA) + #return json_validate(json, SPEC_SCHEMA, max_schema=MAX_SCHEMA) + log.debug(json) + + if not valid: + return (valid, errors) + + return (valid, errors) + + + +# +# Test Result +# + +RESULT_SCHEMA = { + + "local": { + # Define any local types here. + }, + + "versions": { + + "1": { + "type": "object", + "properties": { + "schema": { "type": "integer", "enum": [ 1 ] }, + "succeeded": { "$ref": "#/pScheduler/Boolean" }, + "time": { "$ref": "#/pScheduler/Duration" }, + "ipv4": { + "type": "array", + "items": { "$ref": "#/pScheduler/IPv4" }, + "minItems" : 0 + }, + "ipv6": { + "type": "array", + "items": {"$ref": "#/pScheduler/IPv6"}, + "minItems": 0 + }, + "translated": { "$ref": "#/pScheduler/Boolean" }, + }, + "required": [ + "succeeded", + "time", + ], + "additionalProperties": False + } + + } + +} + + +def result_is_valid(json): + return json_validate_from_standard_template(json, RESULT_SCHEMA) diff --git a/pscheduler-tool-pydns64/Makefile b/pscheduler-tool-pydns64/Makefile new file mode 100644 index 000000000..413b49797 --- /dev/null +++ b/pscheduler-tool-pydns64/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for Any Package +# + +AUTO_TARBALL := 1 + +include unibuild/unibuild.make diff --git a/pscheduler-tool-pydns64/README.md b/pscheduler-tool-pydns64/README.md new file mode 100644 index 000000000..6a4417fb0 --- /dev/null +++ b/pscheduler-tool-pydns64/README.md @@ -0,0 +1 @@ +Documentation for writing a tool for pScheduler can be found in the main directory of the PDK in the file tool.md (https://github.com/perfsonar/pscheduler/blob/pdk-docs/scripts/PDK/tool.md) diff --git a/pscheduler-tool-pydns64/pydns64/Makefile b/pscheduler-tool-pydns64/pydns64/Makefile new file mode 100644 index 000000000..ca806235d --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/Makefile @@ -0,0 +1,28 @@ +# +# Makefile for any tool class +# + +NAME=pydns64 + +FILES=\ + can-run \ + duration \ + enumerate \ + participant-data \ + run \ + merged-results \ + + + +install: $(FILES) +ifndef DESTDIR + @echo No DESTDIR specified for installation + @false +endif + mkdir -p $(DESTDIR) + install -m 555 $(FILES) $(DESTDIR) + + + +clean: + rm -f $(TO_CLEAN) *~ diff --git a/pscheduler-tool-pydns64/pydns64/can-run b/pscheduler-tool-pydns64/pydns64/can-run new file mode 100644 index 000000000..a769020f0 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/can-run @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +# +# Development Order #3: +# +# This file will determine if this tool can run a test based on a test spec. +# +# Be sure to edit line 19, inserting the names of the tests the tool +# should be compatible with. +# + +# exit statuses should be different based on error + +import pscheduler + +json = pscheduler.json_load(exit_on_error=True); + +try: + if json['type'] != 'dns64': + pscheduler.succeed_json({ + "can-run": False, + "reasons": [ "Unsupported test type" ] + }) +except KeyError: + pscheduler.succeed_json({ + "can-run": False, + "reasons": [ "Missing test type" ] + }) + + + +pscheduler.succeed_json({ "can-run": True }) diff --git a/pscheduler-tool-pydns64/pydns64/duration b/pscheduler-tool-pydns64/pydns64/duration new file mode 100644 index 000000000..105053ebf --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/duration @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +# +# Development Order #4: +# +# Determine the duration of a specified test. +# + +# +# TODO: This is a bare-bones, unreliable implementation that should be +# used only for testing. +# + +import datetime + +import pscheduler + +json = pscheduler.json_load(exit_on_error=True); + +try: + timeout_iso = json['spec']['timeout'] +except KeyError: + timeout_iso = 'PT10S' +timeout = pscheduler.iso8601_as_timedelta(timeout_iso) + +pscheduler.succeed_json({ + "duration": pscheduler.timedelta_as_iso8601( timeout ) + }) diff --git a/pscheduler-tool-pydns64/pydns64/enumerate b/pscheduler-tool-pydns64/pydns64/enumerate new file mode 100644 index 000000000..147a725e6 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/enumerate @@ -0,0 +1,28 @@ +#!/bin/sed -e 1d;/^#/d + +# +# Development Order #2: +# +# This JSON data describes the tool, and will be shown when 'pscheduler +# plugins tools' is run. This is the first file which should be edited. +# +# Be sure to edit line 19, as this determines what tests the tool is +# compatible with. +# + +{ + "schema": 1, + + "name": "pydns64", + "description": "Tool to validate DNS64 queries", + "version": "1.0", + "tests": [ "dns64" ], + + "preference": 0, + + "maintainer": { + "name": "perfSONAR Development Team", + "email": "perfsonar-developer@internet2.edu", + "href": "http://www.perfsonar.net" + } +} diff --git a/pscheduler-tool-pydns64/pydns64/error-example-spec.json b/pscheduler-tool-pydns64/pydns64/error-example-spec.json new file mode 100644 index 000000000..cd18e6878 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/error-example-spec.json @@ -0,0 +1,17 @@ +{ + "test": { + "type": "dns64", + "spec": { + "query": "ip4.me", + "timeout": "PT10S", + "schema": 1 + } + }, + "schema": 1, + "tool": "pydns64", + "href": "https://localhost.localdomain/pscheduler/tasks/d0035107-6ef0-4cc7-83b4-19367b502bfc", + "schedule": { + "slip": "PT5M" + } +} + diff --git a/pscheduler-tool-pydns64/pydns64/example-test-spec.json b/pscheduler-tool-pydns64/pydns64/example-test-spec.json new file mode 100644 index 000000000..7675309c3 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/example-test-spec.json @@ -0,0 +1,19 @@ +{ + "test": { + "type": "dns64", + "spec": { + "query": "v4onlytest.notonthe.net", + "nameserver": "2001:4860:4860::64", + "translation-prefix": "64:ff9b::/96", + "timeout": "PT15S", + "schema": 1 + } + }, + "schema": 1, + "tool": "pydns64", + "href": "https://localhost.localdomain/pscheduler/tasks/d0035107-6ef0-4cc7-83b4-19367b502bfc", + "schedule": { + "slip": "PT5M" + } +} + diff --git a/pscheduler-tool-pydns64/pydns64/merged-results b/pscheduler-tool-pydns64/pydns64/merged-results new file mode 100644 index 000000000..9397ecea0 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/merged-results @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# +# Merge the participant results of a run by this tool into a +# test-standard result. +# Note that this method will be given results for all participants +# whether their runs succeeded or failed and should return a result +# that indicates whether or not the run as a whole failed. This +# allows multi-participant tools to return a successful result even if +# one of the participants failed but there's enough data to do so. +# + +import pscheduler + +input = pscheduler.json_load(exit_on_error=True); + +try: + # Single-participant tests usually use the result generated by the + # tool's 'run' method. Multiple-participant tests would go over + # the result from all participants and produce a suitable result. + result = input['results'][0]['result'] +except (IndexError, KeyError) as ex: + result = { + 'succeeded': False, + 'error': "Error in participant data: {}".format(str(ex)) + } + +pscheduler.succeed_json(result) diff --git a/pscheduler-tool-pydns64/pydns64/participant-data b/pscheduler-tool-pydns64/pydns64/participant-data new file mode 100644 index 000000000..521bf47d1 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/participant-data @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 +# +# Return participant-specific data for a run +# + +import pscheduler + +json = pscheduler.json_load(exit_on_error=True) + +# In this case, nothing of interest. +print("{}") + +pscheduler.succeed() diff --git a/pscheduler-tool-pydns64/pydns64/run b/pscheduler-tool-pydns64/pydns64/run new file mode 100755 index 000000000..58112eb04 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/run @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 + +# +# Development Order #5: +# +# This is the meat and bones of the tool, where the actual desired +# commands or operation will be run. The results are then recorded +# and added to the 'results' JSON data, which will then be sent +# back to the test. Both system and api are able to be used here. +# + +import datetime +import subprocess +import json +import sys +import time +import ipaddress +from ipaddress import IPv6Address, IPv4Address +from ipaddress import IPv6Network + +import pscheduler +import dns.resolver + + +log = pscheduler.Log(prefix='tool-pydns64', quiet=True) + +# from stdin +input = pscheduler.json_load(exit_on_error=True) +resolver = dns.resolver.Resolver() + +# Take input from test spec +try: + query = input['test']['spec']['query'] +except KeyError: + pscheduler.fail('missing data in input') + +try: + resolver.nameservers = [input['test']['spec']['nameserver']] +except KeyError: + pass # Not there? Don't care. + +timeout_iso = input['test']['spec'].get("timeout", "PT10S") +timeout = pscheduler.timedelta_as_seconds( pscheduler.iso8601_as_timedelta(timeout_iso) ) + +prefix = input['test']['spec'].get("translation-prefix", "64:ff9b::/96") + +# Run the actual task here: + +start_time = datetime.datetime.now() +succeeded = False +error = '' +diags = '' +ip4answers = None +ip6answers = None +ip4result_list = None +ip6result_list = None +translated = True + +# do test here + +try: + ip4answers = resolver.resolve(query, 'A') + ip6answers = resolver.resolve(query, 'AAAA' ) + succeeded = True +except dns.exception.Timeout: + error = 'Timeout' +except dns.resolver.NoAnswer: + if ip4answers: + error = 'No IPv6 answer' + else: + error = 'No IPv4 answer, aborting' +except dns.resolver.NXDOMAIN: + error = 'Domain does not exist' + +end_time = datetime.datetime.now() + +if ip4answers is None: + ip4result_list = [] +else: + ip4result_list = sorted(list(ip4answers)) + +if ip6answers is None: + ip6result_list = [] +else: + ip6result_list = sorted(list(ip6answers)) + +# Check to see if results are correctly translated +if len(ip4result_list) == 0 or len(ip6result_list) == 0: + translated = False +elif len(ip4result_list) != len(ip6result_list): + translated = False +else: + for index, ip in enumerate(ip6result_list): + ipaddr = IPv6Address(ip) + if ipaddr not in IPv6Network(prefix): + translated = False + break + else: + if IPv4Address(ip4result_list[index]).packed != ipaddr.packed[-4:]: + translated = False + break + + +# Organize results into json data +results = { + 'succeeded': succeeded, + 'result': { + 'schema': 1, + 'time': pscheduler.timedelta_as_iso8601( end_time - start_time), + 'succeeded': succeeded, + 'translated': translated + }, + 'error': error, + 'diags': diags } + +results [ 'result' ][ 'ipv4' ] = [str(ip) for ip in ip4result_list] +results [ 'result' ][ 'ipv6' ] = [str(ip) for ip in ip6result_list] + +pscheduler.succeed_json(results) + diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/changelog b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/changelog new file mode 100644 index 000000000..cdf7dcf25 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/changelog @@ -0,0 +1,12 @@ +pscheduler-tool-pydns64 (5.2.0~a1.0-1) perfsonar-5.2-snapshot; urgency=low + + * New upstream version. + + -- perfSONAR developers Tue, 11 Jun 2024 18:29:36 +0200 + +pscheduler-tool-pydns64 (5.1.0~a1.0-1) perfsonar-5.1-snapshot; urgency=low + + * Initial release + + -- perfSONAR developers Tue, 13 Oct 2020 17:50:44 +0000 + diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/compat b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/compat new file mode 100644 index 000000000..f599e28b8 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/compat @@ -0,0 +1 @@ +10 diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/control b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/control new file mode 100644 index 000000000..32d306fb8 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/control @@ -0,0 +1,16 @@ +Source: pscheduler-tool-pydns64 +Section: net +Priority: optional +Maintainer: perfSONAR developers +Build-Depends: debhelper (>= 10) +Standards-Version: 3.9.8 +Homepage: https://github.com/perfsonar/pscheduler +Vcs-Git: git://github.com/perfsonar/pscheduler +Vcs-Browser: https://github.com/perfsonar/pscheduler/tree/master + +Package: pscheduler-tool-pydns64 +Architecture: all +Depends: ${misc:Depends}, python3, python3-pscheduler, + pscheduler-server, pscheduler-test-pydns64 +Description: pScheduler pydns64 tool + pydns64 tool class for pScheduler diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/copyright b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/copyright new file mode 100644 index 000000000..5f5add890 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/copyright @@ -0,0 +1,23 @@ +Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: pscheduler-tool-pydns64 +Source: https://github.com/perfsonar/pscheduler + +Files: * +Copyright: 2020-2023 perfSONAR project +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache version 2.0 license + can be found in "/usr/share/common-licenses/Apache-2.0". diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/rules b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/rules new file mode 100755 index 000000000..db75d9a7e --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/rules @@ -0,0 +1,33 @@ +#!/usr/bin/make -f +# See debhelper(7) (uncomment to enable) +# output every command that modifies files on the build system. +#DH_VERBOSE = 1 + +# main packaging script based on dh7 syntax +%: + dh $@ + +DEB_SOURCE_PACKAGE ?= $(strip $(shell egrep '^Source: ' debian/control | cut -f 2 -d ':')) +CLASS ?= $(shell echo $(DEB_SOURCE_PACKAGE) | sed 's/^pscheduler-//; s/-.*//') +NAME ?= $(shell echo $(DEB_SOURCE_PACKAGE) | sed 's/^[^-]*-[^-]*-//') +ROOT ?= $(CURDIR)/debian/$(DEB_SOURCE_PACKAGE) +PYTHON := $(shell which python3) + +override_dh_auto_build: + +override_dh_auto_test: + +override_dh_auto_install: + make -C $(NAME) install \ + PYTHON=$(PYTHON) \ + DOCDIR=$(ROOT)/usr/share/doc/pscheduler/$(CLASS) \ + DESTDIR=$(ROOT)/usr/lib/pscheduler/classes/$(CLASS)/$(NAME) \ + CONFDIR=$(ROOT)/etc/pscheduler/$(CLASS)/$(NAME) + + if [ -f $(CURDIR)/debian/sudoers ]; then \ + install -D -m 0440 $(CURDIR)/debian/sudoers \ + $(ROOT)/etc/sudoers.d/$(DEB_SOURCE_PACKAGE); \ + fi + +override_dh_auto_clean: + make -C $(NAME) clean diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/source/format b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/source/format new file mode 100644 index 000000000..163aaf8d8 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/triggers b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/triggers new file mode 100644 index 000000000..b44d62bb8 --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/deb/triggers @@ -0,0 +1 @@ +activate-noawait pscheduler-warmboot diff --git a/pscheduler-tool-pydns64/pydns64/unibuild-packaging/rpm/pscheduler-tool-pydns64.spec b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/rpm/pscheduler-tool-pydns64.spec new file mode 100644 index 000000000..dfd879bbc --- /dev/null +++ b/pscheduler-tool-pydns64/pydns64/unibuild-packaging/rpm/pscheduler-tool-pydns64.spec @@ -0,0 +1,58 @@ +# +# RPM Spec for pScheduler pydns64 Tool +# + +# +# Development Order #1: +# +# This file is significant for buildling the tool into pScheduler. +# If additional libraries or parts of pScheduler are required, +# they should be added here (line 25). +%define short pydns64 +%define perfsonar_auto_version 5.2.0 +%define perfsonar_auto_relnum 0.a1.0 + +Name: pscheduler-tool-%{short} +Version: %{perfsonar_auto_version} +Release: %{perfsonar_auto_relnum}%{?dist} + +Summary: pydns64 tool class for pScheduler +BuildArch: noarch +License: Apache 2.0 +Group: Unspecified + +Source0: %{short}-%{version}.tar.gz + +Provides: %{name} = %{version}-%{release} + +# Include all required libraries here +Requires: pscheduler-server +Requires: %{_pscheduler_python}-pscheduler +Requires: rpm-post-wrapper + +BuildRequires: pscheduler-rpm + +%description +pydns64 tool class for pScheduler + +%prep +%setup -q -n %{short}-%{version} + +%define dest %{_pscheduler_tool_libexec}/%{short} + +%build +make \ + DESTDIR=$RPM_BUILD_ROOT/%{dest} \ + install + +%post +rpm-post-wrapper '%{name}' "$@" <<'POST-WRAPPER-EOF' +pscheduler internal warmboot +POST-WRAPPER-EOF + +%postun +pscheduler internal warmboot + +%files +%defattr(-,root,root,-) +%{dest} diff --git a/unibuild-order b/unibuild-order index 5a2e6f7a0..d6ab9f788 100755 --- a/unibuild-order +++ b/unibuild-order @@ -157,6 +157,7 @@ pscheduler-test-clock pscheduler-test-dhcp --bundle extras pscheduler-test-disk-to-disk --bundle extras pscheduler-test-dns +pscheduler-test-dns64 pscheduler-test-dot1x --bundle extras pscheduler-test-http pscheduler-test-latency @@ -234,6 +235,7 @@ pscheduler-tool-ping pscheduler-tool-psclock pscheduler-tool-pstimer pscheduler-tool-psurl --bundle obsolete +pscheduler-tool-pydns64 pscheduler-tool-pysnmp --bundle snmp define(HAVE_S3_BENCHMARK,ifelse(HAVE_GOLANG,0,0,