1
# Copyright 2012, 2013 Canonical Ltd. This software is licensed under the
1
# Copyright 2012-2014 Canonical Ltd. This software is licensed under the
2
2
# GNU Affero General Public License version 3 (see the file LICENSE).
4
4
"""MAAS Provisioning Configuration.
6
Configuration for most elements of a Cluster Controller can and be obtained by
7
using this module's `Config` class. At the time of writing the exceptions are
8
the Celery worker's configuration, the `CLUSTER_UUID` and `MAAS_URL`
9
environment variables (see `provisioningserver.cluster_config`), and the
10
configuration for ``maas-import-pxe-files`` (soon to be deprecated) and
11
``maas-import-ephemerals`` (deprecated).
6
Configuration for most elements of a Cluster Controller can be obtained
7
through this module's `Config` and `BootConfig` classes. At the time of
8
writing the exceptions are the Celery worker's configuration, as well as the
9
`CLUSTER_UUID` and `MAAS_URL` environment variables
10
(see `provisioningserver.cluster_config`).
13
12
It's pretty simple. Typical usage is::
64
64
from shutil import copyfile
65
65
from threading import RLock
67
from formencode import Schema
67
from formencode import (
68
71
from formencode.declarative import DeclarativeMeta
69
72
from formencode.validators import (
107
111
if_key_missing = None
113
# Obsolete: old TFTP root directory. This is retained for the purpose of
114
# deriving new, Simplestreams-based import configuration from previously
115
# imported boot images.
116
# The last time this is needed is for upgrading an older cluster
117
# controller to the Ubuntu 14.04 version of MAAS. After installation of
118
# the 14.04 version, this setting is never used.
109
119
root = String(if_missing="/var/lib/maas/tftp")
121
# TFTP root directory, managed by the Simplestreams-based import script.
122
# Equates to $storage/current. The import script maintains "current" as a
123
# symlink pointing to the most recent images.
124
resource_root = String(
125
if_missing="/var/lib/maas/boot-resources/current/")
110
127
port = Int(min=1, max=65535, if_missing=69)
111
128
generator = String(if_missing=b"http://localhost/MAAS/api/1.0/pxeconfig/")
117
134
if_key_missing = None
120
class ConfigBootEphemeral(Schema):
121
"""Configuration validator for ephemeral boot configuration."""
123
if_key_missing = None
125
images_directory = String(if_missing="/var/lib/maas/ephemeral")
126
releases = Set(if_missing=None)
137
class ConfigBootSourceSelection(Schema):
138
"""Configuration validator for boot source election onfiguration."""
140
if_key_missing = None
142
release = String(if_missing="*")
143
arches = Set(if_missing=["*"])
144
subarches = Set(if_missing=['*'])
145
labels = Set(if_missing=['*'])
148
class ConfigBootSource(Schema):
149
"""Configuration validator for boot source configuration."""
151
if_key_missing = None
154
if_missing="http://maas.ubuntu.com/images/ephemeral/releases/")
156
if_missing="/usr/share/keyrings/ubuntu-cloudimage-keyring.gpg")
157
selections = ForEach(
158
ConfigBootSourceSelection,
159
if_missing=[ConfigBootSourceSelection.to_python({})])
129
162
class ConfigBoot(Schema):
132
165
if_key_missing = None
134
ephemeral = ConfigBootEphemeral
135
architectures = Set(if_missing=None)
138
class ConfigMeta(DeclarativeMeta):
139
"""Metaclass for the root configuration schema."""
141
def _get_default_filename(cls):
142
# Avoid circular imports.
143
from provisioningserver.utils import locate_config
145
# Get the configuration filename from the environment. Failing that,
146
# look for the configuration in its default locations.
148
"MAAS_PROVISIONING_SETTINGS",
149
locate_config('pserv.yaml'))
151
def _set_default_filename(cls, filename):
152
# Set the configuration filename in the environment.
153
environ["MAAS_PROVISIONING_SETTINGS"] = filename
155
def _delete_default_filename(cls):
156
# Remove any setting of the configuration filename from the
158
environ.pop("MAAS_PROVISIONING_SETTINGS", None)
160
DEFAULT_FILENAME = property(
161
_get_default_filename, _set_default_filename,
162
_delete_default_filename, doc=(
163
"The default config file to load. Refers to "
164
"MAAS_PROVISIONING_SETTINGS in the environment."))
167
class Config(Schema):
168
"""Configuration validator."""
170
__metaclass__ = ConfigMeta
172
if_key_missing = None
174
logfile = String(if_empty=b"pserv.log", if_missing=b"pserv.log")
176
broker = ConfigBroker
167
storage = String(if_missing="/var/lib/maas/boot-resources/")
169
ConfigBootSource, if_missing=[ConfigBootSource.to_python({})])
171
# Marker in the bootresources.yaml file: if True, the file has not been
172
# edited yet and needs to be either configured with initial choices, or
173
# rewritten based on previously downloaded boot images.
174
configure_me = Bool(if_missing=False)
177
class ConfigBase(Schema):
178
"""Base configuration validator."""
182
181
def parse(cls, stream):
242
241
return deepcopy(cls._cache[filename])
244
def flush_cache(cls, filename=None):
245
"""Evict a config file, or any cached config files, from cache."""
246
with cls._cache_lock:
250
if filename in cls._cache:
251
del cls._cache[filename]
245
254
def field(target, *steps):
246
255
"""Obtain a field by following `steps`."""
247
256
for step in steps:
252
261
def get_defaults(cls):
253
262
"""Return the default configuration."""
254
263
return cls.to_python({})
266
class ConfigMeta(DeclarativeMeta):
267
"""Metaclass for the root configuration schema."""
269
envvar = None # Set this in subtypes.
270
default = None # Set this in subtypes.
272
def _get_default_filename(cls):
273
# Avoid circular imports.
274
from provisioningserver.utils import locate_config
276
# Get the configuration filename from the environment. Failing that,
277
# look for the configuration in its default locations.
278
return environ.get(cls.envvar, locate_config(cls.default))
280
def _set_default_filename(cls, filename):
281
# Set the configuration filename in the environment.
282
environ[cls.envvar] = filename
284
def _delete_default_filename(cls):
285
# Remove any setting of the configuration filename from the
287
environ.pop(cls.envvar, None)
289
DEFAULT_FILENAME = property(
290
_get_default_filename, _set_default_filename,
291
_delete_default_filename, doc=(
292
"The default config file to load. Refers to "
293
"`cls.envvar` in the environment."))
296
class Config(ConfigBase):
297
"""Configuration for the provisioning server."""
299
class __metaclass__(ConfigMeta):
300
envvar = "MAAS_PROVISIONING_SETTINGS"
301
default = "pserv.yaml"
303
if_key_missing = None
305
logfile = String(if_empty=b"pserv.log", if_missing=b"pserv.log")
307
broker = ConfigBroker
312
class BootConfig(ConfigBase):
313
"""Configuration for boot resources."""
315
class __metaclass__(ConfigMeta):
316
envvar = "MAAS_BOOT_RESOURCES_SETTINGS"
317
default = "bootresources.yaml"
319
if_key_missing = None