7.1.8. cobbler.services package

7.1.8.1. Submodules

7.1.8.2. cobbler.services.files module

Direct-disk distro tree file server.

This WSGI app serves the files of a distro’s original, uncopied source tree (repodata/, Packages/, etc.) straight from disk, so that clients such as anaconda/installer HTTP clients can fetch package/repo data from $tree URLs of the form:

http://<server>/cblr/svc/tree/<distro_name>/<relative_path>

without cobblerd having to stream every byte through an XML-RPC round trip (XML-RPC is only used here for a single, briefly-cached metadata lookup: resolving a distro name to its source_tree_path). This mirrors cobbler.services.svc’s pattern for reaching cobblerd (same settings file, same xmlrpc_port/xmlrpc_host keys, same unauthenticated xmlrpc.client.Server construction) but never uses XML-RPC for file bytes themselves.

Security note: the path-resolution logic in this module (is_safe_path() / resolve_within_root()) is the only thing standing between an unauthenticated client and arbitrary file disclosure. Both textual traversal (../../etc/passwd) and a symlink inside the tree pointing outside of it must be rejected; both are defeated by resolving os.path.realpath on the fully-joined candidate path and requiring it to be the root or a descendant of the root’s own realpath – never by textual .. rejection alone (which a symlink trivially bypasses).

cobbler.services.files.CACHE_TTL_SECONDS = 30.0

How long a resolved source_tree_path (or a negative “not available” result) is cached for, per distro name, before another XML-RPC get_distro call is made.

exception cobbler.services.files.RangeUnsatisfiable[source]

Bases: Exception

Raised by parse_range() when the Range header is syntactically a byte-range but requests a start offset beyond the file’s size, i.e. a 416 Range Not Satisfiable.

cobbler.services.files.application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) Any[source]

WSGI entrypoint for direct-disk distro tree file serving.

Expects to be invoked (via cobbler.services.application’s dispatch) for request paths of the shape /tree/<distro_name>/<relative_path> – i.e. the client-facing /cblr/svc/tree/... URL with Apache’s ProxyPass prefix already stripped, exactly like cobbler.services.svc.application sees its own paths via environ["RAW_URI"].

Only GET and HEAD are supported. HEAD runs through the exact same resolution/header-computation logic as GET (so e.g. Content-Length/Content-Type reflect the same values a GET would have produced) but the response body is discarded before returning, per RFC 7231 section 4.3.2. Any other method (POST, DELETE, …) is rejected outright with 405 Method Not Allowed rather than being treated as a GET.

Parameters:
  • environ – The WSGI environ.

  • start_response – The WSGI start_response callable.

cobbler.services.files.healthz_application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) Any[source]

WSGI entrypoint for /healthz: reports whether cobblerd’s XML-RPC endpoint is reachable and responsive.

Only GET and HEAD are supported, exactly like application(). A successful XML-RPC ping() round trip yields 200 OK; any failure to reach or get a response from cobblerd (connection refused, timeout, an XML-RPC fault, or a malformed/missing settings file, all of which surface as OSError/xmlrpc.client.Fault/xmlrpc.client.ProtocolError) yields 503 Service Unavailable rather than propagating as an unhandled exception/500.

Parameters:
  • environ – The WSGI environ.

  • start_response – The WSGI start_response callable.

cobbler.services.files.httpboot_application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) Any[source]

WSGI entrypoint for direct-disk serving of /httpboot (UEFI HTTP(S) boot files), the Gunicorn equivalent of Apache’s Alias /httpboot @@tftproot@@/grub.

Only GET and HEAD are supported, exactly like application().

Parameters:
  • environ – The WSGI environ.

  • start_response – The WSGI start_response callable.

cobbler.services.files.images_application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) Any[source]

WSGI entrypoint for direct-disk serving of /images (UEFI HTTP(S) boot files), the Gunicorn equivalent of Apache’s Alias /images @@tftproot@@/grub/images.

Only GET and HEAD are supported, exactly like application().

Parameters:
  • environ – The WSGI environ.

  • start_response – The WSGI start_response callable.

cobbler.services.files.is_safe_path(root_real: str, candidate_real: str) bool[source]

Check whether an already-realpath-resolved candidate path is the root itself or a proper descendant of it.

Both inputs must already have been passed through os.path.realpath by the caller – this function itself does no filesystem access, which is what makes it cheaply, deterministically unit-testable on plain strings. The actual security property (catching symlink escapes) comes entirely from the caller having resolved candidate_real with realpath after joining in the untrusted relative path, not from anything this function does.

Parameters:
  • root_real – The realpath of the distro’s source_tree_path root.

  • candidate_real – The realpath of the fully-joined candidate path.

Returns:

True if candidate_real is root_real or a descendant of it.

cobbler.services.files.parse_range(header: str, size: int) Tuple[int, int] | None[source]

Parse an HTTP Range header of the form bytes=start-end (both bounds optional, per RFC 7233), against a known file size.

Suffix ranges (bytes=-N, meaning “the last N bytes”) and multi-range requests (bytes=0-99,200-299) are treated as unsupported and cause the request to be served in full (None is returned, i.e. “no usable range, ignore it”), rather than as an error – this mirrors the permissive behavior most HTTP servers fall back to for Range syntax they don’t implement.

Parameters:
  • header – The raw Range header value, e.g. bytes=0-99.

  • size – The total size of the file in bytes.

Returns:

An inclusive (start, end) tuple, or None if the header should be ignored and the full file served instead.

Raises:

RangeUnsatisfiable – if the requested start offset is beyond size.

cobbler.services.files.resolve_source_tree_path(distro_name: str) str | None[source]

Resolve a distro name to its source_tree_path, via a short-TTL cached XML-RPC lookup.

Parameters:

distro_name – The name of the distro to resolve.

Returns:

The distro’s source_tree_path, or None if the distro doesn’t exist or has no source_tree_path set (both are treated identically by callers: a 404).

cobbler.services.files.resolve_within_root(root: str, relative_path: str) str | None[source]

Join relative_path onto root and validate the result stays within root.

This is the security-critical traversal guard. It defends against two distinct attacks:

  • Textual traversal: a relative_path containing ../ segments that would lexically escape root (e.g. ../../etc/passwd).

  • Symlink escape: a symlink that lives inside root (so it wouldn’t be caught by rejecting .. in the URL) but whose target points outside of root.

Both are defeated the same way: os.path.realpath is applied to the final joined candidate path (not just to the root), which fully resolves both .. segments and any symlinks encountered anywhere along the path – including a symlink as the last component. The resolved result is then required to be exactly root’s own realpath, or a path beginning with root_real + os.sep. A leading / on relative_path is stripped first so an absolute-looking segment (e.g. from a doubled slash in the URL) can’t make os.path.join discard root outright.

Parameters:
  • root – The distro’s source_tree_path (already validated elsewhere to be an absolute, existing directory).

  • relative_path – The untrusted, already-URL-decoded path requested by the client.

Returns:

The resolved, validated, absolute realpath if it is safe, or None if the request must be rejected (the caller maps this to 403 Forbidden).

7.1.8.3. cobbler.services.svc module

Mod Python service functions for Cobbler’s public interface (aka cool stuff that works with wget/curl)

Changelog:

Schema: From -> To

Current Schema: Please refer to the documentation visible of the individual methods.

V4.0.0 (unreleased)
  • No changes

V3.3.4 (unreleased)
  • No changes

V3.3.3
  • Removed:
    • look

V3.3.2
  • No changes

V3.3.1
  • No changes

V3.3.0
  • Added:
    • settings

  • Changed:
    • gpxe: Renamed to ipxe

V3.2.2
  • No changes

V3.2.1
  • No changes

V3.2.0
  • No changes

V3.1.2
  • No changes

V3.1.1
  • No changes

V3.1.0
  • No changes

V3.0.1
  • No changes

V3.0.0
  • Added:
    • autoinstall

    • find_autoinstall

V2.8.5
  • Inital tracking of changes.

class cobbler.services.svc.CobblerSvc(server: str = '')[source]

Bases: object

Interesting mod python functions are all keyed off the parameter mode, which defaults to index. All options are passed as parameters into the function.

autodetect(**kwargs: str | int | List[str]) str[source]

This tries to autodect the system with the given information. If more than one candidate is found an error message is returned.

Parameters:

kwargs – The keys “REMOTE_MACS”, “REMOTE_ADDR” or “interfaces”.

Returns:

The name of the possible object or an error message.

autoinstall(profile: str | None = None, system: str | None = None, file: str = '', **kwargs: Any) str[source]

Generate automatic installation files.

Parameters:
  • profile – The name of the profile to generate the autoinstall for.

  • system – The name of the system to generate the autoinstall for.

  • kwargs – This parameter is unused.

Returns:

TODO

bootcfg(profile: str | None = None, system: str | None = None, **kwargs: Any) str[source]

Generate a boot.cfg config file. Used primarily for VMware ESXi.

Parameters:
  • profile

  • system

  • kwargs – This parameter is unused.

Returns:

events(user: str = '', **kwargs: Any) str[source]

If no user is given then all events are returned. Otherwise only event associated to a user are returned.

Parameters:
  • user – Filter the events for a given user.

  • kwargs – This parameter is unused.

Returns:

A JSON object which contains all events.

find_autoinstall(system: str | None = None, profile: str | None = None, **kwargs: str | int) str[source]

Find an autoinstallation for a system or a profile. If this is not known different parameters can be passed to kwargs to find it automatically. See “autodetect”.

Parameters:
  • system – The system to find the autoinstallation for,

  • profile – The profile to find the autoinstallation for.

  • kwargs – The metadata to find the autoinstallation automatically.

Returns:

The autoinstall script or error message.

index(**kwargs: Any) str[source]

Just a placeholder method as an entry point.

Parameters:

kwargs – This parameter is unused.

Returns:

“no mode specified”

ipxe(profile: str | None = None, image: str | None = None, system: str | None = None, mac: str | None = None, **kwargs: Any)[source]

Generates an iPXE configuration.

Parameters:
  • profile – A profile.

  • image – An image.

  • system – A system.

  • mac – A MAC address.

  • kwargs – This parameter is unused.

list(what: str = 'systems', **kwargs: Any) str[source]

Return a list of objects of a desired category. Defaults to “systems”.

Parameters:
  • what – May be “systems”, “profiles”, “distros”, “images”, “repos” or “menus”

  • kwargs – This parameter is unused.

Returns:

The list of object names.

nopxe(system: str | None = None, **kwargs: Any) str[source]

Disables the network boot for the given system.

Parameters:
  • system – The system to disable netboot for.

  • kwargs – This parameter is unused.

Returns:

A boolean status if the action succeed or not.

property remote: ServerProxy

Sets up the connection to the Cobbler XMLRPC server. This is the version that does not require a login.

script(profile: str | None = None, system: str | None = None, **kwargs: Any) str[source]

Generate a script based on snippets. Useful for post or late-action scripts where it’s difficult to embed the script in the response file.

Parameters:
  • profile – The profile to generate the script for.

  • system – The system to generate the script for.

  • kwargs – This may contain a parameter with the key “query_string” which has a key “script” which may be an array. The element from position zero is taken.

Returns:

The generated script.

settings(**kwargs: Any) str[source]

Get the application configuration.

Returns:

Settings object.

template(profile: str | None = None, system: str | None = None, path: str | None = None, **kwargs: Any) str[source]

Generate a templated file for the system. Either specify a profile OR a system.

Parameters:
  • profile – The profile to provide for the generation of the template.

  • system – The system to provide for the generation of the template.

  • path – The path to the template.

  • kwargs – This parameter is unused.

Returns:

The rendered template.

trig(mode: str = '?', profile: str | None = None, system: str | None = None, REMOTE_ADDR: str | None = None, **kwargs: Any) str[source]

Hook to call install triggers. Only valid for a profile OR a system.

Parameters:
  • mode – Can be “pre”, “post” or “firstboot”. Everything else is invalid.

  • profile – The profile object to run triggers for.

  • system – The system object to run triggers for.

  • REMOTE_ADDR – The ip if the remote system/profile.

  • kwargs – This parameter is unused.

Returns:

The return code of the action.

yum(profile: str | None = None, system: str | None = None, **kwargs: Any) str[source]

Generate a repo config. Either specify a profile OR a system.

Parameters:
  • profile – The profile to provide for the generation of the template.

  • system – The system to provide for the generation of the template.

  • kwargs – This parameter is unused.

Returns:

The generated repository config.

cobbler.services.svc.VALUE_KEY = <object object>

Empty instance. A unique marker value used instead of None to differentiate between when a key should be used for a value and when ‘None’ is a valid entry in a dictionary.

cobbler.services.svc.application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) List[bytes][source]

UWSGI entrypoint for Gunicorn

Parameters:
  • environ

  • start_response

Returns:

7.1.8.4. Module contents

Gunicorn entry point for Cobbler’s WSGI service(s): gunicorn cobbler.services:application.

cobbler.services.application(environ: Dict[str, Any], start_response: Callable[[str, List[Any]], None]) List[bytes][source]

WSGI entrypoint for Gunicorn.

Dispatches requests for the direct-disk distro tree file server (client-facing /cblr/svc/tree/..., seen here – after Apache’s ProxyPass strips the /cblr/svc/ prefix – as /tree/... in environ["RAW_URI"]) to cobbler.services.files. Requests for /httpboot/... and /images/... (UEFI HTTP(S) boot files, statically served by Apache’s own Alias directives today – not proxied, so no prefix-stripping happens for them) are likewise dispatched straight to cobbler.services.files. /healthz (a liveness check backed by an XML-RPC round trip against cobblerd, for Docker’s HEALTHCHECK and orchestration tooling) is dispatched there too. Everything else falls through to the existing XML-RPC-backed cobbler.services.svc app, unchanged.

Parameters:
  • environ

  • start_response

Returns: