Welcome to pyfarm.master’s documentation!¶
This package contains the models, web interface, APIs, and backend components necessary to scheduler and allocate jobs on PyFarm.
Contents
Commands¶
Standard Commands¶
pyfarm-create-tables¶
usage: pyfarm-tables [-h] [--echo] [--drop-all] [--no-create-tables]
Creates PyFarm's tables
optional arguments:
-h, --help show this help message and exit
--echo If provided then echo the SQL queries being made
--drop-all If provided all tables will be dropped from the database
before they are created.
--no-create-tables If provided then no tables will be created.
Development Commands¶
pyfarm-master¶
usage: pyfarm-master [-h] [--drop-all] [--create-all]
[--confirm-drop CONFIRM_DROP]
[--allow-agent-loopback-addresses]
optional arguments:
-h, --help show this help message and exit
--drop-all, -D drop the existing tables before starting
--create-all, -C create all tables before starting
--confirm-drop CONFIRM_DROP
--allow-agent-loopback-addresses
Configuration Files¶
Below are the configuration files for this subproject. These files are installed along side the source code when the package is installed. These are only the defaults however, you can always override these values in your own environment. See the Configuration object documentation for more detailed information.
Master¶
The below is the current configuration file for the agent. This
file lives at pyfarm/master/etc/master.yml
in the source tree.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | # Configures if the underlying Flask application and other libraries
# should run in debug mode.
#
# **Production Note**: This value should always be false.
debug: true
# Enables verbose output of loggers associated with the
# job queue.
debug_queue: false
# The URL to access the database. For debugging and development
# a local SQLite database is used but for production other databases,
# such as MySQL or PostgreSQL which PyFarm runs tests against, should
# be used.
#
# For more information on the expected format of this variable
# see SQLAlchemy's documentation:
# https://sqlalchemy.readthedocs.org/en/latest/core/engines.html#database-urls
database: "sqlite:///pyfarm.sqlite"
# Where to store runtime statistics. Same format as "database"
statistics_database: "sqlite:///pyfarm-statistics.sqlite"
# The broker that PyFarm's scheduler should use. For debugging and
# development running Redis is the simplest. For large deployments, or
# to understand the format of this variable, see:
# http://celery.readthedocs.org/en/latest/configuration.html#broker-url
scheduler_broker: "redis://"
# The URL the master is running on. This is used to form internal
# urls and other information.
base_url: http://127.0.0.1:5000/
# The name of this render farm, normally this can remain the default value. If
# you're running multiple farms this allows you to only accept agents to your
# master that match your current farm name.
farm_name: ""
# The secret key which is used by several components of Flask
# for form validation, salting of secrets, etc.
#
# **Production Note**: This value should be random, consistent between
# frontends, and kept secret. Do not use the value below for
# production.
secret_key: pyfarm
# The key used for signing the csrf token.
#
# **Production Note**: This value should be random, consistent between
# frontends, and kept secret. Do not use the value below for
# production.
csrf_session_key: pyfarm
# The prefix of the URL from which the API will operate on. This should
# not generally be changed unless you are operating different versions
# of the API at the same time from one web server.
api_prefix: /api/v1
# The URL template we use to communicate with the agent.
agent_api_url_template: http://{host}:{port}/api/v1
# Enables or disable the login functionality. This can be used when
# debugging or doing development but should not be changed for
# production.
login_disabled: false
# The amount of time the 'remeber me' cookie should persist. The keys
# and values here are passed into a `timedelta` object as keywords.
cookie_duration:
hours: 16
# When true json output from the APIs will be reformatted to
# be more human readable.
pretty_json: false
# When true all SQLAlchemy queries will be echoed. This is useful
# for debugging the SQL statements being run and to get an idea of
# what the underlying ORM may be doing.
echo_sql: false
# When true the application will automatically create users in
# PyFarm's database if they do not exist already. Setting this
# to false will cause an exception to be raised if the user in
# question does not exist.
autocreate_users: true
# When autocreating users, use this email address as a template. For example:
# "{username}@example.com"
# Not setting this value and setting `autocreate_users` to true will result
# in a users's email address not being set on a newly created user.
autocreate_user_email: null
# When provided an integer this many seconds will elapse after a job
# has completed before it is deleted.
default_job_delete_time: null
# The format for timestamps in the user interface.
timestamp_format: "YYYY-MM-DD HH:mm:ss"
# The directory to store updates for agents. This will use `temp` above
# as the base directory.
agent_updates_dir: ${temp}/pyfarm-updates
# Optional directory to serve GET requests for agent updates
# from. This is different from `agent_updates_dir` in that it's
# only used when an agent is requested a file to update from. This
# can be useful when you're caching requests or doing something with
# the update files prior to them being requested by the agent.
agent_updates_webdir: null
# The directory to store downloaded logs in.
#
# **Production Note**: For production it's probably best if these are kept
# in a persistent location rather than $temp.
tasklogs_dir: ${temp}/task_logs
# The address the Flask application should listen on. This is only important
# when running the application in a standalone mode of operation. By default
# this will only listen locally but could be changed to listen on
# a specific adatper or `0.0.0.0` for all addresses.
flask_listen_address: 127.0.0.1
# When true all database tables will be dropped prior to setting
# up the application. This is useful for development purposes only
# and should not be used in production. There's also the `pyfarm-tables`
# command line tool which can be used to create or drop tables.
dev_db_drop_all: false
# When true we'll attempt to create any missing database tables
# prior to the application starting. This is useful for development
# purposes only and should not be used in production. There's also
# the `pyfarm-tables` command line tool which can be used to create
# or drop tables.
dev_db_create_all: false
# When true the application will be instanced as 'app' in the
# pyfarm.master.entrypoints module. When running behind something
# like uwsgi this should be true.
instance_application: false
##
## BEGIN Queue defaults
##
# The default priority for a newly created job queue.
queue_default_priority: 0
# The default weight of a newly created job queue.
queue_default_weight: 10
# The minimum and maxinum priority any queue can have. This is
# used by the models for validation purposes.
queue_min_priority: -1000
queue_max_priority: 1000
##
## END Queue defaults
##
##
## BEGIN Job Type defaults
##
# The maximum number of tasks for the given job type
# to send to an agent at once.
job_type_max_batch: 1
# When batching and this value is true frames will be batched
# in contiguous groups.
job_type_batch_contiguous: true
##
## END Job Type defaults
##
|
Models¶
The below is the current configuration file for job types. This
file lives at pyfarm/models/etc/models.yml
in the source tree.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 | ##
## BEGIN Database Table Names
##
# Prefix used in the construction of all table names. See the variables
# below for uage.
table_prefix: ""
# The name of the table for software items
table_software: ${table_prefix}software
# The name of the table for software versions
table_software_version: ${table_software}_versions
# The name of the table used for tagging
table_tag: ${table_prefix}tags
# The name of the table storing agent entries
table_agent: ${table_prefix}agents
# The name of the table which associates agents and software versions
table_agent_software_version_assoc: ${table_prefix}agent_software_version_associations
# The name of the table which associates agents and tags
table_agent_tag_assoc: ${table_prefix}agent_tag_associations
# The name of the table which associated agents and mac addresses
table_agent_mac_address: ${table_prefix}agent_mac_addresses
# The name of the table containing jobs
table_job: ${table_prefix}jobs
# The name of the table containing job types
table_job_type: ${table_prefix}jobtypes
# The name of the table containing job type versions
table_job_type_version: ${table_prefix}jobtype_versions
# The name of the table which associates jobs and tags.
table_job_tag_assoc: ${table_prefix}job_tag_associations
# The name of the table which associates job and tag requirements
table_job_tag_req: ${table_prefix}job_tag_requirements
# The name of the table which associates inter-job dependencies
table_job_dependency: ${table_prefix}job_dependencies
# The name of the table which associates job and software requirements
table_job_software_req: ${table_prefix}job_software_requirements
# The name of the table containing information about users to be notified
# of status changes form jobs
table_job_notified_users: ${table_prefix}notified_users
# The name of the table which associates software requirements and jobs
table_job_type_software_req: ${table_prefix}jobtype_software_requirements
# The name of the table containing tasks
table_task: ${table_prefix}tasks
# The name of the table containing user information
table_user: ${table_prefix}users
# The name of the table containing role information
table_role: ${table_prefix}roles
# The name of the table which associates users and roles
table_user_role: ${table_prefix}user_roles
# The name of the table containing the job queues
table_job_queue: ${table_prefix}job_queues
# The name of the table containing job groups
table_job_group: ${table_prefix}job_groups
# The name of the table containing path mappings
table_path_map: ${table_prefix}path_maps
# The name of the table containing task logs
table_task_log: ${table_prefix}task_logs
# The name of the table containing assoications between task
# logs and jobs
table_task_log_assoc: ${table_prefix}task_log_associations
# The name of the table containing GPU information for agents
table_gpu: ${table_prefix}gpus
# The name of the table containing associations between agents and GPUs
table_gpu_in_agent: ${table_prefix}gpu_agent_associations
# The name of the table storing which tasks where failed on an agent
table_failed_task_in_agent: ${table_prefix}failed_tasks_in_agents
# The name of the table containing the disks of the agents
table_agent_disk: ${table_prefix}agent_disks
table_statistics_agent_count: ${table_prefix}agent_counts
table_statistics_task_event_count: ${table_prefix}task_event_counts
table_statistics_task_count: ${table_prefix}task_counts
##
## END Database Table Names
##
##
## BEGIN Database Model Constraints
##
# There's some validation that happens when an agent is added to the
# database. One of the checks we have is to ensure the agent's address
# is a remote address which a loopback address normally is not considered
# 'remote'. Changing this value to to true disable this and will allow
# agents from a local address to connect.
allow_agents_from_loopback: false
# The maximum length of a tag
max_tag_length: 64
# The maximum length of a hostname
max_hostname_length: 255
# The maximum length of a job group's name.
max_jobgroup_name_length: 255
# The maximum length of the operating system's name for an agent.
max_osname_length: 128
# The maximum length of an agent's CPU name
max_cpuname_length: 128
# **Not Implemented** The default amount of ram the agent is allowed to
# allocate towards work. A value of 1.0 would allow the agent to be
# assigned as much work as the system's ram would allow.
agent_ram_allocation: .8
# **Not Implemented** Based on load, this is the default amount of CPU space
# an agent is allowed to occupy with work.
agent_cpu_allocation: 1.0
# The minimum and maxinum ports an agent can connect from
agent_min_port: 1024
agent_max_port: 65535
# The minimum and maxinum CPUs an agent can declare
# These values also drive the min/max number of CPUS job is allowed to request.
agent_min_cpus: 1
agent_max_cpus: 256
# The minimum and maxinum amount of RAM, in megabytes, an agent can declare.
# These values also drive the min/max amount of ram a job is allowed to request.
agent_min_ram: 16
agent_max_ram: 262144
# The default weight given to a job for use in the queue.
queue_default_weight: 10
# The maxinum length a job's title is allowed to be
jobtitle_max_length: 255
# The global default batch size for all new jobs.
job_default_batch: 1
# The global default number of times a job will requeue
# for tailed tasks. 0 will never requeue, -1 will
# requeue indefinitely.
job_requeue_default: 3
# The global default minimum number of CPUs a job may execute
# on. 0 will disable the minimum, -1 for force an entire agent
# to be exclusive to a job's task.
job_default_cpus: 1
# The global default amount of ram that's required to be free on
# host in order for a task of a job to run on a given agent. A
# value of 0 will not require a minimum, -1 will force the agent's
# entire ram to be allocated to the given task.
job_default_ram: 32
# The maximum length a path mapping is allowed to be.
max_path_length: 512
# The maximum length a GPU name is allowed to be.
max_gpu_name_length: 128
# The maximum length a queue name is allowed to be.
max_queue_name_length: 255
# The maximum length of a queue's path
max_queue_path_length: 1024
# The maximum length of a job type's name
job_type_max_name_length: 64
# The maximum length of a job type's class name
job_type_max_class_name_length: 64
# The maximum length of a username
max_username_length: 255
# The maximum length of an email address
max_email_length: 255
# The maximum length of a role name
max_role_length: 128
# The maximum length of a mountpoint for agent disks
max_mountpoint_length: 255
# The maximum lenght of the function name to discover the presence of a
# software version on an agent
max_discovery_function_name_length: 255
##
## END Database Model Constraints
##
|
Scheduler¶
The below is the current configuration file for job types. This
file lives at pyfarm/scheduler/etc/scheduler.yml
in the source tree.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | ##
## BEGIN Scheduler Settings
##
# The user agent the scheduler will use when connecting to
# an agent. Do not change this value unless the agent is
# updated to reflect the change made here.
master_user_agent: "PyFarm/1.0 (master)"
# How often the scheduler should run and poll agents. The keys and
# values here are passed into a `timedelta` object as keywords.
agent_poll_interval:
seconds: 30
# How often the scheduler should run and and assign tasks. The keys and
# values here are passed into a `timedelta` object as keywords.
assign_tasks_interval:
minutes: 4
# How often orphaned task logs should be cleaned up on disk. The keys and
# values here are passed into a `timedelta` object as keywords.
orphaned_log_cleanup_interval:
hours: 1
# How often we should attempt to compress old task logs. The keys and
# values here are passed into a `timedelta` object as keywords.
compress_log_interval:
minutes: 10
# How often old jobs should be deleted. Please note this only marks
# jobs as to be deleted and does not actually perform the deletion
# itself. See the ``delete_job_interval`` setting which will actually
# trigger the deletion of jobs. The keys and values here are passed
# into a `timedelta` object as keywords.
autodelete_old_job_interval:
hours: 1
# How often the scheduler which deletes jobs should run. The keys and values
# here are passed into a `timedelta` object as keywords.
delete_job_interval:
minutes: 5
# Used when polling agents to determine if we should or should not
# reach out to an agent. This is used in combination with the agent's
# `last_heard_from` column, it's state and number of running tasks. The keys
# and values here are passed into a `timedelta` object as keywords.
poll_busy_agents_interval:
minutes: 5
# Used when polling agents to determine if we should or should not
# reach out to an agent. This is used in combination with an agent's
# `last_head_from` column, state and running task count. The keys
# and values here are passed into a `timedelta` object as keywords.
poll_idle_agents_interval:
hours: 1
# Used when polling agents to determine if an agent is considered
# offline or not after a given period of time without communication. The keys
# and values here are passed into a `timedelta` object as keywords.
poll_offline_agents_interval:
hours: 2
# A directory where lock files for the scheuler can be found.
scheduler_lockfile_base: ${temp}/scheduler_lock
# The number of times an SQL transation error should be retried.
transaction_retries: 10
# The number of seconds we wait for a request to an agent to respond. An
# exception is raised if we exceed this amount.
agent_request_timeout: 10
# When true the queue will prefer to assign work
# for jobs which are already running.
queue_prefer_running_jobs: true
# Whether to use an agents total RAM instead of reported free RAM to determine
# whether or not it can run a task.
use_total_ram_for_scheduling: false
##
## END Scheduler Settings
##
##
## BEGIN Email Server Settings
##
# The smtp server used to send email notifications. Note that setting
# this value to null or leaving it blank will disable email notifications.
smtp_server: localhost
# Port to connect to the smtp server on. The default port, 0, will
# cause the underlying library to use the default smtp port.
smtp_port: 0
# Optional login credentials for the smtp server. The default value
# [null, null] means no username and password is required.
smtp_login: [null, null]
# The default address from which all emails from the scheduler will
# originate.
from_email: pyfarm@localhost
##
## END Email Server Settings
##
##
## BEGIN Email Template Settings
##
# General note about the settings below. The brackets, {{ }}
# are used by the templating system for string substitution. For example,
# {{ job.title }} would substitute in the string found on the `title` column
# of a job model. For more information on template formatting, see Jinja's
# documentation: http://jinja.pocoo.org/docs/
# Finally, for multi-line strings follow this syntax:
# foobar:
# |
# This is a multi-line
# string. It's indentation
#
# and whitespace will be preserved.
# The template email subject line used for a succesful job.
success_subject: Job {{ job.title }} completed successfully
# The template body of an email for a succesful job
success_body:
|
{{ job.jobtype_version.jobtype.name }} job {{ job.title }} (id {{ job.id }})
has completed successfully on {{ job.time_finished.isoformat() }}.
Job: {{ job.url }}
{% if job.output_link %}
Output: {{ job.output_link }}
{% endif %}
Sincerely,
The PyFarm render manager
# The template email subject line used for a failed job.
failed_subject: Job {{ job.title }} failed
# The template email body for a failed job.
failed_body:
|
{{ job.jobtype_version.jobtype.name }} job {{ job.title }}
(id {{ job.id }}) has failed on
{{ job.time_finished.isoformat() }}.
Job: {{ job.url }}
{% if job.output_link %}
Output:
{{ job.output_link }}
{% endif %}
{% if failed_log_urls %}
Log(s) for failed tasks:
{% for url in failed_log_urls %}
{{url}}
{% endfor%}
{% endif %}
Sincerely,
The PyFarm render manager
# The template email subject line used for a deleted job. Supported
# template values are:
# {job_title} - The title of the job being deleted
deleted_subject: Job {job_title} deleted
# The template email body for a deleted job. Supported template
# values are:
# {job_title} - The title of the job deleted
# {job_id} - The id of the job deleted
# {jobtype_name} - The name of the job type used
deleted_body:
|
{jobtype_name} job {job_title} has been deleted.
Sincerely,
The PyFarm render manager
##
## END Email Template Settings
##
##
## BEGIN Statistics Gathering Settings
##
# Whether or not to gather data for runtime statistics
enable_statistics: true
agent_count_interval:
hours: 1
task_event_count_consolidate_interval:
minutes: 15
task_count_interval:
minutes: 15
##
## END Statistics Gathering Settings
##
|
pyfarm.master package¶
Subpackages¶
pyfarm.master.api package¶
Submodules¶
pyfarm.master.api.agent_updates module¶
The API allows access to agent update packages, possibly through redirects
-
class
pyfarm.master.api.agent_updates.
AgentUpdatesAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(version)[source]¶ A
GET
to this endpoint will return the update package as a zip file the specified version-
GET
/api/v1/agents/updates/<string:version> HTTP/1.1
¶ Request
PUT /api/v1/agents/updates/1.2.3 HTTP/1.1 Accept: application/zip
Response
HTTP/1.1 200 OK Content-Type: application/zip <binary data>
Statuscode 200: The update file was found and is returned Statuscode 301: The update can be found under a different URL Statuscode 400: there was something wrong with the request (such as an invalid version number specified or the mime type not being application/zip) -
-
methods
= ['GET', 'PUT']¶
-
put
(version)[source]¶ A
PUT
to this endpoint will upload a new version of pyfarm-agent to be used for agent auto-updates. The update must be a zip file.-
PUT
/api/v1/agents/updates/<string:version> HTTP/1.1
¶ Request
PUT /api/v1/agents/updates/1.2.3 HTTP/1.1 Content-Type: application/zip <binary data>
Response
HTTP/1.1 200 OK Content-Type: application/json
Statuscode 201: The update was put in place Statuscode 400: there was something wrong with the request (such as an invalid version number specified or the mime type not being application/zip) -
-
pyfarm.master.api.agents module¶
Contained within this module are an API handling functions which can manage or query agents using JSON.
-
class
pyfarm.master.api.agents.
AgentIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of known agents, with id and name.-
GET
/api/v1/agents/ HTTP/1.1
¶ Request
GET /api/v1/agents/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "hostname": "agent1", "id": "dd0c6da2-0c91-42cf-a82f-6d503aae43d3" }, { "hostname": "agent2", "id": "8326779e-90b5-447c-8da8-1eaa154771d9" }, { "hostname": "agent3.local", "id": "14b28230-64a1-4b62-803e-5fd1baa209e4" } ]
Request (with filters)
GET /api/v1/agents/?min_ram=4096&min_cpus=4 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "hostname": "foobar", "port": 50000, "remote_ip": "127.0.0.1", "id": "e20bae92-6472-442e-98a8-0ea4c9ee41cd" } ]
Qparam min_ram: If set, list only agents with min_ram
ram or moreQparam max_ram: If set, list only agents with max_ram
ram or lessQparam min_cpus: If set, list only agents with min_cpus
cpus or moreQparam max_cpus: If set, list only agents with max_cpus
cpus or lessQparam hostname: If set, list only agents matching hostname
Qparam remote_ip: If set, list only agents matching remote_ip
Qparam port: If set, list only agents matching port
.Statuscode 200: no error, host may or may not have been found -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will either create or update an existing agent. Theport
andid
columns will determine if an agent already exists.- If an agent is found matching the
port
andid
columns from the request the existing model will be updated and the resulting data and theOK
code will be returned. - If we don’t find an agent matching the
port
andid
however a new agent will be created and the resulting data and theCREATED
code will be returned.
Note
The
remote_ip
field is not required and should typically not be included in a request. When not providedremote_ip
is be populated by the server based off of the ip of the incoming request. Providingremote_ip
in your request however will override this behavior.-
POST
/api/v1/agents/ HTTP/1.1
¶ Request
POST /api/v1/agents/ HTTP/1.1 Accept: application/json { "cpu_allocation": 1.0, "cpus": 14, "free_ram": 133, "hostname": "agent1", "id": "6a0c11df-660f-4c1e-9fb4-5fe2b8cd2437", "remote_ip": "10.196.200.115", "port": 64994, "ram": 2157, "ram_allocation": 0.8, "state": 8 }
Response (agent created)
HTTP/1.1 201 CREATED Content-Type: application/json { "cpu_allocation": 1.0, "cpus": 14, "use_address": "remote", "free_ram": 133, "time_offset": 0, "hostname": "agent1", "id": "6a0c11df-660f-4c1e-9fb4-5fe2b8cd2437", "port": 64994, "ram": 2157, "ram_allocation": 0.8, "state": "online", "remote_ip": "10.196.200.115" }
Response (existing agent updated)
HTTP/1.1 200 OK Content-Type: application/json { "cpu_allocation": 1.0, "cpus": 14, "use_address": "remote", "free_ram": 133, "time_offset": 0, "hostname": "agent1", "id": "6a0c11df-660f-4c1e-9fb4-5fe2b8cd2437", "port": 64994, "ram": 2157, "ram_allocation": 0.8, "state": "online", "remote_ip": "10.196.200.115" }
Statuscode 201: a new agent was created Statuscode 200: an existing agent is updated with data from the request Statuscode 400: there was something wrong with the request (such as invalid columns being included) - If an agent is found matching the
-
-
class
pyfarm.master.api.agents.
SingleAgentAPI
[source]¶ Bases:
flask.views.MethodView
API view which is used for retrieving information about and updating single agents.
-
delete
(agent_id)[source]¶ Delete a single agent
-
DELETE
/api/v1/agents/
(uuid: agent_id)HTTP/1.1
¶ Request (agent exists)
DELETE /api/v1/agents/b25ee7eb-9586-439a-b131-f5d022e0d403 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO CONTENT Content-Type: application/json
Statuscode 204: the agent was deleted or did not exist -
-
get
(agent_id)[source]¶ Return basic information about a single agent
-
GET
/api/v1/agents/
(str: agent_id)HTTP/1.1
¶ Request (agent exists)
GET /api/v1/agents/4eefca76-1127-4c17-a3df-c1a7de685541 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "cpu_allocation": 1.0, "cpus": 14, "use_address": 311, "free_ram": 133, "time_offset": 0, "hostname": "agent1", "id": "322360ad-976f-4103-9acc-a811d43fd24d", "ip": "10.196.200.115", "port": 64994, "ram": 2157, "ram_allocation": 0.8, "state": 202, "remote_ip": "10.196.200.115" }
Request (no such agent)
GET /api/v1/agents/4eefca76-1127-4c17-a3df-c1a7de685541 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 404 NOT FOUND Content-Type: application/json {"error": "Agent `4eefca76-1127-4c17-a3df-c1a7de685541` not " "found"}
Statuscode 200: no error Statuscode 400: something within the request is invalid Statuscode 404: no agent could be found using the given id -
-
methods
= ['DELETE', 'GET', 'POST']¶
-
post
(agent_id)[source]¶ Update an agent’s columns with new information by merging the provided data with the agent’s current definition in the database.
-
POST
/api/v1/agents/
(str: agent_id)HTTP/1.1
¶ Request
POST /api/v1/agents/29d466a5-34f8-408a-b613-e6c2715077a0 HTTP/1.1 Accept: application/json {"ram": 1234}
Response
HTTP/1.1 200 OK Content-Type: application/json { "cpu_allocation": 1.0, "cpus": 14, "use_address": 311, "free_ram": 133, "time_offset": 0, "hostname": "agent1", "id": "29d466a5-34f8-408a-b613-e6c2715077a0", "ip": "10.196.200.115", "port": 64994, "ram": 1234, "ram_allocation": 0.8, "state": "running", "remote_ip": "10.196.200.115" }
Statuscode 200: no error Statuscode 400: something within the request is invalid Statuscode 404: no agent could be found using the given id -
-
-
class
pyfarm.master.api.agents.
SingleSoftwareInAgentAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(agent_id, software_name, version_name)[source]¶ A
DELETE
to this endpoint will remove the specified software version from the list of supported software in this agent-
DELETE
/api/v1/agents/<str:agent_id>/software/<str:software>/versions/<str:version> HTTP/1.1
¶ Request
DELETE /api/v1/agents/bbf55143-f2b1-4c15-9d41-139bd8057931/software/Blender/versions/2.72 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 NO CONTENT
Statuscode 204: the software version has been removed from the supported versions on this agent or has not been on the list in the first place Statuscode 404: agent not found -
-
methods
= ['DELETE']¶
-
-
class
pyfarm.master.api.agents.
SoftwareInAgentIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(agent_id)[source]¶ A
GET
to this endpoint will return a list of all software versions available on this agent.-
GET
/api/v1/agents/<str:agent_id>/software/ HTTP/1.1
¶ Request
GET /api/v1/agents/bbf55143-f2b1-4c15-9d41-139bd8057931/software/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "software": "Blender", "version": "2.72" } ]
Statuscode 200: no error Statuscode 404: agent not found -
-
methods
= ['GET', 'POST']¶
-
post
(agent_id)[source]¶ A
POST
to this endpoint will mark the given version of the given software as available on this agent.-
POST
/api/v1/agents/<str:agent_id>/software/ HTTP/1.1
¶ Request
POST /api/v1/agents/bbf55143-f2b1-4c15-9d41-139bd8057931/software/ HTTP/1.1 Accept: application/json { "software": "Blender", "version": "2.72" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "software": "Blender", "version": "2.72" }
Statuscode 200: no error Statuscode 400: the request contained unknown keys or required keys were missing. Statuscode 404: agent not found -
-
-
class
pyfarm.master.api.agents.
TasksInAgentAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(agent_id)[source]¶ A
GET
to this endpoint will return a list of all tasks assigned to this agent.-
GET
/api/v1/agents/<str:agent_id>/tasks/ HTTP/1.1
¶ Request
GET /api/v1/agents/bbf55143-f2b1-4c15-9d41-139bd8057931/tasks/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "state": "assign", "priority": 0, "job": { "jobtype": "TestJobType", "id": 1, "title": "Test Job", "jobtype_version": 1, "jobtype_id": 1 }, "hidden": false, "time_started": null, "project_id": null, "frame": 2.0 "agent_id": "bbf55143-f2b1-4c15-9d41-139bd8057931", "id": 2, "attempts": 2, "project": null, "time_finished": null, "time_submitted": "2014-03-06T15:40:58.338904", "job_id": 1 } ]
Statuscode 200: no error Statuscode 404: agent not found -
-
methods
= ['GET', 'POST']¶
-
post
(agent_id)[source]¶ A
POST
to this endpoint will assign am existing task to the agent.-
POST
/api/v1/agents/<str:agent_id>/tasks/ HTTP/1.1
¶ Request
POST /api/v1/agents/238d7334-8ca5-4469-9f54-e76c66614a43/tasks/ HTTP/1.1 Accept: application/json { "id": 2 }
Response
HTTP/1.1 200 OK Content-Type: application/json { "agent_id": 1, "parents": [], "attempts": 2, "children": [], "job": { "title": "Test Job", "id": 1 }, "project_id": null, "agent": { "ip": null, "hostname": "agent1", "port": 50000, "id": "238d7334-8ca5-4469-9f54-e76c66614a43" }, "hidden": false, "job_id": 1, "time_submitted": "2014-03-06T15:40:58.338904", "frame": 2.0, "priority": 0, "state": "assign", "time_finished": null, "id": 2, "project": null, "time_started": null }
Statuscode 200: no error Statuscode 404: agent not found -
-
-
pyfarm.master.api.agents.
schema
()[source]¶ Returns the basic schema of
Agent
-
GET
/api/v1/agents/schema HTTP/1.1
¶ Request
GET /api/v1/agents/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "ram": "INTEGER", "free_ram": "INTEGER", "time_offset": "INTEGER", "use_address": "INTEGER", "hostname": "VARCHAR(255)", "cpus": "INTEGER", "port": "INTEGER", "state": "INTEGER", "ram_allocation": "FLOAT", "cpu_allocation": "FLOAT", "id": "UUIDType", "remote_ip": "IPv4Address" }
Statuscode 200: no error -
pyfarm.master.api.jobgroups module¶
This module defines an API for managing and querying job groups
-
class
pyfarm.master.api.jobgroups.
JobGroupIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of known job groups.-
GET
/api/v1/jobgroups/ HTTP/1.1
¶ Request
GET /api/v1/jobgroups/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "id": 2, "user": "testuser", "main_jobtype": "Test JobType", "title": "Test Group" } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will create a new job group.-
POST
/api/v1/jobgroups/ HTTP/1.1
¶ Request
POST /api/v1/jobgroups/ HTTP/1.1 Accept: application/json { "title": "Test Group", "user": "testuser", "main_jobtype": "Test JobType" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 2, "jobs": [], "user": "testuser", "main_jobtype": "Test JobType", "title": "Test Group" }
Statuscode 201: a new job group was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.jobgroups.
JobsInJobGroupIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(group_id)[source]¶ A
GET
to this endpoint will return all jobs in the speicfied jobgroup.-
GET
/api/v1/jobgroups/<int:id>/jobs HTTP/1.1
¶ Request
GET /api/v1/jobgroups/2/jobs HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "jobs": [ { "id": "12345", "title": "Test Job", "state": "queued", "jobtype_id": 5, "jobtype": "Test Jobtype", "tasks_queued": 5, "tasks_running": 0, "tasks_done": 0, "tasks_failed": 0 } ] }
Statuscode 200: no error Statuscode 404: the requested job group was not found -
-
methods
= ['GET']¶
-
-
class
pyfarm.master.api.jobgroups.
SingleJobGroupAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(group_id)[source]¶ A
DELETE
to this endpoint will delete the specified job group-
DELETE
/api/v1/jobgroup/<int:id>
¶ Request
DELETE /api/v1/jobgroups/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the job group was deleted or didn’t exist Statuscode 409: the job group cannot be deleted because it still contains jobs -
-
get
(group_id)[source]¶ A
GET
to this endpoint will return the requested job group-
GET
/api/v1/jobgroups/<int:id> HTTP/1.1
¶ Request
GET /api/v1/jobgroups/2 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 2, "user": "testuser", "main_jobtype": "Test JobType", "jobs": [], "title": "Test Group" }
Statuscode 200: no error Statuscode 404: the requested job group was not found -
-
methods
= ['DELETE', 'GET', 'POST']¶
-
post
(group_id)[source]¶ A
POST
to this endpoint will update the specified group with the data in the request. Columns not specified in the request will be left as they are.-
POST
/api/v1/jobgroups/<int:id> HTTP/1.1
¶ Request
POST /api/v1/jobgroups/2 HTTP/1.1 Accept: application/json { "user": "testuser2" }
Response
HTTP/1.1 201 OK Content-Type: application/json { "id": 2, "user": "testuser2", "main_jobtype": "Test JobType", "jobs": [], "title": "Test Group" }
Statuscode 200: the job group was updated Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
pyfarm.master.api.jobgroups.
schema
()[source]¶ Returns the basic schema of
JobGroup
-
GET
/api/v1/jobgroups/schema HTTP/1.1
¶ Request
GET /api/v1/jobgroups/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "main_jobtype": "VARCHAR(64)", "title": "VARCHAR(255)", "user": "VARCHAR(255)", "id": "INTEGER" }
Statuscode 200: no error -
pyfarm.master.api.jobqueues module¶
This module defines an API for managing and querying job queues
-
class
pyfarm.master.api.jobqueues.
JobQueueIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of known job queues.-
GET
/api/v1/jobqueues/ HTTP/1.1
¶ Request
GET /api/v1/jobqueues/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "priority": 5, "weight": 10, "parent_jobqueue_id": null, "name": "Test Queue", "minimum_agents": null, "id": 1, "maximum_agents": null }, { "priority": 5, "weight": 10, "parent_jobqueue_id": null, "name": "Test Queue 2", "minimum_agents": null, "id": 2, "maximum_agents": null } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will create a new job queue.-
POST
/api/v1/jobqueues/ HTTP/1.1
¶ Request
POST /api/v1/jobqueues/ HTTP/1.1 Accept: application/json { "name": "Test Queue" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "weight": 10, "jobs": [], "minimum_agents": null, "priority": 5, "name": "Test Queue", "maximum_agents": null, "id": 1, "parent": null, "parent_jobqueue_id": null }
Statuscode 201: a new job queue was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 409: a job queue with that name already exists -
-
-
class
pyfarm.master.api.jobqueues.
SingleJobQueueAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(queue_rq)[source]¶ A
DELETE
to this endpoint will delete the specified job queue-
DELETE
/api/v1/jobqueue/[<str:name>|<int:id>]
¶ Request
DELETE /api/v1/jobqueues/Test%20Queue HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the job queue was deleted or didn’t exist Statuscode 409: the job queue cannot be deleted because it still contains jobs or child queues -
-
get
(queue_rq)[source]¶ A
GET
to this endpoint will return the requested job queue-
GET
/api/v1/jobqueues/[<str:name>|<int:id>] HTTP/1.1
¶ Request
GET /api/v1/jobqueues/Test%20Queue HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "parent": [], "jobs": [], "weight": 10, "parent_jobqueue_id": null, "priority": 5, "minimum_agents": null, "name": "Test Queue", "maximum_agents": null }
Statuscode 200: no error Statuscode 404: the requested job queue was not found -
-
methods
= ['DELETE', 'GET', 'POST']¶
-
post
(queue_rq)[source]¶ A
POST
to this endpoint will update the specified queue with the data in the request. Columns not specified in the request will be left as they are.-
POST
/api/v1/jobqueues/[<str:name>|<int:id>] HTTP/1.1
¶ Request
POST /api/v1/jobqueues/Test%20Queue HTTP/1.1 Accept: application/json { "priority": 6 }
Response
HTTP/1.1 201 OK Content-Type: application/json { "id": 1, "parent": [], "jobs": [], "weight": 10, "parent_jobqueue_id": null, "priority": 6, "minimum_agents": null, "name": "Test Queue", "maximum_agents": null }
Statuscode 200: the job queue was updated Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
pyfarm.master.api.jobqueues.
schema
()[source]¶ Returns the basic schema of
JobQueue
-
GET
/api/v1/jobqueues/schema HTTP/1.1
¶ Request
GET /api/v1/jobqueues/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": "INTEGER", "name": VARCHAR(255)", "minimum_agents": "INTEGER", "maximum_agents": "INTEGER", "priority": "INTEGER", "weight": "INTEGER", "parent_jobqueue_id": "INTEGER" }
Statuscode 200: no error -
pyfarm.master.api.jobs module¶
This module defines an API for managing and querying jobs
-
class
pyfarm.master.api.jobs.
JobIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of all jobs.-
GET
/api/v1/jobs/ HTTP/1.1
¶ Request
GET /api/v1/jobs/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "title": "Test Job", "state": "queued", "id": 1 }, { "title": "Test Job 2", "state": "queued", "id": 2 } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will submit a new job.-
POST
/api/v1/jobs/ HTTP/1.1
¶ Request
POST /api/v1/jobs/ HTTP/1.1 Accept: application/json { "end": 2.0, "title": "Test Job 2", "jobtype": "TestJobType", "data": { "foo": "bar" }, "software_requirements": [ { "software": "blender" } ], "start": 1.0 }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "time_finished": null, "time_started": null, "end": 2.0, "time_submitted": "2014-03-06T15:40:58.335259", "jobtype_version": 1, "jobtype": "TestJobType", "jobqueue": None "start": 1.0, "priority": 0, "state": "queued", "parents": [], "hidden": false, "project_id": null, "ram_warning": null, "title": "Test Job 2", "tags": [], "user": null, "by": 1.0, "data": { "foo": "bar" }, "ram_max": null, "notes": "", "batch": 1, "project": null, "environ": null, "requeue": 3, "software_requirements": [ { "min_version": null, "max_version": null, "max_version_id": null, "software_id": 1, "min_version_id": null, "software": "blender" } ], "tag_requirements": [ { "tag": "workstation", "negate": true } ], "id": 2, "ram": 32, "cpus": 1, "children": [] }
Statuscode 201: a new job item was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: a referenced object, like a software or software version, does not exist Statuscode 409: a conflicting job already exists -
-
-
class
pyfarm.master.api.jobs.
JobNotifiedUsersIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_name)[source]¶ A
GET
to this endpoint will return a list of all users to be notified on events in this job.-
GET
/api/v1/jobs/[<str:name>|<int:id>]/notified_users/ HTTP/1.1
¶ Request
GET /api/v1/jobs/Test%20Job%202/notified_users/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "id": 1, "username": "testuser", "email": "testuser@localhost" } ]
Statuscode 200: no error Statuscode 404: job not found -
-
methods
= ['GET', 'POST']¶
-
post
(job_name)[source]¶ A
POST
to this endpoint will add the specified user to the list of notified users for this job.-
POST
/api/v1/jobs/[<str:name>|<int:id>]/notified_users/ HTTP/1.1
¶ Request
POST /api/v1/jobs/Test%20Job/notified_users/ HTTP/1.1 Accept: application/json { "username": "testuser" "on_success": true, "on_failure": true, "on_deletion": false }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1 "username": "testuser" "email": "testuser@example.com" }
Statuscode 201: a new notified user entry was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: the job or the specified user does not exist -
-
-
class
pyfarm.master.api.jobs.
JobSingleNotifiedUserAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(job_name, username)[source]¶ A
DELETE
to this endpoint will remove the specified user from the list of notified users for this job.-
DELETE
/api/v1/jobs/[<str:name>|<int:id>]/notified_users/<str:username> HTTP/1.1
¶ Request
DELETE /api/v1/jobs/Test%20Job/notified_users/testuser HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the notified user was removed from this job or wasn’t in the list in the first place Statuscode 404: the job or the specified user does not exist -
-
methods
= ['DELETE']¶
-
-
class
pyfarm.master.api.jobs.
JobSingleTaskAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_name, task_id)[source]¶ A
GET
to this endpoint will return the requested task-
GET
/api/v1/jobs/[<str:name>|<int:id>]/tasks/<int:task_id> HTTP/1.1
¶ Request
GET /api/v1/jobs/Test%20Job%202/tasks/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "time_finished": null, "agent": null, "attempts": 0, "frame": 2.0, "agent_id": null, "job": { "id": 1, "title": "Test Job" }, "time_started": null, "state": "running", "project_id": null, "id": 2, "time_submitted": "2014-03-06T15:40:58.338904", "project": null, "parents": [], "job_id": 1, "hidden": false, "children": [], "priority": 0 }
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
(job_name, task_id)[source]¶ A
POST
to this endpoint will update the specified task with the data in the request. Columns not specified in the request will be left as they are. The agent will use this endpoint to inform the master of its progress.-
POST
/api/v1/jobs/[<str:name>|<int:id>]/tasks/<int:task_id> HTTP/1.1
¶ Request
PUT /api/v1/job/Test%20Job/tasks/1 HTTP/1.1 Accept: application/json { "state": "running" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "time_finished": null, "agent": null, "attempts": 0, "failures": 0, "frame": 2.0, "agent_id": null, "job": { "id": 1, "title": "Test Job" }, "time_started": null, "state": "running", "project_id": null, "id": 2, "time_submitted": "2014-03-06T15:40:58.338904", "project": null, "parents": [], "job_id": 1, "hidden": false, "children": [], "priority": 0 }
Statuscode 200: the task was updated Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.jobs.
JobTasksIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_name)[source]¶ A
GET
to this endpoint will return a list of all tasks in a job.-
GET
/api/v1/jobs/[<str:name>|<int:id>]/tasks HTTP/1.1
¶ Request
GET /api/v1/jobs/Test%20Job%202/tasks/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "hidden": false, "id": 3, "attempts": 0, "priority": 0, "time_started": null, "time_submitted": "2014-03-06T15:49:51.892228", "frame": 1.0, "time_finished": null, "job_id": 2, "project_id": null, "state": "queued", "agent_id": null }, { "hidden": false, "id": 4, "attempts": 0, "priority": 0, "time_started": null, "time_submitted": "2014-03-06T15:49:51.892925", "frame": 2.0, "time_finished": null, "job_id": 2, "project_id": null, "state": "queued", "agent_id": null } ]
Statuscode 200: no error -
-
methods
= ['GET']¶
-
-
class
pyfarm.master.api.jobs.
SingleJobAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(job_name)[source]¶ A
DELETE
to this endpoint will mark the specified job for deletion and remove it after stopping and removing all of its tasks.-
DELETE
/api/v1/jobs/[<str:name>|<int:id>] HTTP/1.1
¶ Request
DELETE /api/v1/jobs/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the specified job was marked for deletion Statuscode 404: the job does not exist -
-
get
(job_name)[source]¶ A
GET
to this endpoint will return the specified job, by name or id.-
GET
/api/v1/jobs/[<str:name>|<int:id>] HTTP/1.1
¶ Request
GET /api/v1/jobs/Test%20Job%202 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "ram_warning": null, "title": "Test Job", "state": "queued", "jobtype_version": 1, "jobtype": "TestJobType", "environ": null, "user": null, "priority": 0, "time_finished": null, "start": 2.0, "id": 1, "notes": "", "notified_users": [] "ram": 32, "tags": [], "hidden": false, "data": { "foo": "bar" }, "software_requirements": [ { "software": "blender", "software_id": 1, "min_version": null, "max_version": null, "min_version_id": null, "max_version_id": null } ], "tag_requirements": [ { "tag": "workstation", "negate": true } ], "batch": 1, "time_started": null, "time_submitted": "2014-03-06T15:40:58.335259", "requeue": 3, "end": 4.0, "parents": [], "cpus": 1, "ram_max": null, "children": [], "by": 1.0, "project_id": null }
Statuscode 200: no error Statuscode 404: job not found -
-
methods
= ['DELETE', 'GET', 'POST']¶
-
post
(job_name)[source]¶ A
POST
to this endpoint will update the specified job with the data in the request. Columns not specified in the request will be left as they are. If the “start”, “end” or “by” columns are updated, tasks will be created or deleted as required.-
POST
/api/v1/jobs/[<str:name>|<int:id>] HTTP/1.1
¶ Request
PUT /api/v1/jobs/Test%20Job HTTP/1.1 Accept: application/json { "start": 2.0 }
Response
HTTP/1.1 201 OK Content-Type: application/json { "end": 4.0, "children": [], "jobtype_version": 1, "jobtype": "TestJobType", "time_started": null, "tasks_failed": [], "project_id": null, "id": 1, "software_requirements": [ { "software": "blender", "min_version": null, "max_version_id": null, "software_id": 1, "max_version": null, "min_version_id": null } ], "tags": [], "environ": null, "requeue": 3, "start": 2.0, "ram_warning": null, "title": "Test Job", "batch": 1, "time_submitted": "2014-03-06T15:40:58.335259", "ram_max": null, "user": null, "notes": "", "data": { "foo": "bar" }, "tag_requirements": [ { "tag": "workstation", "negate": true } ], "ram": 32, "parents": [], "hidden": false, "priority": 0, "cpus": 1, "state": "queued", "by": 1.0, "time_finished": null }
Statuscode 200: the job was updated Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.jobs.
SingleTaskOnAgentFailureAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(job_id, task_id, agent_id)[source]¶ A
DELETE
to this endpoint will remove the specified agent from the list of agents that failed to execute this task-
DELETE
/api/v1/jobs/<int:id>/tasks/<int:task_id>/failed_on_agents/<str:agent_id> HTTP/1.1
¶ Request
DELETE /api/v1/jobs/12/tasks/1234/failed_on_agents/02f08241-c556-4355-9e5e-33243d8c4577 HTTP/1.1
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the given agent was removed from the list of agents that failed to execute this task Statuscode 404: the job, task or agent does not exist -
-
methods
= ['DELETE']¶
-
-
class
pyfarm.master.api.jobs.
TaskFailedOnAgentsIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_id, task_id)[source]¶ A
GET
to this endpoint will return a list of all agents that failed to execute this task-
GET
/api/v1/jobs/<int:job_id>/tasks/<int:task_id>/failed_on_agents/ HTTP/1.1
¶ Request
GET /api/v1/jobs/12/tasks/1234/failed_on_agents/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "id": "02f08241-c556-4355-9e5e-33243d8c4577", "hostname": "agent1" } ]
Statuscode 200: no error Statuscode 404: job or task not found -
-
methods
= ['GET', 'POST']¶
-
post
(job_id, task_id)[source]¶ A
POST
to this endpoint will add the specified agent to the list of agents that failed to execute this task-
POST
/api/v1/jobs/<int:id>/tasks/<int:task_id>/failed_on_agents/ HTTP/1.1
¶ Request
POST /api/v1/jobs/12/tasks/1234/failed_on_agents/ HTTP/1.1 Accept: application/json Content-Type: application/json { "id": "02f08241-c556-4355-9e5e-33243d8c4577" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": "02f08241-c556-4355-9e5e-33243d8c4577", "hostname": "agent1" }
Statuscode 201: a new entry was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: the job, task or agent specified does not exist -
-
-
pyfarm.master.api.jobs.
parse_requirements
(requirements)[source]¶ Takes a list dicts specifying a software and optional min- and max-versions and returns a list of
JobRequirement
objects.Raises TypeError if the input was not as expected or ObjectNotFound if a referenced software or version was not found.
Parameters: requirements (list) – A list of of dicts specifying a software and optionally min_version and/or max_version.
Raises: - TypeError – Raised if
requirements
is not a list or if an entry inrequirements
is not a dictionary. - ValueError – Raised if there’s a problem with the content of at least one of the requirement dictionaries.
- ObjectNotFound – Raised if the referenced software or version was not found
- TypeError – Raised if
-
pyfarm.master.api.jobs.
schema
()[source]¶ Returns the basic schema of
Job
-
GET
/api/v1/jobs/schema HTTP/1.1
¶ Request
GET /api/v1/jobs/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "batch": "INTEGER", "by": "NUMERIC(10, 4)", "cpus": "INTEGER", "data": "JSONDict", "end": "NUMERIC(10,4)", "environ": "JSONDict", "hidden": "BOOLEAN", "id": "INTEGER", "jobtype": "VARCHAR(64)", "jobtype_version": "INTEGER", "jobqueue": "VARCHAR(255)", "notes": "TEXT", "priority": "INTEGER", "project_id": "INTEGER", "ram": "INTEGER", "ram_max": "INTEGER", "ram_warning": "INTEGER", "requeue": "INTEGER", "start": "NUMERIC(10,4)", "state": "WorkStateEnum", "time_finished": "DATETIME", "time_started": "DATETIME", "time_submitted": "DATETIME", "title": "VARCHAR(255)", "user": "VARCHAR(255)" }
Statuscode 200: no error -
pyfarm.master.api.jobtypes module¶
This module defines an API for managing and querying jobtypes
-
class
pyfarm.master.api.jobtypes.
JobTypeCodeAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(jobtype_name, version)[source]¶ A
GET
to this endpoint will return just the python code for this version of the specified jobtype.-
GET
/api/v1/jobtypes/[<str:name>|<int:id>]/versions/<int:version>/code HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType/versions/1/code HTTP/1.1 Accept: text/x-python
Response
HTTP/1.1 200 OK Content-Type: text/x-python from pyfarm.jobtypes.core.jobtype import JobType class TestJobType(JobType): def get_command(self): return "/usr/bin/touch" def get_arguments(self): return [os.path.join( self.assignment_data["job"]["data"]["path"], "%04d" % self.assignment_data["tasks"][0]["frame"])]
Statuscode 200: no error Statuscode 404: jobtype or version not found -
-
methods
= ['GET']¶
-
-
class
pyfarm.master.api.jobtypes.
JobTypeIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of registered jobtypes.-
GET
/api/v1/jobtypes/ HTTP/1.1
¶ Request
GET /api/v1/jobtypes/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "id": 1, "name": "TestJobType" } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will create a new jobtype.-
POST
/api/v1/jobtypes/ HTTP/1.1
¶ Request
POST /api/v1/jobtypes/ HTTP/1.1 Accept: application/json { "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "batch_contiguous": true, "software_requirements": [], "version": 1, "max_batch": 1, "name": "TestJobType", "classname": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n" }
Statuscode 201: a new jobtype item was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 409: a conflicting jobtype already exists -
-
-
class
pyfarm.master.api.jobtypes.
JobTypeSoftwareRequirementAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(jobtype_name, software)[source]¶ A
DELETE
to this endpoint will delete the requested software requirement from the specified jobtype, creating a new version of the jobtype in the process-
DELETE
/api/v1/jobtypes/[<str:name>|<int:id>]/software_requirements/<int:id> HTTP/1.1
¶ Request
DELETE /api/v1/jobtypes/TestJobType/software_requirements/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO CONTENT
Statuscode 204: the software requirement was deleted or didn’t exist -
-
get
(jobtype_name, software)[source]¶ A
GET
to this endpoint will return the specified software requirement from the newest version of the requested jobtype.-
GET
/api/v1/jobtypes/[<str:name>|<int:id>]/software_requirements/<int:id> HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType/software_requirements/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "software": { "software": "/bin/touch", "id": 1 }, "max_version": null, "min_version": { "version": "8.21", "id": 1 }, "jobtype_version": { "version": 7, "jobtype": "TestJobType" } }
Statuscode 200: no error Statuscode 404: jobtype or software requirement not found -
-
methods
= ['DELETE', 'GET']¶
-
-
class
pyfarm.master.api.jobtypes.
JobTypeSoftwareRequirementsIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(jobtype_name, version=None)[source]¶ A
GET
to this endpoint will return a list of all the software requirements of the specified jobtype-
GET
/api/v1/jobtypes/[<str:name>|<int:id>]/software_requirements/ HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType/software_requirements/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "software": { "software": "/bin/touch", "id": 1 }, "max_version": null, "min_version": { "version": "8.21", "id": 1 }, "jobtype_version": { "version": 7, "jobtype": "TestJobType" } } ]
Statuscode 200: no error Statuscode 404: jobtype or version not found -
-
methods
= ['GET', 'POST']¶
-
post
(jobtype_name, version=None)[source]¶ A
POST
to this endpoint will create a new software_requirement for the specified jobtype. This will transparently create a new jobtype version-
POST
/api/v1/jobtypes/[<str:name>|<int:id>]/software_requirements/ HTTP/1.1
¶ Request
POST /api/v1/jobtypes/TestJobType/software_requirements/ HTTP/1.1 Accept: application/json { "software": "blender", "min_version": "2.69" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "jobtype_version": { "id": 8, "jobtype": "TestJobType", "version": 7 }, "max_version": null, "min_version": { "id": 2, "version": "1.69" }, "software": { "id": 2, "software": "blender" } }
Statuscode 201: a new software requirement was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 405: you tried calling this method on a specific version Statuscode 409: a conflicting software requirement already exists -
-
-
class
pyfarm.master.api.jobtypes.
JobTypeVersionsIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(jobtype_name)[source]¶ A
GET
to this endpoint will return a sorted list of of all known versions of the specified jobtype.-
GET
/api/v1/jobtypes/[<str:name>|<int:id>]/versions/ HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType/versions/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [1, 2]
Statuscode 200: no error Statuscode 404: jobtype not found -
-
methods
= ['GET']¶
-
-
class
pyfarm.master.api.jobtypes.
SingleJobTypeAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(jobtype_name)[source]¶ A
DELETE
to this endpoint will delete the requested jobtype-
DELETE
/api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1
¶ Request
DELETE /api/v1/jobtypes/TestJobType HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO CONTENT
Statuscode 204: the jobtype was deleted or didn’t exist -
-
get
(jobtype_name)[source]¶ A
GET
to this endpoint will return the most recent version of the referenced jobtype, by name or id.-
GET
/api/v1/jobtypes/<str:tagname> HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "batch_contiguous": true, "classname": null, "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n", "id": 1, "version": 1, "max_batch": 1, "name": "TestJobType", "software_requirements": [ { "max_version": null, "max_version_id": null, "min_version": "8.21", "min_version_id": 1, "software": "/bin/touch", "software_id": 1 } ] }
Statuscode 200: no error Statuscode 404: jobtype or version not found -
-
methods
= ['DELETE', 'GET', 'PUT']¶
-
put
(jobtype_name)[source]¶ A
PUT
to this endpoint will create a new jobtype under the given URI. If a jobtype already exists under that URI, a new version will be created with the given data.You should only call this by id for updating an existing jobtype or if you have a reserved jobtype id. There is currently no way to reserve a jobtype id.
-
PUT
/api/v1/jobtypes/[<str:name>|<int:id>] HTTP/1.1
¶ Request
PUT /api/v1/jobtypes/TestJobType HTTP/1.1 Accept: application/json { "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "batch_contiguous": true, "classname": null, "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n", "id": 1, "max_batch": 1, "name": "TestJobType", "description": "Jobtype for testing inserts and queries", "software_requirements": [] }
Statuscode 201: a new jobtype was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.jobtypes.
VersionedJobTypeAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(jobtype_name, version)[source]¶ A
DELETE
to this endpoint will delete the requested version of the specified jobtype.-
DELETE
/api/v1/jobtypes/[<str:name>|<int:id>]/versions/<int:version> HTTP/1.1
¶ Request
DELETE /api/v1/jobtypes/TestJobType/versions/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO CONTENT
Statuscode 204: the version was deleted or didn’t exist -
-
get
(jobtype_name, version)[source]¶ A
GET
to this endpoint will return the specified version of the referenced jobtype, by name or id.-
GET
/api/v1/jobtypes/[<str:name>|<int:id>]/versions/<int:version> HTTP/1.1
¶ Request
GET /api/v1/jobtypes/TestJobType/versions/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "batch_contiguous": true, "classname": null, "name": "TestJobType", "code": "\nfrom pyfarm.jobtypes.core.jobtype import " "JobType\n\nclass TestJobType(JobType):\n" " def get_command(self):\n" " return "/usr/bin/touch"\n\n" " def get_arguments(self):\n" " return [os.path.join(" "self.assignment_data["job"]["data"]["path"], " ""%04d" % self.assignment_data["tasks"]" "[0]["frame"])]\n", "id": 1, "version": 1, "max_batch": 1, "software_requirements": [ { "max_version": null, "max_version_id": null, "min_version": "8.21", "min_version_id": 1, "software": "/bin/touch", "software_id": 1 } ] }
Statuscode 200: no error Statuscode 404: jobtype or version not found -
-
methods
= ['DELETE', 'GET']¶
-
-
pyfarm.master.api.jobtypes.
parse_requirements
(requirements)[source]¶ Takes a list dicts specifying a software and optional min- and max-versions and returns a list of
JobRequirement
objects.Raises TypeError if the input was not as expected or ObjectNotFound if a referenced software of or version was not found.
Parameters: requirements (list) – A list of of dicts specifying a software and optionally min_version and/or max_version.
Raises: - TypeError – Raised if
requirements
is not a list or if an entry inrequirements
is not a dictionary. - ValueError – Raised if there’s a problem with the content of at least one of the requirement dictionaries.
- ObjectNotFound – Raised if the referenced software or version was not found
- TypeError – Raised if
-
pyfarm.master.api.jobtypes.
schema
()[source]¶ Returns the basic schema of
JobType
-
GET
/api/v1/jobtypes/schema HTTP/1.1
¶ Request
GET /api/v1/jobtypes/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "batch_contiguous": "BOOLEAN", "classname": "VARCHAR(64)", "code": "TEXT", "description": "TEXT", "id": "INTEGER", "version": "INTEGER", "max_batch": "INTEGER", "no_automatic_start_time": "INTEGER", "name": "VARCHAR(64)" }
Statuscode 200: no error -
pyfarm.master.api.pathmaps module¶
API endpoints for viewing and managing path maps
-
class
pyfarm.master.api.pathmaps.
PathMapIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of all registered path maps, with id. It can be made with a for_agent query parameter, in which case it will return only those path maps that apply to that agent.-
GET
/api/v1/pathmaps/ HTTP/1.1
¶ Request
GET /api/v1/pathmaps/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "id": 1, "path_osx": "/mnt/nfs", "path_windows": "\\domains\cifs_server", "path_linux": "/mnt/nfs" }, { "id": 7, "path_osx": "/renderout", "path_windows": "c:\renderout", "path_linux": "/renderout" "tag": "usual", } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will create a new path map.A path map will list the equivalent path prefixes for all three supported families of operating systems, Linux, Windows and OS X. A path map can optionally be restricted to one tag, in which case it will only apply to agents with that tag. If a tag is specified that does not exist yet, that tag will be transparently created.
-
POST
/api/v1/pathmaps/ HTTP/1.1
¶ Request
POST /api/v1/pathmaps/ HTTP/1.1 Accept: application/json { "path_linux": "/mnt/nfs", "path_windows": "\domain\cifs_server", "path_osx": "/mnt/nfs", "tag": "production" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "path_linux": "/mnt/nfs", "path_windows": "\domain\cifs_server", "path_osx": "/mnt/nfs", "tag": "production" }
Statuscode 201: a new pathmap was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.pathmaps.
SinglePathMapAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(pathmap_id)[source]¶ A
DELETE
to this endpoint will remove the specified pathmap-
DELETE
/api/v1/pathmaps/<int:pathmap_id> HTTP/1.1
¶ Request
DELETE /api/v1/pathmaps/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the path map was deleted or did not exist in the first place -
-
get
(pathmap_id)[source]¶ A
GET
to this endpoint will return a single path map specified by pathmap_id-
GET
/api/v1/pathmaps/<int:pathmap_id> HTTP/1.1
¶ Request
GET /api/v1/pathmaps/1 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "path_osx": "/mnt/nfs", "path_windows": "\\domains\cifs_server", "path_linux": "/mnt/nfs" }
Statuscode 200: no error -
-
methods
= ['DELETE', 'GET', 'POST']¶
-
post
(pathmap_id)[source]¶ A
POST
to this endpoint will update an existing path map with new values.Only the values included in the request will be updated. The rest will be left unchanged. The id column cannot be changed. Including it in the request will lead to an error.
-
POST
/api/v1/pathmaps/<int:pathmap_id> HTTP/1.1
¶ Request
POST /api/v1/pathmaps/1 HTTP/1.1 Accept: application/json { "path_linux": "/mnt/smb" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "path_linux": "/mnt/smb", "path_windows": "\domain\cifs_server", "path_osx": "/mnt/nfs", "tag": "production" }
Statuscode 200: the specified pathmap was updated Statuscode 404: the specified pathmap does not exist Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
pyfarm.master.api.pathmaps.
schema
()[source]¶ Returns the basic schema of
Agent
-
GET
/api/v1/pathmaps/schema HTTP/1.1
¶ Request
GET /api/v1/pathmaps/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": "INTEGER", "path_linux": "VARCHAR(512)", "path_windows": "VARCHAR(512)", "path_osx": "VARCHAR(512)", "tag": "VARCHAR(64)" }
Statuscode 200: no error -
pyfarm.master.api.software module¶
Contained within this module are an API handling functions which can manage or query software items using JSON.
-
class
pyfarm.master.api.software.
SingleSoftwareAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(software_rq)[source]¶ A
DELETE
to this endpoint will delete the requested software tag-
DELETE
/api/v1/software/<str:softwarename> HTTP/1.1
¶ Request
DELETE /api/v1/software/Autodesk%20Maya HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the software tag was deleted or didn’t exist -
-
get
(software_rq)[source]¶ A
GET
to this endpoint will return the requested software tag-
GET
/api/v1/software/<str:softwarename> HTTP/1.1
¶ Request
GET /api/v1/software/Autodesk%20Maya HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "software": "Autodesk Maya", "id": 1, "versions": [ { "version": "2013", "id": 1, "rank": 100 }, { "version": "2014", "id": 2, "rank": 200 } ] }
Statuscode 200: no error Statuscode 404: the requested software tag was not found -
-
methods
= ['DELETE', 'GET', 'PUT']¶
-
put
(software_rq)[source]¶ A
PUT
to this endpoint will create a new software tag under the given URI or update an existing software tag if one exists. Renaming existing software tags via this call is supported, but when creating new ones, the included software name must be equal to the one in the URI.You should only call this by id for overwriting an existing software tag or if you have a reserved software id. There is currently no way to reserve a tag id.
-
PUT
/api/v1/software/<str:softwarename> HTTP/1.1
¶ Request
PUT /api/v1/software/blender HTTP/1.1 Accept: application/json { "software": "blender" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 4, "software": "blender", "versions": [] }
Request
PUT /api/v1/software/blender HTTP/1.1 Accept: application/json { "software": "blender", "version": [ { "version": "1.69" } ] }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 4, "software": "blender", "versions": [ { "version": "1.69", "id": 1, "rank": 100 } ] }
Statuscode 200: an existing software tag was updated Statuscode 201: a new software tag was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) -
-
-
class
pyfarm.master.api.software.
SingleSoftwareVersionAPI
[source]¶ Bases:
flask.views.MethodView
-
delete
(software_rq, version_name)[source]¶ A
DELETE
to this endpoint will delete the requested software version-
DELETE
/api/v1/software/<str:softwarename>/versions/<str:version> HTTP/1.1
¶ Request
DELETE /api/v1/software/Autodesk%20Maya/versions/2013 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 204 NO_CONTENT
Statuscode 204: the software version was deleted or didn’t exist Statuscode 404: the software specified does not exist -
-
get
(software_rq, version_name)[source]¶ A
GET
to this endpoint will return the specified version-
GET
/api/v1/software/<str:softwarename>/versions/<str:version> HTTP/1.1
¶ Request
GET /api/v1/software/Autodesk%20Maya/versions/2014 HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "version": "2013", "id": 1, "rank": 100, "discovery_function_name": null }
Statuscode 200: no error Statuscode 404: the requested software tag or version was not found -
-
methods
= ['DELETE', 'GET']¶
-
-
class
pyfarm.master.api.software.
SoftwareIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
()[source]¶ A
GET
to this endpoint will return a list of known software, with all known versions.-
GET
/api/v1/software/ HTTP/1.1
¶ Request
GET /api/v1/software/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "software": "Houdini", "id": 1, "versions": [ { "version": "13.0.1", "id": 1, "rank": 100 } ] } ]
Statuscode 200: no error -
-
methods
= ['GET', 'POST']¶
-
post
()[source]¶ A
POST
to this endpoint will create a new software tag.A list of versions can be included. If the software item already exists the listed versions will be added to the existing ones. Versions with no explicit rank are assumed to be the newest version available. Users should not mix versions with an explicit rank with versions without one.
-
POST
/api/v1/software/ HTTP/1.1
¶ Request
POST /api/v1/software/ HTTP/1.1 Accept: application/json { "software": "blender" }
Response (new software item create)
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 4, "software": "blender", "versions": [] }
Statuscode 201: a new software item was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 409: a software tag with that name already exists -
-
-
class
pyfarm.master.api.software.
SoftwareVersionDiscoveryCodeAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(software_rq, version_name)[source]¶ A
GET
to this endpoint will return just the python code for detecting whether this software version is installed on an agent.-
GET
/api/v1/software/[<str:software_name>|<int:software_id>]/versions/<str:version>/code HTTP/1.1
¶ Request
GET /api/v1/software/Blender/versions/2.72/code HTTP/1.1 Accept: text/x-python
Response
HTTP/1.1 200 OK Content-Type: text/x-python def blender_2_72_installed() return True
Statuscode 200: no error Statuscode 404: software or version not found or this software version has no discovery code defined -
-
methods
= ['GET']¶
-
-
class
pyfarm.master.api.software.
SoftwareVersionsIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(software_rq)[source]¶ A
GET
to this endpoint will list all known versions for this software-
GET
/api/v1/software/<str:softwarename>/versions/ HTTP/1.1
¶ Request
GET /api/v1/software/Autodesk%20Maya/versions/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "version": "2013", "id": 1, "rank": 100 }, { "version": "2014", "id": 2, "rank": 200 } ]
Statuscode 200: no error Statuscode 404: the requested software tag was not found -
-
methods
= ['GET', 'POST']¶
-
post
(software_rq)[source]¶ A
POST
to this endpoint will create a new version for this software.A rank can optionally be included. If it isn’t, it is assumed that this is the newest version for this software
-
POST
/api/v1/software/versions/ HTTP/1.1
¶ Request
POST /api/v1/software/blender/versions/ HTTP/1.1 Accept: application/json { "version": "1.70" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 4, "version": "1.70", "rank": "100" }
Statuscode 201: a new software version was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 409: a software version with that name already exists -
-
-
exception
pyfarm.master.api.software.
VersionParseError
[source]¶ Bases:
Exception
Raised by
extract_version_dicts()
when the function is unable to parse a version.
-
pyfarm.master.api.software.
extract_version_dicts
(json_in)[source]¶ Extracts and returns a list of versions from
json_in
.
-
pyfarm.master.api.software.
schema
()[source]¶ Returns the basic schema of
Software
-
GET
/api/v1/software/schema HTTP/1.1
¶ Request
GET /api/v1/software/schema HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": "INTEGER", "software": "VARCHAR(64)" }
Statuscode 200: no error -
pyfarm.master.api.tags module¶
Contained within this module are an API handling functions which can manage or query tags using JSON.
Bases:
flask.views.MethodView
A
GET
to this endpoint will list all agents associated with this tag.Request
GET /api/v1/tags/interesting/agents/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 201 CREATED Content-Type: application/json [ { "hostname": "agent3", "id": 1, "href": "/api/v1/agents/1 } ]
Statuscode 200: the list of agents associated with this tag is returned Statuscode 404: the tag specified does not exist
A
POST
will add an agent to the list of agents tagged with this tag The tag can be given as a string or as an integer (its id).Request
POST /api/v1/tags/interesting/agents/ HTTP/1.1 Accept: application/json { "agent_id": "dd0c6da2-0c91-42cf-a82f-6d503aae43d3" }
Response (agent newly tagged)
HTTP/1.1 201 CREATED Content-Type: application/json { "href": "/api/v1/agents/1", "id": 1 }
Request
POST /api/v1/tags/interesting/agents/ HTTP/1.1 Accept: application/json { "agent_id": "dd0c6da2-0c91-42cf-a82f-6d503aae43d3" }
Response (agent already had that tag)
HTTP/1.1 200 OK Content-Type: application/json { "href": "/api/v1/agents/1", "id": 1 }
Statuscode 200: an existing tag was found and returned Statuscode 201: a new tag was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: either the tag or the referenced agent does not exist
Bases:
flask.views.MethodView
A
DELETE
to this endpoint will delete the tag under this URI, including all relations to tags or jobs.Request
DELETE /api/v1/tags/interesting HTTP/1.1 Accept: application/json
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" }
Statuscode 204: the tag was deleted or did not exist in the first place
A
GET
to this endpoint will return the referenced tag, either by name or id, including a list of agents and jobs associated with it.Request
GET /api/v1/tags/interesting HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "agents": [{ "hostname": "agent3", "href": "/api/v1/agents/94522b7e-817b-4358-95da-670b31aad624", "id": 1 }], "id": 1, "jobs": [], "tag": "interesting" }
Statuscode 200: no error Statuscode 404: tag not found
A
PUT
to this endpoint will create a new tag under the given URI. If a tag already exists under that URI, it will be deleted, then recreated. Note that when overwriting a tag like that, all relations that are not explicitly specified here will be deleted You can optionally specify a list of agents or jobs relations as integers in the request data.You should only call this by id for overwriting an existing tag or if you have a reserved tag id. There is currently no way to reserve a tag id.
Request
PUT /api/v1/tags/interesting HTTP/1.1 Accept: application/json { "tag": "interesting" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" }
Request
PUT /api/v1/tags/interesting HTTP/1.1 Accept: application/json { "tag": "interesting", "agents": [1] "jobs": [] }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" }
Statuscode 201: a new tag was created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: a referenced agent or job does not exist
Bases:
flask.views.MethodView
A
GET
to this endpoint will return a list of known tags, with id. Associated agents and jobs are included for every tag:rtype : object .. http:get:: /api/v1/tags/ HTTP/1.1
Request
GET /api/v1/tags/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "agents": [ 1 ], "jobs": [], "id": 1, "tag": "interesting" }, { "agents": [], "jobs": [], "id": 2, "tag": "boring" } ]
Statuscode 200: no error
A
POST
to this endpoint will do one of two things:- create a new tag and return the row
- return the row for an existing tag
Tags only have one column, the tag name. Two tags are automatically considered equal if the tag names are equal.
Request
POST /api/v1/tags/ HTTP/1.1 Accept: application/json { "tag": "interesting" }
Response (new tag create)
HTTP/1.1 201 CREATED Content-Type: application/json { "id": 1, "tag": "interesting" }
Request
POST /api/v1/tags/ HTTP/1.1 Accept: application/json { "tag": "interesting" }
Response (existing tag returned)
HTTP/1.1 200 OK Content-Type: application/json { "id": 1, "tag": "interesting" }
Statuscode 200: an existing tag was found and returned Statuscode 201: a new tag was created Statuscode 400: there was something wrong with the request (such as invalid columns being included)
Returns the basic schema of
Tag
Request
GET /api/v1/tags/schema/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": "INTEGER", "tag": "VARCHAR(64)" }
Statuscode 200: no error
pyfarm.master.api.tasklogs module¶
This module defines an API for managing and querying logs belonging to tasks
-
class
pyfarm.master.api.tasklogs.
LogsInTaskAttemptsIndexAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_id, task_id, attempt)[source]¶ A
GET
to this endpoint will return a list of all known logs that are associated with this attempt at running this task-
GET
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/ HTTP/1.1
¶ Request
GET /api/v1/jobs/4/tasks/1300/attempts/5/logs/ HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json [ { "agent_id": "3087ada4-290a-45b0-8c1a-21db4cd284fc", "created_on": "2014-09-03T10:58:59.754880", "identifier": "2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv" } ]
Statuscode 200: no error Statuscode 404: the specified task was not found -
-
methods
= ['GET', 'POST']¶
-
post
(job_id, task_id, attempt)[source]¶ A
POST
to this endpoint will register a new logfile with the given attempt at running the given taskA logfile has an identifier which must be unique in the system. If two tasks get assigned a logfile with the same id, it is considered to be the same log.
-
POST
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/ HTTP/1.1
¶ Request
POST /api/v1/jobs/4/tasks/1300/attempts/5/logs/ HTTP/1.1 Content-Type: application/json { "identifier": "2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv", "agent_id": "2dc2cb5a-35da-41d6-8864-329c0d7d5391" }
Response
HTTP/1.1 201 CREATED Content-Type: application/json { "identifier": "2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv", "agent_id": "2dc2cb5a-35da-41d6-8864-329c0d7d5391", "created_on": "2014-09-03T10:59:05.103005", "id": 148 }
Statuscode 201: the association between this task attempt and logfile has been created Statuscode 400: there was something wrong with the request (such as invalid columns being included) Statuscode 404: the specified task does not exist Statuscode 409: the specified log was already registered on the specified task -
-
-
class
pyfarm.master.api.tasklogs.
SingleLogInTaskAttempt
[source]¶ Bases:
flask.views.MethodView
-
get
(job_id, task_id, attempt, log_identifier)[source]¶ A
GET
to this endpoint will return metadata about the specified logfile-
GET
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/<log_identifier> HTTP/1.1
¶ Request
GET /api/v1/jobs/4/tasks/1300/attempts/5/logs/2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv HTTP/1.1 Accept: application/json
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 147, "identifier": "2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv", "created_on": "2014-09-03T10:58:59.754880", "agent_id": "836ce137-6ad4-443f-abb9-94c4465ff87c" }
Statuscode 200: no error Statuscode 404: task or logfile not found -
-
methods
= ['GET', 'POST']¶
-
post
(job_id, task_id, attempt, log_identifier)[source]¶ A
POST
to this endpoint will update metadata about the specified logfile-
POST
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/<log_identifier> HTTP/1.1
¶ Request
POST /api/v1/jobs/4/tasks/1300/attempts/5/logs/2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv HTTP/1.1 Accept: application/json Content-Type: application/json { "state": "done" }
Response
HTTP/1.1 200 OK Content-Type: application/json { "id": 147, "identifier": "2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv", "created_on": "2014-09-03T10:58:59.754880", "agent_id": "836ce137-6ad4-443f-abb9-94c4465ff87c" }
Statuscode 200: no error Statuscode 404: task or logfile not found -
-
-
class
pyfarm.master.api.tasklogs.
TaskLogfileAPI
[source]¶ Bases:
flask.views.MethodView
-
get
(job_id, task_id, attempt, log_identifier)[source]¶ A
GET
to this endpoint will return the actual logfile or a redirect to it.-
GET
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/<log_identifier>/logfile HTTP/1.1
¶ Request
GET /api/v1/jobs/4/tasks/1300/attempts/5/logs/2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv/logfile HTTP/1.1 Accept: text/csv
Response
HTTP/1.1 200 OK Content-Type: text/csv <Content of the logfile>
Statuscode 200: no error Statuscode 307: The logfile can be found in another location at this point in time. Independent future requests for the same logfile should continue using the original URL Statuscode 400: the specified logfile identifier is not acceptable Statuscode 404: task or logfile not found -
-
methods
= ['GET', 'PUT']¶
-
put
(job_id, task_id, attempt, log_identifier)[source]¶ A
PUT
to this endpoint will upload the request’s body as the specified logfile-
PUT
/api/v1/jobs/<job_id>/tasks/<task_id>/attempts/<attempt>/logs/<log_identifier>/logfile HTTP/1.1
¶ Request
PUT /api/v1/jobs/4/tasks/1300/attempts/5/logs/2014-09-03_10-58-59_4_4ee02475335911e4a935c86000cbf5fb.csv/logfile HTTP/1.1 <content of the logfile>
Response
HTTP/1.1 201 CREATED
Statuscode 201: lofile was uploaded Statuscode 400: the specified logfile identifier is not acceptable Statuscode 404: task or logfile not found -
-
Module contents¶
pyfarm.master.user_interface package¶
Subpackages¶
pyfarm.master.user_interface.statistics package¶
Submodules¶
pyfarm.master.user_interface.agents module¶
pyfarm.master.user_interface.jobgroups module¶
pyfarm.master.user_interface.jobqueues module¶
pyfarm.master.user_interface.jobs module¶
pyfarm.master.user_interface.jobtypes module¶
UI endpoints allowing seeing and manipulating jobtypes via the web interface
-
pyfarm.master.user_interface.jobtypes.
jobtype
(jobtype_id)[source]¶ UI endpoint for a single jobtype. Allows showing and updating the jobtype
Module contents¶
Submodules¶
pyfarm.master.application module¶
Application¶
Contains the functions necessary to construct the application layer classes necessary to run the master.
-
class
pyfarm.master.application.
SessionMixin
[source]¶ Bases:
object
Mixin which adds a
_session
attribute. This class is provided mainly to limit issues with circular imports.
-
class
pyfarm.master.application.
UUIDConverter
(map)[source]¶ Bases:
werkzeug.routing.BaseConverter
A URL converter for UUIDs. This class is loaded as part of the Flask application setup and may be used in url routing:
@app.route('/foo/<uuid:value>') def foobar(value): pass
When a request such as
GET /foo/F9A63B47-66BF-4E2B-A545-879986BB7CA9
is madeUUIDConverter
will receivevalue
toto_python()
which will then convert the string to an instance ofUUID
.
-
pyfarm.master.application.
before_request
()[source]¶ Global before_request handler that will handle common problems when trying to accept json data to the api.
-
pyfarm.master.application.
get_api_blueprint
(url_prefix=None)[source]¶ Constructs and returns an instance of
Blueprint
for routing api requests.Parameters: url_prefix (string) – The url prefix for the api such as /api/v1
. If not provided then value will be derived from the api_prefix configuration variable.
-
pyfarm.master.application.
get_application
(**configuration_keywords)[source]¶ Returns a new application context. If keys and values are provided to
config_values
they will be used to override the default configuration values or create new ones>>> app = get_application(TESTING=True) >>> assert app.testing is True
Parameters: setup_appcontext (bool) – If True
then setup theflask.g
variable to include the application level information (ex.g.db
)
-
pyfarm.master.application.
get_login_manager
(**kwargs)[source]¶ Constructs and returns an instance of
LoginManager
. Any keyword arguments provided will be passed to the constructor ofLoginManager
pyfarm.master.config module¶
Configuration¶
A small wrapper around pyfarm.core.config.Configuration
that loads in the configuration files and provides backwards
compatibility for some environment variables.
-
class
pyfarm.master.config.
Configuration
[source]¶ Bases:
pyfarm.core.config.Configuration
The main configuration object for the master, models and scheduler. This will load in the configuration files and also handle any overrides present in the environment.
Variables: ENVIRONMENT_OVERRIDES – A dictionary containing all environment variables we support as overrides. This set is mainly provided for backwards comparability purposes or for the rare case where an environment override would be preferred over a config. -
ENVIRONMENT_OVERRIDES
= {'allow_agents_from_loopback': ('PYFARM_DEV_ALLOW_AGENT_LOOPBACK_ADDRESSES', <function read_env_bool at 0x7f1ce401be18>), 'farm_name': ('PYFARM_FARM_NAME', <function read_env at 0x7f1ce40b6ea0>), 'tasklogs_dir': ('PYFARM_LOGFILES_DIR', <function read_env at 0x7f1ce40b6ea0>), 'dev_db_drop_all': ('PYFARM_DEV_APP_DB_DROP_ALL', functools.partial(<function read_env_bool at 0x7f1ce401be18>, default=False)), 'secret_key': ('PYFARM_SECRET_KEY', functools.partial(<function read_env at 0x7f1ce40b6ea0>, log_result=False)), 'agent_request_timeout': ('PYFARM_AGENT_REQUEST_TIMEOUT', functools.partial(<function read_env_strict_number at 0x7f1ce401d158>, number_type=<class 'int'>)), 'autocreate_users': ('PYFARM_AUTOCREATE_USERS', <function read_env_bool at 0x7f1ce401be18>), 'echo_sql': ('PYFARM_SQL_ECHO', <function read_env_bool at 0x7f1ce401be18>), 'database': ('PYFARM_DATABASE_URI', functools.partial(<function read_env at 0x7f1ce40b6ea0>, log_result=False)), 'agent_updates_webdir': ('PYFARM_AGENT_UPDATES_WEBDIR', <function read_env at 0x7f1ce40b6ea0>), 'pretty_json': ('PYFARM_JSON_PRETTY', <function read_env_bool at 0x7f1ce401be18>), 'instance_application': ('PYFARM_APP_INSTANCE', functools.partial(<function read_env_bool at 0x7f1ce401be18>, default=False)), 'dev_db_create_all': ('PYFARM_DEV_APP_DB_CREATE_ALL', functools.partial(<function read_env_bool at 0x7f1ce401be18>, default=False)), 'from_email': ('PYFARM_FROM_ADDRESS', <function read_env at 0x7f1ce40b6ea0>), 'scheduler_broker': ('PYFARM_SCHEDULER_BROKER', <function read_env at 0x7f1ce40b6ea0>), 'agent_updates_dir': ('PYFARM_AGENT_UPDATES_DIR', <function read_env at 0x7f1ce40b6ea0>), 'transaction_retries': ('PYFARM_TRANSACTION_RETRIES', functools.partial(<function read_env_strict_number at 0x7f1ce401d158>, number_type=<class 'int'>)), 'base_url': ('PYFARM_BASE_URL', <function read_env at 0x7f1ce40b6ea0>), 'timestamp_format': ('PYFARM_TIMESTAMP_FORMAT', <function read_env at 0x7f1ce40b6ea0>), 'login_disabled': ('PYFARM_LOGIN_DISABLED', <function read_env_bool at 0x7f1ce401be18>), 'default_job_delete_time': ('PYFARM_DEFAULT_JOB_DELETE_TIME', functools.partial(<function read_env_strict_number at 0x7f1ce401d158>, number_type=<class 'int'>)), 'scheduler_lockfile_base': ('PYFARM_SCHEDULER_LOCKFILE_BASE', <function read_env at 0x7f1ce40b6ea0>), 'smtp_server': ('PYFARM_MAIL_SERVER', <function read_env at 0x7f1ce40b6ea0>)}¶
-
pyfarm.master.entrypoints module¶
Entry Points¶
Contains the code which operates the Python entry point scripts as well as serving as a central location for the construction of the web application.
-
pyfarm.master.entrypoints.
create_app
()[source]¶ An entry point specifically for uWSGI or similar to use
-
pyfarm.master.entrypoints.
load_api
(app_instance, api_instance)[source]¶ configures flask to serve the api endpoints
-
pyfarm.master.entrypoints.
load_authentication
(app_instance)[source]¶ configures flask to serve the authentication endpoints
-
pyfarm.master.entrypoints.
load_error_handlers
(app_instance)[source]¶ loads the error handlers onto application instance
-
pyfarm.master.entrypoints.
load_index
(app_instance)[source]¶ configures flask to serve the main index and favicon
-
pyfarm.master.entrypoints.
load_master
(app, api)[source]¶ loads and attaches all endpoints needed to run the master
-
pyfarm.master.entrypoints.
load_setup
(app_instance)[source]¶ configures flask to serve the endpoint used for setting up the system
-
pyfarm.master.entrypoints.
run_master
()[source]¶ Runs
load_master()
then runs the application
pyfarm.master.index module¶
pyfarm.master.initial module¶
Initial Setup¶
Entry points for the /setup/ target
-
class
pyfarm.master.initial.
NewUserForm
(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)[source]¶ Bases:
wtforms.form.Form
-
email
= <UnboundField(TextField, (), {'validators': [<wtforms.validators.Required object at 0x7f1ce1e781d0>]})>¶
-
password
= <UnboundField(PasswordField, (), {'validators': [<wtforms.validators.Required object at 0x7f1ce1e780f0>]})>¶
-
username
= <UnboundField(TextField, (), {'validators': [<wtforms.validators.Required object at 0x7f1ce1e87d68>]})>¶
-
pyfarm.master.testutil module¶
Test Utilities¶
Functions and classes mainly used during the unittests.
-
class
pyfarm.master.testutil.
BaseTestCase
(methodName='runTest')[source]¶ Bases:
unittest.case.TestCase
-
ENVIRONMENT_SETUP
= False¶
-
ORIGINAL_ENVIRONMENT
= {'SUPERVISOR_SERVER_URL': 'unix:///var/run/supervisor.sock', 'LOGNAME': 'root', 'DJANGO_PROJECT_DIR': '/home/docs/checkouts/readthedocs.org', 'LESSCLOSE': '/usr/bin/lesspipe %s %s', 'MAIL': '/var/mail/root', 'TERM': 'screen', 'SHELL': '/bin/bash', 'TZ': 'America/Chicago', 'HOME': '/home/docs', 'NEW_RELIC_PYTHON_PREFIX': '/home/docs', 'READTHEDOCS': 'True', '_MP_FORK_LOGFILE_': '/home/docs/log/celery_proc.log', '_MP_FORK_LOGLEVEL_': '20', 'SSH_TTY': '/dev/pts/2', 'NEW_RELIC_PYTHON_VERSION': '2.7', 'LESSOPEN': '| /usr/bin/lesspipe %s', 'SSH_CLIENT': '75.175.74.79 53328 22', 'USER': 'docs', 'CELERY_LOG_FILE': '/home/docs/log/celery_proc.log', 'XDG_SESSION_ID': '1013146', 'CELERY_LOG_REDIRECT': '1', 'SHLVL': '1', 'CELERY_LOG_LEVEL': '20', '_MP_FORK_LOGFORMAT_': '[%(asctime)s: %(levelname)s/%(processName)s] %(message)s', 'CELERY_LOADER': 'djcelery.loaders.DjangoLoader', 'PIP_DOWNLOAD_CACHE': '/tmp/pip', '_': '/etc/init.d/supervisor', 'PATH': '/home/docs/checkouts/readthedocs.org/user_builds/pyfarm-master/envs/latest/bin:/home/docs/bin:/usr/local/bin:/usr/bin:/bin:/home/docs/.dnx/bin/:/home/docs/.dnx/runtimes/dnx-mono.1.0.0-beta6/bin/', 'NEW_RELIC_CONFIG_FILE': '/home/docs/newrelic.ini', 'SSH_CONNECTION': '75.175.74.79 53328 162.242.232.51 22', 'PWD': '/root', 'XDG_RUNTIME_DIR': '/run/user/0', 'SUPERVISOR_PROCESS_NAME': 'build', 'SUPERVISOR_GROUP_NAME': 'build', 'CELERY_LOG_REDIRECT_LEVEL': 'WARNING', 'LANG': 'en_US.UTF-8', 'SSH_AUTH_SOCK': '/tmp/ssh-wavlhIgMsO/agent.27659', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:', 'SUPERVISOR_ENABLED': '1'}¶
-
assert_contents_equal
(a_source, b_source)[source]¶ Explicitly check to see of the two iterable objects contain the same data. This method exists to check to make sure two iterables contain the same data without regards to order. This is mostly meant for cases where two lists contain unhashable types.
-
classmethod
build_environment
()[source]¶ Sets up the current environment with some values for unittesting. This must be used before any other code is imported otherwise
Warning
This classmethod should not be used outside of a testing context
-
maxDiff
= None¶
-
pyfarm.master.utility module¶
Utility¶
General utility which are not view or tool specific
-
class
pyfarm.master.utility.
JSONEncoder
(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, default=None)[source]¶ Bases:
json.encoder.JSONEncoder
-
pyfarm.master.utility.
assert_mimetypes
(flask_request, mimetypes)[source]¶ Warning
This function will produce an unhandled error if you use it outside of a request.
Check to make sure that the request’s mimetype is in
mimetypes
. If this is not true then callflask.abort()
withUNSUPPORTED_MEDIA_TYPE
Parameters: - flask_request – The flask request object which we should check the
mimetype
attribute on. - mimetypes (list, tuple, set) – The mimetypes which
flask_request
can be.
- flask_request – The flask request object which we should check the
-
pyfarm.master.utility.
dumps
(obj, **kwargs)[source]¶ Wrapper for
json.dumps()
that ensuresJSONEncoder
is passed in.
-
pyfarm.master.utility.
error_handler
(e, code=None, default=None, title=None, template=None)[source]¶ Constructor for http errors that respects the current mimetype. By default this function returns html however when
request.mimetype
isapplication/json
it will return a json response. This function is typically used within afunctools.partial()
call:>>> from functools import partial >>> try: ... from httplib import BAD_REQUEST ... except ImportError: ... from http.client import BAD_REQUEST ... >>> from flask import request >>> error_400 = partial( ... error_handler, BAD_REQUEST, ... lambda: "bad request to %s" % request.url, "Bad Request")
Parameters: - e (flask.Response) – The response object which will be passed into
error_handler()
, this value is ignored by default. - code (int) – The integer to use in the response. For the most consistent
results you can use the
httplib
orhttp.client
modules depending on your Python version. - default (callable) – This will be the default error message if g.error does not
contain anything.
default
may either be a callable function which will produce the string or it may be a string by itself. - title (str) – The HTML title of the request being made. This is not used when dealing with json requests and if not provided at all will default to using the official status code’s string representation.
- template (str) – A alternative template path for HTML responses
- e (flask.Response) – The response object which will be passed into
-
pyfarm.master.utility.
get_g
(attribute, instance_types, unset=<object object>)[source]¶ Returns data from
flask.g
after checking to make sure the attribute was set and that it has the correct type.This function does not check to see if you’re already inside a request.
Parameters:
-
pyfarm.master.utility.
get_request_argument
(argument, default=None, required=False, types=None)[source]¶ This is a function similar to Flask’s
request.args.get
except it does type validation and it has the concept of required url arguments.Parameters: - argument (str) – The name of the url argument we’re trying to retrieve
- default – The value to return if
argument
is not present in the url and argument is not a required parameter. - required (bool) – If True and the url argument provided by
argument
is not provided respond to the request withBAD_REQUEST
- types –
A single or list of multiple callable objects which will be used to try and produce a result to return. This would function similarly to this:
value = "5" types = (int, bool) for type_callable in types: try: return type_callable(value) except Exception: continue
-
pyfarm.master.utility.
inside_request
()[source]¶ Returns True if we’re inside a request, False if not.
-
pyfarm.master.utility.
isuuid
(value)[source]¶ Returns True if
value
is aUUID
object or can be converted to one
-
pyfarm.master.utility.
jsonify
(*args, **kwargs)[source]¶ Drop in replacement for
flask.jsonify()
that also handles list objects as well as a few custom objects like Decimal or datetime. Flask does not support lists by default because it’s considered a security risk in most cases but we do need it in certain cases. Since flask’s jsonify does not allow passing arbitrary arguments tojson.dumps()
, we cannot use it if the output data contains custom types.
-
pyfarm.master.utility.
timedelta_format
(value)[source]¶ Formats a timedelta object without the microseconds
-
pyfarm.master.utility.
validate_json
(validator, json_types=(<class 'dict'>, ))[source]¶ A decorator, similar to
validate_with_model()
, but greatly simplified and more flexible. Unlikevalidate_with_model()
this decorator is meant to handle data which may not be structured for a model.Parameters:
-
pyfarm.master.utility.
validate_with_model
(model, type_checks=None, ignore=None, ignore_missing=None, disallow=None)[source]¶ Decorator which will check the contents of the of the json request against a model for:
- missing fields which are required
- values which don’t match their type(s) in the database
- inclusion of fields which do not exist
Parameters: - model – The model object that the decorated endpoint should use for testing the points above.
- type_checks (dict) – A dictionary containing a mapping of column names to special functions used for checking. If there’s a key in the incoming request that needs a more detailed check than “isinstance(g.json[column_name], <Python type(s) from sql>)” then this is the place to add it.
- ignore_missing (list) – A list of fields to completely ignore in the incoming
request. Typically this is used by
PUT
requests or other similar requests where part of the data is in the url. - allow_missing (list) – A list of fields which are allowed to be missing in the request. These fields will still be checked for type however.
- disallow (list) – A list of columns which are never in the request to the decorated function
Module contents¶
Contains all the necessary code to operate an instance of the master.
pyfarm.models package¶
Subpackages¶
pyfarm.models.core package¶
Submodules¶
pyfarm.models.core.functions module¶
Contains core functions and data for use by pyfarm.models
-
pyfarm.models.core.functions.
getuuid
(value, table, table_attrib, error_tail)[source]¶ Returns the proper value for the given input. Depending on the type being provided this will return one of the following:
- None
- the value from an attribute
- string from a UUID
- the original value (after validating it’s a UUID)
Parameters: - value (string) – the value to validate and returning data from
- table (string) – the table which the provided value belongs to
- table_attrib (string) – the attribute to use when attempting to pull data off of a model object
- error_tail (string) – added to the end of error messages
- error_text (str) – error text to render in the event of problems
Raises ValueError: raised when the provided input is invalid, blank, or otherwise unexpected
-
pyfarm.models.core.functions.
modelfor
(model, table)[source]¶ Returns True if the given model object is for the expected table.
>>> from pyfarm.master.config import config >>> from pyfarm.models.agent import Agent >>> modelfor(Agent("foo", "10.56.0.0", "255.0.0.0"), config.get("table_agent")) True
-
pyfarm.models.core.functions.
repr_enum
(value, enum=None)[source]¶ produces the string representation of an enum value
pyfarm.models.core.mixins module¶
Module containing mixins which can be used by multiple models.
-
class
pyfarm.models.core.mixins.
ModelTypes
(primary_keys, autoincrementing, columns, required, relationships, mappings)¶ Bases:
tuple
-
autoincrementing
¶ Alias for field number 1
-
columns
¶ Alias for field number 2
-
mappings
¶ Alias for field number 5
-
primary_keys
¶ Alias for field number 0
-
relationships
¶ Alias for field number 4
-
required
¶ Alias for field number 3
-
-
class
pyfarm.models.core.mixins.
ReprMixin
[source]¶ Bases:
object
Mixin which allows model classes to to convert columns into a more easily read object format.
Variables: - REPR_COLUMNS (tuple) – the columns to convert
- REPR_CONVERT_COLUMN (dict) – optional dictionary containing columns names and functions for converting to a more readable string format
-
REPR_COLUMNS
= NotImplemented¶
-
REPR_CONVERT_COLUMN
= {}¶
-
class
pyfarm.models.core.mixins.
UtilityMixins
[source]¶ Bases:
object
Mixins which can be used to produce dictionaries of existing data.
Const dict DICT_CONVERT_COLUMN: A dictionary containing key value pairs of attribute names and a function to retrieve the attribute. The function should take a single input and return the value itself. Optionally, you can also use the NotImplemented
object to exclude some columns from the results.-
DICT_CONVERT_COLUMN
= {}¶
-
to_dict
(unpack_relationships=True)[source]¶ Produce a dictionary of existing data in the table
Parameters: unpack_relationships (list, tuple, set, bool) – If True
then unpack all relationships. Ifunpack_relationships
is an iterable such as a list or tuple object then only unpack those relationships.
-
classmethod
to_schema
()[source]¶ Produce a dictionary which represents the table’s schema in a basic format
-
classmethod
types
()[source]¶ A classmethod that constructs a
namedtuple
object with four attributes:- primary_keys - set of all primary key(s) names
- autoincrementing - set of all columns which have autoincrement set
- columns - set of all column names
- required - set of all required columns (non-nullable wo/defaults)
- relationships - not columns themselves but do store relationships
- mappings - contains a dictionary with each field mapping to a Python type
-
-
class
pyfarm.models.core.mixins.
ValidatePriorityMixin
[source]¶ Bases:
object
Mixin that adds a state column and uses a class level STATE_ENUM attribute to assist in validation.
-
MAX_PRIORITY
= 1000¶
-
MIN_PRIORITY
= -1000¶
-
pyfarm.models.core.types module¶
Special column types used by PyFarm’s models.
-
class
pyfarm.models.core.types.
AgentStateEnum
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.EnumType
custom column type for working with
AgentState
-
enum
= AgentState(RUNNING=Values(203, 'running'), ONLINE=Values(202, 'online'), DISABLED=Values(200, 'disabled'), OFFLINE=Values(201, 'offline'))¶
-
-
class
pyfarm.models.core.types.
EnumType
(*args, **kwargs)[source]¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
Special column type which handles translation from a human readable enum into an integer that the database can use.
Variables: enum – required class level variable which defines what enum this custom column handles Raises AssertionError: raised if enum
is not set on the class-
enum
= NotImplemented¶
-
impl
¶ alias of
Integer
-
json_types
= (<class 'str'>, <class 'int'>)¶
-
process_bind_param
(value, dialect)[source]¶ Takes
value
and maps it to the internal integer.Raises ValueError: raised if value
is not part of the class levelenum
mapping
-
-
class
pyfarm.models.core.types.
IPAddress
(addr, version=None, flags=0)[source]¶ Bases:
netaddr.ip.IPAddress
Custom version of
netaddr.IPAddress
which can match itself against other instance of the same class, a string, or an integer.
-
class
pyfarm.models.core.types.
IPv4Address
(*args, **kwargs)[source]¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
Column type which can store and retrieve IPv4 addresses in a more efficient manner
-
MAX_INT
= 4294967295¶
-
impl
¶ alias of
BigInteger
-
json_types
= (<class 'str'>, <class 'int'>)¶
-
-
class
pyfarm.models.core.types.
JSONDict
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.JSONSerializable
Column type for storing dictionary objects as json
-
serialize_types
= (<class 'dict'>, <class 'collections.UserDict'>)¶
-
-
class
pyfarm.models.core.types.
JSONList
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.JSONSerializable
Column type for storing list objects as json
-
serialize_types
= (<class 'list'>, <class 'tuple'>, <class 'collections.UserList'>)¶
-
-
class
pyfarm.models.core.types.
JSONSerializable
(*args, **kwargs)[source]¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
Base of all custom types which process json data to and from the database.
Variables: - serialize_types (tuple) – the kinds of objects we expect to serialize to and from the database
- serialize_none (bool) – if True then return None instead of converting it to its json value
- allow_blank (bool) – if True, do not raise a
ValueError
for empty data - allow_empty (bool) – if True, do not raise
ValueError
if the input data itself is empty
-
dumps
(value)[source]¶ Performs the process of dumping value to json. For classes such as
UserDict
orUserList
this will dump the underlying data instead of the object itself.
-
impl
¶ alias of
UnicodeText
-
serialize_none
= False¶
-
serialize_types
= None¶
-
class
pyfarm.models.core.types.
MACAddress
(*args, **kwargs)[source]¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
Column type which can store and retrieve MAC addresses in a more efficient manner
-
MAX_INT
= 281474976710655¶
-
impl
¶ alias of
BigInteger
-
json_types
= (<class 'str'>, <class 'int'>)¶
-
-
class
pyfarm.models.core.types.
OperatingSystemEnum
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.EnumType
custom column type for working with
AgentState
-
enum
= OperatingSystem(BSD=Values(304, 'bsd'), WINDOWS=Values(301, 'windows'), LINUX=Values(300, 'linux'), OTHER=Values(303, 'other'), MAC=Values(302, 'mac'))¶
-
-
class
pyfarm.models.core.types.
UUIDType
(*args, **kwargs)[source]¶ Bases:
sqlalchemy.sql.type_api.TypeDecorator
Custom column type which handles UUIDs in the appropriate manner for various databases.
-
impl
¶ alias of
TypeEngine
-
json_types
¶ alias of
UUID
-
-
class
pyfarm.models.core.types.
UseAgentAddressEnum
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.EnumType
custom column type for working with
UseAgentAddress
-
enum
= UseAgentAddress(PASSIVE=Values(313, 'passive'), HOSTNAME=Values(312, 'hostname'), LOCAL=Values(310, 'local'), REMOTE=Values(311, 'remote'))¶
-
-
class
pyfarm.models.core.types.
WorkStateEnum
(*args, **kwargs)[source]¶ Bases:
pyfarm.models.core.types.EnumType
custom column type for working with
WorkState
-
enum
= WorkState(PAUSED=Values(100, 'paused'), FAILED=Values(107, 'failed'), RUNNING=Values(105, 'running'), DONE=Values(106, 'done'))¶
-
Module contents¶
pyfarm.models.statistics package¶
Submodules¶
pyfarm.models.statistics.agent_count module¶
Model describing the counts for agents in various states at a given point in time.
-
class
pyfarm.models.statistics.agent_count.
AgentCount
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
-
counted_time
¶ The point in time at which these counts were done
-
num_disabled
¶ The number of agents that were in state disabled at counted_time
-
num_offline
¶ The number of agents that were in state offline at counted_time
-
num_online
¶ The number of agents that were in state online at counted_time
-
num_running
¶ The number of agents that were in state running at counted_time
-
pyfarm.models.statistics.task_count module¶
Model describing the number of tasks in a given queue in a given state at a point in time
-
class
pyfarm.models.statistics.task_count.
TaskCount
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
-
counted_time
¶ The point in time at which these counts were done
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
job_queue_id
¶ ID of the jobqueue these stats refer to
-
total_done
¶ Number of done tasks at counted_time
-
total_failed
¶ Number of failed tasks at counted_time
-
total_queued
¶ Number of queued tasks at counted_time
-
total_running
¶ Number of running tasks at counted_time
-
pyfarm.models.statistics.task_event_count module¶
Model describing the number of events that happened for tasks over a time period
-
class
pyfarm.models.statistics.task_event_count.
TaskEventCount
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
job_queue_id
¶ ID of the jobqueue these stats refer to
-
num_deleted
¶ Number of tasks that were deleted during the time period
-
num_done
¶ Number of tasks that were finished successfully during the time period
-
num_failed
¶ Number of tasks that failed during the time period
-
num_new
¶ Number of tasks that were newly created during the time period
-
num_restarted
¶ Number of tasks that were restarted during the time period
-
num_started
¶ Number of tasks that work was started on during the time period
-
time_end
¶
-
time_start
¶
-
Module contents¶
Contains models specifically for gathering runtime statistics about the farm
Submodules¶
pyfarm.models.agent module¶
Agent Models¶
Models and interface classes related to the agent.
-
class
pyfarm.models.agent.
Agent
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.ValidatePriorityMixin
,pyfarm.models.core.mixins.ValidateWorkStateMixin
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Stores information about an agent include its network address, state, allocation configuration, etc.
Note
This table enforces two forms of uniqueness. The
id
column must be unique and the combination of these columns must also be unique to limit the frequency of duplicate data:-
MAX_CPUS
= 256¶
-
MAX_PORT
= 65535¶
-
MAX_RAM
= 262144¶
-
MIN_CPUS
= 1¶
-
MIN_PORT
= 1024¶
-
MIN_RAM
= 16¶
-
REPR_COLUMNS
= ('id', 'hostname', 'port', 'state', 'remote_ip', 'cpus', 'ram', 'free_ram')¶
-
REPR_CONVERT_COLUMN
= {'remote_ip': <function repr_ip at 0x7f1ce33ebd90>}¶
-
STATE_DEFAULT
= 'online'¶
-
STATE_ENUM
= MappedEnum(ONLINE='online', RUNNING='running', OFFLINE='offline', DISABLED='disabled')¶
-
URL_TEMPLATE
= 'http://{host}:{port}/api/v1'¶
-
api_url
()[source]¶ Returns the base url which should be used to access the api of this specific agent.
Raises ValueError: Raised if this function is called while the agent’s use_address
column is set toPASSIVE
-
cpu_allocation
¶ The total amount of cpu space an agent is allowed to process work in. A value of 1.0 would mean an agent can handle as much work as the system could handle given the requirements of a task. For example if an agent has 8 cpus, cpu_allocation is .5, and a task requires 4 cpus then only that task will run on the system.
-
cpu_name
¶ The make and model of CPUs in this agents
-
cpus
¶ The number of logical CPU cores installed on the agent
-
disks
¶ The known disks available to this agent
-
failed_tasks
¶ The tasks this agents failed to execute
-
free_ram
¶ The amount of ram which was last considered free
-
gpus
¶ The graphics cards that are installed in this agent
-
hostname
¶ The hostname we should use to talk to this host. Preferably this value will be the fully qualified name instead of the base hostname alone.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
last_heard_from
¶ Time we last had contact with this agent
-
last_polled
¶ Time we last tried to contact the agent
-
last_success_on
¶ The last time this agent has set a task to done
-
mac_addresses
¶ The MAC addresses this agent has
-
notes
¶ Free form notes about this agent
-
os_class
¶ The type of operating system running on the agent; ‘linux’, ‘windows’, or ‘mac’.
-
os_fullname
¶ The full human-readable name of the agent’s OS, as returned by platform.platform()
-
port
¶ The port the agent is currently running on
-
ram
¶ The amount of ram installed on the agent in megabytes
-
ram_allocation
¶ The amount of ram the agent is allowed to allocate towards work. A value of 1.0 would mean to let the agent use all of the memory installed on the system when assigning work.
-
remote_ip
¶ the remote address which came in with the request
-
restart_requested
¶ If True, the agent will be restarted
-
software_versions
¶ software this agent has installed or is configured for
-
state
¶ Stores the current state of the host. This value can be changed either by a master telling the host to do something with a task or from the host via REST api.
Tags associated with this agent
-
task_logs
¶
-
time_offset
¶ The offset in seconds the agent is from an official time server
-
upgrade_to
¶ The version this agent should upgrade to.
-
use_address
¶ The address we should use when communicating with the agent
-
classmethod
validate_hostname
(key, value)[source]¶ Ensures that the hostname provided by value matches a regular expression that expresses what a valid hostname is.
-
classmethod
validate_ipv4_address
(_, value)[source]¶ Ensures the
ip
address is valid. This checks to ensure that the value provided is:
-
validate_numeric_column
(key, value)[source]¶ Validates several numerical columns. Columns such as ram, cpus and port a are validated with this method.
-
classmethod
validate_resource
(key, value)[source]¶ Ensure the
value
provided forkey
is within an expected range. This classmethod retrieves the min and max values from theAgent
class directory using:>>> min_value = getattr(Agent, "MIN_%s" % key.upper()) >>> max_value = getattr(Agent, "MAX_%s" % key.upper())
-
version
¶ The pyfarm version number this agent is running.
-
pyfarm.models.disk module¶
Disk Model¶
Model describing a given disk, with size and free space.
-
class
pyfarm.models.disk.
AgentDisk
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Stores information about a single disk belonging to an agent, including usage information.
-
agent
¶
-
agent_id
¶
-
free
¶ Available space on the disk in bytes.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
mountpoint
¶ The mountpoint of this disk on the agent (Drive letter for Windows agents)
-
size
¶ The total capacity of this disk in bytes
-
pyfarm.models.gpu module¶
GPU Model¶
Model describing a given make and model of graphics card. Every agent can have zero or more GPUs associated with it.
-
class
pyfarm.models.gpu.
GPU
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
-
agents
¶
-
fullname
¶ The full name of this graphics card model
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
pyfarm.models.job module¶
Job Models¶
Models and interface classes related to jobs.
-
class
pyfarm.models.job.
Job
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.ValidatePriorityMixin
,pyfarm.models.core.mixins.ValidateWorkStateMixin
,pyfarm.models.core.mixins.WorkStateChangedMixin
,pyfarm.models.core.mixins.ReprMixin
,pyfarm.models.core.mixins.UtilityMixins
Defines the attributes and environment for a job. Individual commands are kept track of by
Task
-
REPR_COLUMNS
= ('id', 'state', 'project')¶
-
REPR_CONVERT_COLUMN
= {'state': <built-in function repr>}¶
-
STATE_ENUM
= ['paused', 'failed', 'running', 'done', None]¶
-
autodelete_time
¶ If not None, this job will be automatically deleted this number of seconds after it finishes.
-
batch
¶ Number of tasks to run on a single agent at once. Depending on the capabilities of the software being run this will either cause a single process to execute on the agent or multiple processes one after the other.
-
by
¶ The number of frames to count by between start and end. This column may also sometimes be referred to as ‘step’ by other software.
-
children
¶
-
completion_notify_sent
¶ Whether or not the finish notification mail has already been sent out.
-
cpus
¶ Number of cpus or threads each task should consume oneach agent. Depending on the job type being executed this may result in additional cpu consumption, longer wait times in the queue (2 cpus means 2 ‘fewer’ cpus on an agent), or all of the above... csv-table:: Special Values :header: Value, Result :widths: 10, 50 0, minimum number of cpu resources not required -1, agent cpu is exclusive for a task from this job
-
data
¶ Json blob containing additional data for a job .. note:: Changes made directly to this object are not applied to the session.
-
environ
¶ Dictionary containing information about the environment in which the job will execute. .. note:: Changes made directly to this object are not applied to the session.
-
group
¶ The job group this job belongs to
If True, keep the job hidden from the queue and web ui. This is typically set to True if you either want to save a job for later viewing or if the jobs data is being populated in a deferred manner.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
job_group_id
¶ The foreign key which stores:class:JobGroup.id
-
job_queue_id
¶ The foreign key which stores
JobQueue.id
-
jobtype_version
¶
-
jobtype_version_id
¶ The foreign key which stores
JobTypeVersion.id
-
maximum_agents
¶ The scheduler will never assign more than this numberof agents to this job.
-
minimum_agents
¶ The scheduler will try to assign at least this number of agents to this job as long as it can use them, before any other considerations.
-
notes
¶ Notes that are provided on submission or added after the fact. This column is only provided for human consumption, is not scanned, indexed, or used when searching
-
notified_users
¶
-
num_tiles
¶ How many regions to split frames into for rendering.
-
output_link
¶ An optional link to a URI where this job’s output can be viewed.
-
parents
¶
-
priority
¶ The priority of the job relative to others in the queue. This is not the same as task priority.
configured by: job.priority
-
queue
¶ The queue for this job
-
ram
¶ Amount of ram a task from this job will require to be free in order to run. A task exceeding this value will not result in any special behavior... csv-table:: Special Values :header: Value, Result :widths: 10, 500, minimum amount of free ram not required-1, agent ram is exclusive for a task from this job
-
ram_max
¶ Maximum amount of ram a task is allowed to consume on an agent... warning:: If set, the task will be terminated if the ram in use by the process exceeds this value.
-
ram_warning
¶ Amount of ram used by a task before a warning raised. A task exceeding this value will not cause any work stopping behavior.
-
requeue
¶ Number of times to requeue failed tasks .. csv-table:: Special Values :header: Value, Result :widths: 10, 50 0, never requeue failed tasks -1, requeue failed tasks indefinitely
-
rerun
()[source]¶ Makes this job rerun all its task. Tasks that are currently running are left untouched.
-
rerun_failed
()[source]¶ Makes this job rerun all its failed tasks. Tasks that are done or are currently running are left untouched
-
software_requirements
¶
-
state
¶ The state of the job with a value provided by
WorkState
-
tag_requirements
¶
Relationship between this job and
Tag
objects
-
tasks
¶
-
tasks_done
¶ Relationship between this job and any
Task
objects which are done.
-
tasks_failed
¶ Relationship between this job and any
Task
objects which have failed.
-
tasks_queued
¶ Relationship between this job and any
Task
objects which are queued.
-
tasks_running
¶ Relationship between this job and any
Task
objects which are running.
-
time_finished
¶ Time the job was finished. This will be set when the last task finishes and reset if a job is requeued.
-
time_started
¶ The time this job was started. By default this value is set when
state
is changed to an appropriate value or when a job is requeued.
-
time_submitted
¶ The time the job was submitted. By default this defaults to using
datetime.datetime.utcnow()
as the source of submission time. This value will not be set more than once and will not change even after a job is requeued.
-
title
¶ The title of this job
-
to_be_deleted
¶ If true, the master will stop all running tasks for this job and then delete it.
-
user
¶ The owner of this job
-
user_id
¶ The id of the user who owns this job
-
validate_resource
(key, value)[source]¶ Validation that ensures that the value provided for either
ram
orcpus
is a valid value with a given range
-
weight
¶ The weight of this job. The scheduler will distribute available agents between jobs and job queues in the same queue in proportion to their weights.
-
pyfarm.models.jobgroup module¶
Job Group Model¶
Model for job groups
-
class
pyfarm.models.jobgroup.
JobGroup
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
Used to group jobs together for better presentation in the UI
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
jobs
¶
-
main_jobtype
¶ The jobtype of the main job in this group
-
main_jobtype_id
¶ ID of the jobtype of the main job in this group. Purely for display and filtering.
-
title
¶ The title of the job group’s name
-
user
¶ The user who owns these jobs
-
user_id
¶ The id of the user who owns these jobs
-
pyfarm.models.jobqueue module¶
Job Queue Model¶
Model for job queues
-
class
pyfarm.models.jobqueue.
JobQueue
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Stores information about a job queue. Used for flexible, configurable distribution of computing capacity to jobs.
-
REPR_COLUMNS
= ('id', 'name')¶
-
child_queues_sorted
()[source]¶ Return child queues sorted by number of currently assigned agents with priority as a secondary sort key.
-
children
¶
-
fullpath
¶ The path of this jobqueue. This column is a database denormalization. It is technically redundant, but faster to access than recursively querying all parent queues. If set to NULL, the path must be computed by recursively querying the parent queues.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
jobs
¶
-
maximum_agents
¶ The scheduler will never assign more than this number of agents to jobs in or below this queue.
-
minimum_agents
¶ The scheduler will try to assign at least this number of agents to jobs in or below this queue as long as it can use them, before any other considerations.
-
name
¶ The name of the job queue
-
parent
¶ Relationship between this queue its parent
-
parent_jobqueue_id
¶ The parent queue of this queue. If NULL, this is a top level queue.
-
priority
¶ The priority of this job queue. The scheduler will not assign any nodes to other job queues or jobs with the same parent and a lower priority as long as this one can still use nodes. The minimum_agents column takes precedence over this.
-
weight
¶ The weight of this job queue. The scheduler will distribute available agents between jobs and job queues in the same queue in proportion to their weights.
-
pyfarm.models.jobtype module¶
Job Type Models¶
Models and objects dedicated to handling information which is specific
to an individual job. See pyfarm.models.job
for more the more
general implementation.
-
class
pyfarm.models.jobtype.
JobType
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Stores the unique information necessary to execute a task
-
REPR_COLUMNS
= ('id', 'name')¶
-
description
¶ Human readable description of the job type. This field is not required and is not directly relied upon anywhere.
-
fail_body
¶ The email body to use for notifications in in case of success. Some substitutions, for example for the job title, are available.
-
fail_subject
¶ The subject line to use for notifications in case of failure. Some substitutions, for example for the job title, are available.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
jobgroups
¶
-
name
¶ The name of the job type. This can be either a human readable name or the name of the job type class itself.
-
success_body
¶ The email body to use for notifications in in case of success. Some substitutions, for example for the job title, are available.
-
success_subject
¶ The subject line to use for notifications in case of success. Some substitutions, for example for the job title, are available.
-
versions
¶
-
pyfarm.models.pathmap module¶
Path Map Model¶
Model for path maps, allowing for OS-dependent mapping of path prefixes to other path prefixes.
-
class
pyfarm.models.pathmap.
PathMap
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.ReprMixin
,pyfarm.models.core.mixins.UtilityMixins
Defines a table which is used for cross-platform file path mappings.
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
path_linux
¶ The path on linux platforms
-
path_osx
¶ The path on Mac OS X platforms
-
path_windows
¶ The path on Windows platforms
-
tag
¶ Relationship attribute for the tag this path map applies to.
-
tag_id
¶ The tag an agent needs to have for this path map to apply to it. If this is NULL, this path map applies to all agents, but is overridden by applying path maps that do specify a tag.
-
pyfarm.models.software module¶
Software Models¶
Table of software items. Agents can reference this table to show that they provide a given software. Jobs or jobtypes can depend on a software via the SoftwareRequirement table
-
class
pyfarm.models.software.
Software
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
Model to represent a versioned piece of software that can be present on an agent and may be depended on by a job and/or jobtype through the appropriate SoftwareRequirement table
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
software
¶ The name of the software
-
versions
¶ All known versions of this software
-
pyfarm.models.tag module¶
Tag Model¶
Table with tags for both jobs and agents
-
class
pyfarm.models.tag.
Tag
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
Model which provides tagging for
Job
and class:.Agent objects-
agents
¶
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
jobs
¶
-
tag
¶ The actual value of the tag
-
pyfarm.models.task module¶
Task Models¶
Models and interface classes related to tasks
-
class
pyfarm.models.task.
Task
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.ValidatePriorityMixin
,pyfarm.models.core.mixins.ValidateWorkStateMixin
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Defines a task which a child of a
Job
. This table represents rows which contain the individual work unit(s) for a job.-
REPR_COLUMNS
= ('id', 'state', 'frame', 'project')¶
-
REPR_CONVERT_COLUMN
= {'state': functools.partial(<function repr_enum at 0x7f1ce33ebe18>, enum=['paused', 'failed', 'running', 'done', None])}¶
-
STATE_DEFAULT
= None¶
-
STATE_ENUM
= ['paused', 'failed', 'running', 'done', None]¶
-
agent
¶
-
agent_id
¶ Foreign key which stores
Job.id
-
attempts
¶ The number of attempts which have been made on this task. This value is auto incremented when
state
changes to a value synonymous with a running state.
-
static
clear_error_state
(target, new_value, old_value, initiator)[source]¶ Sets
last_error
column toNone
if the task’s state is ‘done’
-
failed_in_agents
¶
-
failures
¶ The number of times this task has failed. This value is auto incremented when
state
changes to a value synonymous with a failed state.
When True this hides the task from queue and web ui
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
job
¶ relationship attribute which retrieves the associated job for this task
-
job_id
¶ Foreign key which stores
Job.id
-
last_error
¶ This column may be set when an error is present. The agent typically sets this column when the job type either can’t or won’t run a given task. This column will be cleared whenever the task’s state is returned to a non-error state.
-
log_associations
¶
-
priority
¶ The priority of the job relative to others in the queue. This is not the same as task priority.
configured by: job.priority
-
progress
¶ The progress for this task, as a value between 0.0 and 1.0. Used purely for display purposes.
-
sent_to_agent
¶ Whether this task was already sent to the assigned agent
-
static
set_times
(target, new_value, old_value, initiator)[source]¶ update the datetime objects depending on the new value
-
state
¶ The state of the job with a value provided by
WorkState
-
tile
¶ When using tiled rendering, the number of the tile this task refers to. The jobtype will have to translate that into an actual image region. This will be NULL if the job doesn’t use tiled rendering.
-
time_finished
¶ Time the job was finished. This will be set when the last task finishes and reset if a job is requeued.
-
time_started
¶ The time this job was started. By default this value is set when
state
is changed to an appropriate value or when a job is requeued.
-
time_submitted
¶ The time the job was submitted. By default this defaults to using
datetime.datetime.utcnow()
as the source of submission time. This value will not be set more than once and will not change even after a job is requeued.
-
pyfarm.models.tasklog module¶
Task Log Models¶
Model describing a log file for a task or batch of tasks.
A task can be associated with more than one log file, for example because it needed to be retried and there are logs for every attempt or because the job type used uses more than one process to execute a batch. A log file can belong to more than one task if tasks have been batched together for execution.
-
class
pyfarm.models.tasklog.
TaskLog
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,pyfarm.models.core.mixins.UtilityMixins
,pyfarm.models.core.mixins.ReprMixin
Table which represents a single task log entry
-
agent
¶ Relationship between an
TaskLog`and the :class:`pyfarm.models.Agent
it was created on
-
agent_id
¶ The agent this log was created on
-
created_on
¶ The time when this log was created
-
id
¶ Provides an id for the current row. This value should never be directly relied upon and it’s intended for use by relationships.
-
identifier
¶ The identifier for this log
-
task_associations
¶ Relationship between tasks and their logs.
-
-
class
pyfarm.models.tasklog.
TaskTaskLogAssociation
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
Stores an association between the task table and a task log
-
attempt
¶ The attempt number for the given task log
-
log
¶
-
state
¶ The state of the work being performed
-
task
¶
-
task_id
¶ The ID of the job a task log is associated with
-
task_log_id
¶ The ID of the task log
-
pyfarm.models.user module¶
User and Role Models¶
Stores users and their roles in the database.
-
class
pyfarm.models.user.
User
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
,flask_login.UserMixin
,pyfarm.models.core.mixins.ReprMixin
Stores information about a user including the roles they belong to
-
REPR_COLUMNS
= ('id', 'username')¶
-
active
¶ Enables or disables a particular user across the entire system
-
email
¶ Contact email for registration and possible notifications
-
expiration
¶ User expiration. If this value is set then the user will no longer be able to access PyFarm past the expiration.
-
has_roles
(allowed=None, required=None)[source]¶ checks the provided arguments against the roles assigned
-
id
¶
-
jobgroups
¶
-
jobs
¶
-
last_login
¶ The last date that this user was logged in.
-
onetime_code
¶ SHA256 one time use code which can be used for unique urls such as for password resets.
-
password
¶ The password used to login
-
roles
¶
-
subscribed_jobs
¶
-
username
¶ The username used to login.
-
-
class
pyfarm.models.user.
Role
(**kwargs)[source]¶ Bases:
flask_sqlalchemy.Model
Stores role information that can be used to give a user access to individual resources.
-
active
¶ Enables or disables a role. Disabling a role will prevent any users of this role from accessing PyFarm
-
classmethod
create
(name, description=None)[source]¶ Creates a role by the given name or returns an existing role if it already exists.
-
description
¶ Human description of the role.
-
expiration
¶ Role expiration. If this value is set then the role, and anyone assigned to it, will no longer be able to access PyFarm past the expiration.
-
id
¶
-
name
¶ The name of the role
-
users
¶
-
Module contents¶
Contains all the models used for database communication and object relational management.
pyfarm.scheduler package¶
Submodules¶
pyfarm.scheduler.celery_app module¶
Celery Application¶
Creates the base instance of Celery
which is used by components of
PyFarm’s master that require interaction with a task queue. This module also
configures Celery’s beat scheduler for other tasks such as agent polling
and task assignment.