Making Packages that Provide Services

Services when running provide functionality for users and other services. Most service packages contain only a few configuration files. The programs themselves should be packaged separately, and the service should depend upon the required programs' packages.

Services are really just normal packages. They are distinguished by the packaging system in several ways:

By default, starting a service consists of starting a particular program. Usually this means making a symlink so that the program has the appropriate name in $0, so that it can be seen by top or killall. The scripts should make a pid file in the location specified by SERVICE_PIDFILE, which is set to LOCAL_VAR/run/SERVICE.pid. The output of the program will be redirected to SERVICE_OUTPUT_FILE which is set to LOCAL_VAR/run/SERVICE.output. The symlink itself should be make in LOCAL_VAR/linkfarm/.

The service is in charge of managing its own configuration, but in general, we recommend making a service_pre_start script that runs sub-conf on each configuration file. It take a path under etc and searches first in etc then in ext/etc, which allows users to override the configuration file by putting a copy in their project instead of using the package's version. sub generally takes strings like __ENVIRONMENT_VARIABLE__ and replaces that with the value of $ENVIRONMENT_VARIABLE.

The $PACKAGE-$VERSION.config file is a sh-script which is sourced by a subshell of servicectl. It is in the service package. It may set the following sh-variables. It should not export them. General running options:

service_program

The name of the binary to run. If it is not in $PLAYPEN_ROOT/bin or $PLAYPEN_ROOT/ext/bin, then it should be the path to a binary, relative to ext/.

service_run_name

The name to use as "argv[0]" or the first string in /proc/pid/cmdline or the string seen in top or ps.

The name of the service's package will be used if none is provided.

This is implemented by making symlinks under the directory $LOCAL_VAR/linkfarm, so if you specify service_no_symlink this will have no effect.

service_arguments

The flags to pass to the service when starting or stopping it.

service_pre_start

An optional command to run before starting or sending a SIGHUP to the service.

It is often more convenient to include a SERVICE-VERSION.pre-start file in your package.

service_post_start

An optional command to run after starting or sending a SIGHUP to the service.

It is often more convenient to include a SERVICE-VERSION.post-start file in your package.

service_pre_stop

An optional command to run before stopping the service.

It is often more convenient to include a SERVICE-VERSION.pre-stop file in your package.

service_post_stop

An optional command to run before stopping the service.

It is often more convenient to include a SERVICE-VERSION.post-stop file in your package.

service_stop_start_delay

An optional number of seconds to wait when restarting between stopping and starting the service. This only has an effect if the service does not handle SIGHUP and does not have a service_restart script.

In addition to the pre-start commands, some configuration files are also constructed immediately before starting the service. These are listed

service_subconfdir_conffiles

Configuration files which are run through sub-conf-dir. They are specified relative to either $PLAYPEN_ROOT/ext or $PLAYPEN_ROOT (for per-project overrides).

The output is placed in the same relative location, under LOCAL_VAR.

There are a few booleans which describe how to perform the restart action:

service_hupable

If set to 1, the service may be restarted by sending a SIGHUP.

service_restart_to_upgrade

If set to 1, the service must be restarted if any package it depends on has been upgraded. The default is 1, so you must set it to 0 explicitly if the service does not need to be restarted before upgrading.

service_stop_before_upgrading

If set to 1, the service must be stopped before it or anything on which it depends can be upgraded. The default is 1, so you must set it to 0 explicitly if the service does not need to be stopped before upgrading.

service_stop_before_upgrading_self

If set to 1, the service must be stopped before it is upgraded. The default is 1, so you must set it to 0 explicitly if the service does not need to be stopped before upgrading.

service_stop_before_changing_files

If set to 1, the service must be stopped before any files listed in filedep. (See the Section called Dependencies). can be changed. The default is 0 (that is, restart instead of stopping the service).

service_restart

A special script to run whenever the service needs to be restarted (this is discouraged). Package's services are passed two arguments: the service name and version number. Project services are just passed the service name, because they don't have a version number.

The environment variable SERVICE_UPGRADED will be set to 1 if the service was upgraded while it was running since the last restart; otherwise it is set to 0.

For ease of writing Java services, we support a few convenience variables, mostly to help location java libraries.

service_jar_dirs

A space-separated list of directories containing .jar files, all of which will be added to CLASSPATH before running the service. (Specified relative to ext.)

service_jar_files

A space-separated list of .jar files, all of which will be added to CLASSPATH before running the service. (Specified relative to ext.)

Other booleans describing the server's ability or behavior:

service_writes_pidfile

If set to 1, the service is expected to write its own pidfile. The $SERVICE_PIDFILE environment variable will be set to the full path of the pidfile the service must create before sourcing the .config or the start, stop or hup scripts.

service_no_pidfile

If set to 1, there should be no pidfile at all for this service. Such services must provide service_ping scripts.

service_no_symlink

If set to 1, the service cannot be invoked through a symlink; service_program must be invoked directly.

NoteService Runtime Symlinks
 

By default, services will be invoked through symlinks so that their run names can be changed if either PLAYPEN_TAG or service_run_name are set.

Note that this flag is automatically turned on if the program to run is the Java runtime (since the java program is a wrapper which cannot be a symlink).

service_required_envars

A list of environment variables that must be set before the service can be run.

service_optional_envars

A list of environment variables that may optionally be set but affect how the service runs.

There are other variables used to prompt the user about the meaning of the required environment variables. Each of these variables may be set for each variable listed in service_required_envars or service_optional_envars:

service_envar_description_ENVAR

A string describing the given environment variable.

service_envar_type_ENVAR

The type of value to which this environment variable may be set. This must be set to one of the following values:

simple_string

The value of this variable should be a nonempty string that does not contain whitespace.

string

The value of this variable should be a nonempty string that may contain whitespace.

filename

Like string, but intended for filenames.

integer

Any integer value.

port

A port number.

If the environment variable ABC is required and has type `port', then the value of the port will be computed in one of these ways:

  • If ABC is set, it will be used.

  • If PORT_PREFIX and ABC_OFFSET are set, then the value PORT_PREFIX + ABC_OFFSET will be used.

    For now, I'll add a hack to assume untyped variables which end _PORT are of type `port', and print a warning.... Try to get the services switched over quick...

real

Any real number.

nonnegative_integer

Any positive integer or 0.

service_envar_constraints_ENVAR

Type-dependent constraints on a variable. For an numeric type, this may be a space-separated list of ranges: START-END . For a simple_string, this may be a space-separated list of allowed values.

service_envar_default_ENVAR

A default recommended value for this variable. (Used for creating example scripts).

Scripts which can brutally override the start, stop or restart behavior:

service_start, service_stop

We expect that the generic server starting and stopping mechanisms will be sufficient, but if they are not, you may set $service_start to the name of a script to run to start the service or service_stop to to a script to shut down the service.

These scripts are invoked with two arguments, the service name and version number. If the second argument is omitted, then the service is a local service. This should never happen to a packaged script.

By default, the service_start script is responsible for writing a $SERVICE_PIDFILE file. If you do not want to have a pidfile, you must use $service_no_pidfile, but you must be able to implement a $service_stop script without a pidfile.

service_restart

Provide a script which will restart the service. This will only be used if the service doesn't restart when sent a SIGHUP. If there is no restart script and SIGHUP doesn't cause a restart, then a "restart" request to servicectl, it will stop and then start the service.

Scripts the service can provide to test its aliveness. Testing the aliveness of a service:

service_ping

Provide a script which will test the service's aliveness. Without this we just ensure the process is still running, which may be wrong if an unclean shutdown occurred.

service_check

Provide a script which will test that the service is working, for example, fetching a known page from a webserver or even a 404 or some other known error.

A few packages need to set environment variables before running programs in that package (or in dependent packages). For that purpose, the package may include a $PACKAGE-$VERSION.profile script that will be automatically copied into ext/etc/profile. ( note: this only works for make style packages at the moment. raw and other packages styles will have to copy profile files in place themselves. ) This is sourced automatically by load-config.