diff --git a/compose/limits.conf b/compose/limits.conf
new file mode 100644
index 0000000..6f5d014
--- /dev/null
+++ b/compose/limits.conf
@@ -0,0 +1,309 @@
+{
+ "#": "-------------------------------------------------------------------",
+ "#": " PSCHEDULER LIMIT CONFIGURATION ",
+ "#": " ",
+ "#": "This file is a sample which contains fairly sane defaults. It ",
+ "#": "should be customized according to the needs of your site. ",
+ "#": "-------------------------------------------------------------------",
+
+ "schema": 3,
+
+ "#": "-------------------------------------------------------------------",
+ "#": "IDENTIFIERS: WHO'S ASKING? ",
+ "#": " ",
+ "#": "These identify who's asking to run the test. One requester can ",
+ "#": "map to zero or more identifiers. ",
+ "#": "-------------------------------------------------------------------",
+
+ "identifiers": [
+ {
+ "name": "everybody",
+ "description": "An identifier that always identifies",
+ "type": "always",
+ "data": { }
+ },
+ {
+ "name": "local-interfaces",
+ "description": "Requests coming from this system",
+ "type": "localif",
+ "data": { }
+ },
+ {
+ "#": "NOTE: This only works if the host can resolve DNS",
+ "#": "on the public Internet.",
+
+ "name": "bogons",
+ "description": "Bogon/Martian IPv4 addresses without private networks",
+ "type": "ip-cymru-bogon",
+ "data": {
+ "exclude": [
+ "10.0.0.0/8",
+ "127.0.0.0/8",
+ "172.16.0.0/12",
+ "192.168.0.0/16",
+ "169.254.0.0/16",
+ "::/8",
+ "fe80::/10"
+ ],
+ "timeout": "PT1S",
+ "fail-result": false
+ }
+ },
+ {
+ "name": "hackers",
+ "description": "Blocks that have tried to hack us (actually TEST-NET-2)",
+ "type": "ip-cidr-list",
+ "data": {
+ "cidrs": [ "198.51.100.0/24" ]
+ }
+ }
+ ],
+
+
+ "#": "-------------------------------------------------------------------",
+ "#": "CLASSIFIERS: HOW DO WE CLASSIFY THE IDENTIFIERS? ",
+ "#": " ",
+ "#": "These collect identifiers into groups. ",
+ "#": "-------------------------------------------------------------------",
+
+ "classifiers": [
+ {
+ "name": "default",
+ "description": "Everybody",
+ "identifiers": [ "everybody" ]
+ },
+ {
+ "name": "friendlies",
+ "description": "Identifiers we find friendly",
+ "identifiers": [ "local-interfaces" ]
+ },
+ {
+ "name": "hostiles",
+ "description": "Identifiers we find unfriendly",
+ "identifiers": [ "hackers", "bogons" ]
+ }
+ ],
+
+
+ "#": "-------------------------------------------------------------------",
+ "#": "REWRITE: WHAT CHANGES ARE MADE TO INCOMING TASKS? ",
+ "#": " ",
+ "#": "This is a jq transform that makes changes to incoming tasks prior ",
+ "#": "to limit enforcement. ",
+ "#": "-------------------------------------------------------------------",
+
+ "rewrite": {
+ "script": [
+ "import \"pscheduler/iso8601\" as iso;",
+
+ "# This does nothing but is recommended so the statements below",
+ "# all begin with |. (This makes editing easier.)",
+ ".",
+
+ "# Hold this for use later.",
+ "| .test.type as $testtype",
+
+ "# Make some tests run a minimum of 5 seconds",
+ "| if ( [\"idle\", \"idlebgm\", \"idleex\", \"latency\", \"latencybg\", \"throughput\" ]",
+ " | contains([$testtype]) )",
+ " and .test.spec.duration != null",
+ " and iso::duration_as_seconds(.test.spec.duration) < 5",
+ " then",
+ " .test.spec.duration = \"PT5S\"",
+ " | change(\"Bumped duration to 5-second minimum\")",
+ " else",
+ " .",
+ " end",
+
+ "# The end. (This takes care of the no-comma-at-end problem)"
+ ]
+ },
+
+
+
+ "#": "-------------------------------------------------------------------",
+ "#": "LIMITS: WHAT ARE THE RESTRICTIONS? ",
+ "#": " ",
+ "#": "These are comparisons made against the type of test being proposed,",
+ "#": "the paramaters for the run and when it is proposed to be run. ",
+ "#": "-------------------------------------------------------------------",
+
+ "limits": [
+ {
+ "name": "always",
+ "description": "Always passes",
+ "type": "pass-fail",
+ "data": {
+ "pass": true
+ }
+ },
+ {
+ "name": "never",
+ "description": "Always fails",
+ "type": "pass-fail",
+ "data": {
+ "pass": false
+ }
+ },
+ {
+ "#": "This prevents denial of service by scheduling long tasks.",
+ "name": "idleex-default",
+ "description": "Default limits for idleex",
+ "type": "test",
+ "data": {
+ "test": "idleex",
+ "limit": {
+ "duration": {
+ "range": {
+ "lower": "PT1S",
+ "upper": "PT2S"
+ }
+ }
+ }
+ }
+ },
+
+ {
+ "name": "innocuous-tests",
+ "description": "Tests considered harmless",
+ "type": "test-type",
+ "data": {
+ "#": "Resource hogs, which will be inverted below",
+ "types": [ "throughput", "idleex" ]
+ },
+ "invert": true
+ },
+ {
+ "name": "throughput-default-time",
+ "description": "Throughput time limits",
+ "type": "test",
+ "data": {
+ "test": "throughput",
+ "limit": {
+ "duration": {
+ "range": {
+ "lower": "PT5S",
+ "upper": "PT60S"
+ }
+ },
+ "udp":{
+ "match":false
+ }
+ }
+ }
+ },
+ {
+ "name": "throughput-default-udp",
+ "description": "Throughput UDP limits",
+ "type": "test",
+ "data": {
+ "test": "throughput",
+ "limit": {
+ "bandwidth": {
+ "range": {
+ "lower": "1",
+ "upper": "50M"
+ }
+ },
+ "duration": {
+ "range": {
+ "lower": "PT5S",
+ "upper": "PT60S"
+ }
+ },
+ "udp":{
+ "match":true
+ }
+ }
+ }
+ }
+ ],
+
+
+ "#": "-------------------------------------------------------------------",
+ "#": "APPLICATIONS: TO WHOM DO WE APPLY THE LIMITS? ",
+ "#": " ",
+ "#": "These are processed in order until one passes all of the ",
+ "#": "requirements. The run will be rejected if one fails with ",
+ "#": "stop-on-failure set to true or none of them passes. ",
+ "#": "-------------------------------------------------------------------",
+
+ "applications": [
+ {
+ "description": "Hosts we don't want running any tests",
+ "classifier": "hostiles",
+ "apply": [
+ { "require": "all", "limits": [ "never" ] }
+ ],
+ "stop-on-failure": true
+ },
+ {
+ "description": "Hosts we trust to do everything",
+ "classifier": "friendlies",
+ "apply": [
+ { "require": "all", "limits": [ "always" ] }
+ ]
+ },
+ {
+ "description": "Defaults applied to non-friendly hosts",
+ "classifier": "default",
+ "apply": [
+ {
+ "require": "any",
+ "limits": [
+ "innocuous-tests",
+ "throughput-default-time",
+ "throughput-default-udp",
+ "idleex-default"
+ ]
+ }
+ ]
+ }
+ ],
+
+
+ "#": "-------------------------------------------------------------------",
+ "#": "PRIORITY: HOW DO WE PRIORITIZE RUNS OF TASKS? ",
+ "#": " ",
+ "#": "This is a jq transform that examines a proposed run of a task and ",
+ "#": "produces an integer value indicating its priority. If this is not ",
+ "#": "present, the neutral priority value of 0 will be used. ",
+ "#": "-------------------------------------------------------------------",
+
+ "priority": {
+ "script": [
+ ".",
+
+ "# Start with the lower of the requested and default priorities",
+ "| set(default; \"Initial priority\")",
+
+ "# This is where decisions to change priority would be made,",
+ "# as in this commented-out example:",
+
+ "# # Friendly requesters get a small bump in priority.",
+ "# | if classifiers_has(\"friendlies\")",
+ "# then adjust(5; \"Friendly requester\") else . end",
+
+ "# The two blocks below implement recommended standard behavior.",
+
+ "# If the requested priority was lower than what we came up",
+ "# with, force that.",
+ "| if requested != null and requested < priority",
+ " then set(requested; \"Lower requested priority\")",
+ " else . end",
+
+ "# Allow at least the requested priority for those who are",
+ "# allowed to do so. Do this last in case things done",
+ "# above push the priority higher than was requested",
+ "| if requested != null",
+ " and requested > default",
+ " and requested > priority",
+ " and classifiers_has(\"priority-positive\")",
+ " then set(requested; \"Higher requested priority\")",
+ " else . end",
+
+ "# The end. (This takes care of the no-comma-at-end problem)"
+ ]
+ }
+
+}
diff --git a/compose/lsregistrationdaemon.conf b/compose/lsregistrationdaemon.conf
new file mode 100644
index 0000000..5d3322c
--- /dev/null
+++ b/compose/lsregistrationdaemon.conf
@@ -0,0 +1,149 @@
+#############################
+# All the information you provide on this file will be sent, recorded and made
+# publicly available on the global perfSONAR Lookup Service. For privacy
+# reasons, we recommend you use a role or group name and related email address
+# to be registered. Any personal information you would provide will be on your
+# own responsibility and will by no means represent an obligation for the
+# perfSONAR project. See our Privacy Policy for more information:
+# https://www.perfsonar.net/about/privacy-policy/
+#############################
+##Optional Location information
+
+## Name of site where host is running
+#site_name Acme Co.
+
+## Administrative domain of host in DNS format
+#domain mydomain.example
+
+## A keyword identifying a project or community in which the host is involved
+## You may list multiple of these projects on separate lines.
+#site_project MyProject1
+#site_project MyProject2
+
+## City where host is running
+#city Berkeley
+
+## Two-letter abbreviation for State/Province/Region where host is running
+#region CA
+
+## Two-letter ISO country code for country where host is running
+#country US
+
+## Postal code for location where host is running
+#zip_code 94720
+
+## Latitude for location here host is running
+#latitude 37.5
+
+## Longitude for location here host is running
+#longitude 121.7469
+#############################
+
+## The URL of a lookup service in which to register. If not set, will choose
+## from global list based on closest RTT. use this to set a private lookup service.
+#ls_instance http://private-ls:8090/lookup/records
+## configure how long the record must be valid in the LS
+#ls_lease_duration 7200
+
+## The interval between service checks to see if a service is still running.
+check_interval 3600 # In seconds
+
+## Set this if you don't want private IPs ignored
+allow_internal_addresses 0
+
+## Set to 1 if you want to sign records
+add_signature 0
+#signing_key /path/to/key
+
+#
+# certificate_name testhost_ps_certificate
+# certificate_path /path/to/certificate
+#
+
+
+#
+# name pS Admin
+# email admin@organization.edu
+#
+
+## Templates containing list of common parameters that services will use
+
+ autodiscover_addresses 1
+# primary_interface eth0
+
+
+
+ autodiscover_addresses 1
+# primary_interface eth1
+
+
+
+ autodiscover_addresses 1
+# primary_interface eth2
+
+
+## List of services to register
+
+
+ is_local 1
+ autodiscover 1
+ autodiscover_interfaces 1
+
+ ####
+ # If you want to publish that only certain tests are allowed on certain interfaces
+ # then you need to first do the following:
+ # 1. Set autodiscover_interfaces to 0 above
+ # 2. List each interface you want published in an interface block
+ # Inside the interface block you can define what tests you want run a few different
+ # ways. See examples below:
+ #
+ ##
+ ## This interface will only allow throughput and trace tests. It explicitly defines
+ ## the tests it supports.
+ #
+ # if_name eth0
+ # disable_autodiscover_tests 1
+ # test throughput
+ # test trace
+ #
+ #
+ ## This interface will allow any type of test EXCEPT throughput. It will
+ ## contact pscheduler for the list of installed plug-ins and will everything
+ ## except throughput. You can define disable_test multiple times to disable multiple
+ ## tests
+ ## the tests it supports.
+ #
+ # # don't run throughput tests
+ # if_name eth1
+ # disable_test throughput
+ #
+
+
+ inherits local_latency_service
+ type owamp
+
+
+ inherits local_latency_service
+ type twamp
+
+
+ inherits local_web_service
+ type ma
+ http_port 80
+ https_port 443
+ url_path /esmond/perfsonar/archive
+ service_version esmond-2.0
+ autodiscover_tests 0
+
+
+ inherits local_web_service
+ type pscheduler
+ https_port 443
+ url_path /pscheduler
+ service_version pscheduler-1.0
+ autodiscover_tests 1
+ autodiscover_tools 1
+
+
+
+
diff --git a/docker-compose.systemd.yml b/docker-compose.systemd.yml
index 49e83cb..fd46934 100644
--- a/docker-compose.systemd.yml
+++ b/docker-compose.systemd.yml
@@ -14,4 +14,8 @@ services:
- /tmp
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
- tty: true
\ No newline at end of file
+ - ./compose/psconfig/pscheduler-agent.json:/etc/perfsonar/psconfig/pscheduler-agent.json
+ - ./compose/psconfig/pscheduler-agent-logger.conf:/etc/perfsonar/psconfig/pscheduler-agent-logger.conf
+ - ./compose/lsregistrationdaemon.conf:/etc/perfsonar/lsregistrationdaemon.conf
+ - ./compose/limits.conf:/etc/pscheduler/limits.conf
+ tty: true
diff --git a/docker-compose.yml b/docker-compose.yml
index 367cd52..655706d 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -5,4 +5,6 @@ services:
network_mode: "host"
restart: on-failure
volumes:
- - ./compose/psconfig:/etc/perfsonar/psconfig
\ No newline at end of file
+ - ./compose/psconfig:/etc/perfsonar/psconfig
+ - ./compose/lsregistrationdaemon.conf:/etc/perfsonar/lsregistrationdaemon.conf
+ - ./compose/limits.conf:/etc/pscheduler/limits.conf
\ No newline at end of file