Skip to content

Commit 36c1267

Browse files
committed
Fix handling configs in base image
This commit restructures the handling of configuration files in set_configs.py, introducing functions for managing default configuration files first. Closes-Bug: #2060855 Change-Id: If91e0330dc149143c82d2183b8ddf6fa9f68d80e
1 parent 8eaf414 commit 36c1267

File tree

3 files changed

+617
-0
lines changed

3 files changed

+617
-0
lines changed

docker/base/set_configs.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
LOG = logging.getLogger(__name__)
3535
LOG.setLevel(logging.INFO)
3636

37+
KOLLA_DEFAULTS = "/etc/kolla/defaults"
38+
KOLLA_DEFAULTS_STATE = KOLLA_DEFAULTS + '/' + 'state'
39+
3740

3841
class ExitingException(Exception):
3942
def __init__(self, message, exit_code=1):
@@ -403,10 +406,157 @@ def handle_exclusion(root, path_suffix):
403406
handle_exclusion(root, file_)
404407

405408

409+
def get_defaults_state():
410+
"""Retrieve the saved default configuration state from default state file.
411+
412+
This function creates the directory for Kolla defaults if it does not
413+
exist, and then attempts to read the current configuration state from
414+
a JSON file. If the file exists, it reads and returns the content.
415+
If not, it returns an empty dictionary.
416+
417+
Simply said, when the container starts for the first time, the state file
418+
doesn't exist, and it returns an empty dictionary.
419+
However, if it has already been started before, it will contain the state
420+
as it was when it first ran.
421+
422+
Returns:
423+
dict: The configuration state stored in the Kolla defaults state file.
424+
425+
Example:
426+
{
427+
"/etc/cinder/cinder.conf": {
428+
"source": "/etc/cinder/cinder.conf",
429+
"preserve_properties": true,
430+
"dest": null
431+
},
432+
"/etc/apache2/conf-enabled/cinder-wsgi.conf": {
433+
"source": "/etc/apache2/conf-enabled/cinder-wsgi.conf",
434+
"preserve_properties": true,
435+
"dest": null
436+
},
437+
"/etc/cinder/cinder_audit_map.conf": {
438+
"source": "/etc/cinder/cinder_audit_map.conf",
439+
"preserve_properties": true,
440+
"dest": "/etc/kolla/defaults/etc/cinder/cinder_audit_map.conf"
441+
}
442+
}
443+
444+
From above example:
445+
/etc/cinder/cinder.conf didn't exist
446+
/etc/apache2/conf-enabled/cinder-wsgi.conf didn't exist
447+
/etc/cinder/cinder_audit_map.conf exists and saved
448+
"""
449+
os.makedirs(KOLLA_DEFAULTS, exist_ok=True)
450+
if os.path.exists(KOLLA_DEFAULTS_STATE):
451+
with open(KOLLA_DEFAULTS_STATE, 'r') as f:
452+
return json.load(f)
453+
else:
454+
return {}
455+
456+
457+
def set_defaults_state(state):
458+
"""Save the provided configuration state to the defaults state file.
459+
460+
This function writes the provided state (a dictionary) to a JSON file at
461+
the specified Kolla defaults state location, ensuring that it is properly
462+
formatted with indentation for readability.
463+
464+
Args:
465+
state (dict): The configuration state to save to the Kolla defaults
466+
state file.
467+
"""
468+
with open(KOLLA_DEFAULTS_STATE, 'w') as f:
469+
json.dump(state, f, indent=4)
470+
471+
472+
def remove_or_restore_configs(state):
473+
"""Remove or restore configuration files based on their current state.
474+
475+
This function iterates over the configuration files in the provided state.
476+
If the destination is `None`, it removes the file or directory. Otherwise,
477+
it swaps the source and destination, restoring the configuration file
478+
by copying it back to its original location.
479+
480+
Args:
481+
state (dict): The current default state of configuration files, mapping
482+
file paths to their source and destination information.
483+
"""
484+
for k, v in state.items():
485+
if v['dest'] is None:
486+
if os.path.exists(k):
487+
if os.path.isfile(k):
488+
os.remove(k)
489+
else:
490+
shutil.rmtree(k)
491+
else:
492+
v['source'], v['dest'] = v['dest'], v['source']
493+
config_file = ConfigFile(**v)
494+
config_file.copy()
495+
496+
497+
def backup_configs(config, state):
498+
"""Back up new configuration files and update the default state.
499+
500+
This function processes new configuration files provided in the
501+
input `config`. For each file, it checks if the destination exists in the
502+
current state. If not, it backs up the file by copying it to the default
503+
directory. It then updates the state with the new configuration file's
504+
information.
505+
506+
Args:
507+
config (dict): The input configuration containing a list of config
508+
files.
509+
state (dict): The current default state to be updated with the new
510+
config files.
511+
"""
512+
if 'config_files' in config:
513+
for data in config['config_files']:
514+
if data['dest'] in state.keys():
515+
continue
516+
src = data['source']
517+
if data['dest'].endswith('/'):
518+
dst = data['dest'] + data['source'].split('/')[-1]
519+
else:
520+
dst = data['dest']
521+
default = KOLLA_DEFAULTS + dst
522+
if os.path.exists(src):
523+
copy = {'source': dst, 'preserve_properties': True}
524+
if os.path.exists(dst):
525+
copy['dest'] = default
526+
if dst not in state:
527+
config_file = ConfigFile(**copy)
528+
config_file.copy()
529+
state[dst] = copy
530+
else:
531+
copy['dest'] = None
532+
if dst not in state:
533+
state[dst] = copy
534+
535+
536+
def handle_defaults(config):
537+
"""Handle the default config files by copying/removing them as needed.
538+
539+
This function loads the current default state and manages the configuration
540+
files. It first processes existing configuration files in the default
541+
state, either removing or restoring them based on their destination status.
542+
It then backs up any new configuration files from the input config,
543+
updating the default state accordingly.
544+
545+
Args:
546+
config (dict): A dictionary containing the list of configuration files
547+
to be handled.
548+
"""
549+
state = get_defaults_state()
550+
remove_or_restore_configs(state)
551+
backup_configs(config, state)
552+
set_defaults_state(state)
553+
554+
406555
def execute_config_strategy(config):
407556
config_strategy = os.environ.get("KOLLA_CONFIG_STRATEGY")
408557
LOG.info("Kolla config strategy set to: %s", config_strategy)
409558
if config_strategy == "COPY_ALWAYS":
559+
handle_defaults(config)
410560
copy_config(config)
411561
handle_permissions(config)
412562
elif config_strategy == "COPY_ONCE":
@@ -415,6 +565,7 @@ def execute_config_strategy(config):
415565
"The config strategy prevents copying new configs",
416566
exit_code=0)
417567
else:
568+
handle_defaults(config)
418569
copy_config(config)
419570
handle_permissions(config)
420571
os.mknod('/configured')
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
Fixes the inconsistency issue between config.json and
5+
real state in the container.
6+
`LP#2060855 <https://launchpad.net/bugs/2060855>`__

0 commit comments

Comments
 (0)