Skip to content

Commit

Permalink
cephadm: add generic methods for sharing namespaces across containers
Browse files Browse the repository at this point in the history
In the future, some sidecar containers will need to share namespaces
with the primary container (or each other). Make it easy to set this up
by creating a enable_shared_namespaces function and Namespace enum.

Signed-off-by: John Mulligan <jmulligan@redhat.com>
  • Loading branch information
phlogistonjohn committed Mar 21, 2024
1 parent 0c72fcc commit b6fa001
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 1 deletion.
63 changes: 62 additions & 1 deletion src/cephadm/cephadmlib/container_types.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# container_types.py - container instance wrapper types

import copy
import enum
import functools
import os

from typing import Dict, List, Optional, Any, Union, Tuple, cast
from typing import Dict, List, Optional, Any, Union, Tuple, Iterable, cast

from .call_wrappers import call, call_throws, CallVerbosity
from .constants import DEFAULT_TIMEOUT
Expand Down Expand Up @@ -599,3 +601,62 @@ def extract_uid_gid(
raise Error(f'Failed to extract uid/gid for path {ex[0]}: {ex[1]}')

raise RuntimeError('uid/gid not found')


@functools.lru_cache()
def _opt_key(value: str) -> str:
"""Return a (long) option stripped of its value."""
return value.split('=', 1)[0]


def _replace_container_arg(args: List[str], new_arg: str) -> None:
"""Remove and replace arguments that have the same `--xyz` part as
the given `new_arg`. If new_arg is expected to have a value it
must be part of the new_arg string following an equal sign (`=`).
The existing arg may be a single or two strings in the input list.
"""
key = _opt_key(new_arg)
has_value = key != new_arg
try:
idx = [_opt_key(v) for v in args].index(key)
if '=' in args[idx] or not has_value:
del args[idx]
else:
del args[idx]
del args[idx]
except ValueError:
pass
args.append(new_arg)


class Namespace(enum.Enum):
"""General container namespace control options."""

cgroupns = 'cgroupns'
cgroup = 'cgroupns' # alias
ipc = 'ipc'
network = 'network'
pid = 'pid'
userns = 'userns'
user = 'userns' # alias
uts = 'uts'

def to_option(self, value: str) -> str:
return f'--{self}={value}'

def __str__(self) -> str:
return self.value


def enable_shared_namespaces(
args: List[str],
name: str,
ns: Iterable[Namespace],
) -> None:
"""Update the args list to contain options that enable container namespace
sharing where name is the name/id of the target container and ns is a list
or set of namespaces that should be shared.
"""
cc = f'container:{name}'
for n in ns:
_replace_container_arg(args, n.to_option(cc))
62 changes: 62 additions & 0 deletions src/cephadm/tests/test_util_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -906,3 +906,65 @@ def test_daemon_sub_id_systemd_names():
)
with pytest.raises(ValueError):
dsi.service_name


@pytest.mark.parametrize(
"args,new_arg,expected",
[
(['--foo=77'], '--bar', ['--foo=77', '--bar']),
(['--foo=77'], '--foo=12', ['--foo=12']),
(
['--foo=77', '--quux=later', '--range=2-5'],
'--quux=now',
['--foo=77', '--range=2-5', '--quux=now'],
),
(
['--foo=77', '--quux', 'later', '--range=2-5'],
'--quux=now',
['--foo=77', '--range=2-5', '--quux=now'],
),
(
['--foo=77', '--quux', 'later', '--range=2-5'],
'--jiffy',
['--foo=77', '--quux', 'later', '--range=2-5', '--jiffy'],
),
(
['--foo=77', '--quux=buff', '--range=2-5'],
'--quux',
['--foo=77', '--range=2-5', '--quux'],
),
],
)
def test_replace_container_args(args, new_arg, expected):
from cephadmlib.container_types import _replace_container_arg

_args = list(args) # preserve the input so test input is not mutated
_replace_container_arg(_args, new_arg)
assert _args == expected



def test_enable_shared_namespaces():
from cephadmlib.container_types import enable_shared_namespaces, Namespace

args = []
enable_shared_namespaces(args, 'c001d00d', {Namespace.ipc})
assert args == ['--ipc=container:c001d00d']

enable_shared_namespaces(
args, 'c001d00d', [Namespace.uts, Namespace.network]
)
assert args == [
'--ipc=container:c001d00d',
'--uts=container:c001d00d',
'--network=container:c001d00d',
]

enable_shared_namespaces(
args, 'badd33d5', [Namespace.network]
)
assert args == [
'--ipc=container:c001d00d',
'--uts=container:c001d00d',
'--network=container:badd33d5',
]

0 comments on commit b6fa001

Please sign in to comment.