Merge "Add LDAP-related actions in application lifecycle"
This commit is contained in:
commit
a98e6464f6
@ -107,3 +107,5 @@ CEPH_POOL_VOLUMES_CHUNK_SIZE = 512
|
|||||||
|
|
||||||
CEPH_POOL_BACKUP_APP_NAME = 'cinder-backup'
|
CEPH_POOL_BACKUP_APP_NAME = 'cinder-backup'
|
||||||
CEPH_POOL_BACKUP_CHUNK_SIZE = 256
|
CEPH_POOL_BACKUP_CHUNK_SIZE = 256
|
||||||
|
|
||||||
|
OPENSTACK_VOLUME_MOUNT_DIR = "/var/opt/openstack"
|
||||||
|
@ -0,0 +1,185 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from sysinv.common import utils as cutils
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def check_group(group: str) -> bool:
|
||||||
|
"""Check if group exists.
|
||||||
|
|
||||||
|
:returns: bool -- Returns `True` if group exists.
|
||||||
|
Otherwise, returns `False`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# First, run `ldapsearch`.
|
||||||
|
cmd_p1 = [
|
||||||
|
"ldapsearch",
|
||||||
|
"-x",
|
||||||
|
"-b",
|
||||||
|
"ou=Group,dc=cgcs,dc=local",
|
||||||
|
f"(cn={group})",
|
||||||
|
]
|
||||||
|
p1 = subprocess.Popen(
|
||||||
|
cmd_p1, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Second, verify if the `ldapsearch` output contains the word `numEntries`.
|
||||||
|
# If it does, it means that the group exists.
|
||||||
|
cmd_p2 = ["grep", "numEntries"]
|
||||||
|
p2 = subprocess.Popen(cmd_p2, stdin=p1.stdout, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
p1.stdout.close()
|
||||||
|
p2.communicate()
|
||||||
|
|
||||||
|
if p2.returncode == 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def add_group(group: str) -> None:
|
||||||
|
"""Add group.
|
||||||
|
|
||||||
|
:param group: The group name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ["ldapaddgroup", group]
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(f"Failed to add group `{group}`: {stderr}")
|
||||||
|
|
||||||
|
|
||||||
|
def delete_group(group: str) -> None:
|
||||||
|
"""Delete group.
|
||||||
|
|
||||||
|
:param group: The group name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
members = list_group_members(group)
|
||||||
|
for member in members:
|
||||||
|
delete_group_member(member, group)
|
||||||
|
|
||||||
|
cmd = ["ldapdeletegroup", group]
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(f"Failed to delete group `{group}`: {stderr}")
|
||||||
|
|
||||||
|
|
||||||
|
def check_group_member(member: str, group: str) -> bool:
|
||||||
|
"""Check if group member exists.
|
||||||
|
|
||||||
|
:param member: The member name.
|
||||||
|
:param group: The group name.
|
||||||
|
:returns: bool -- Returns `True` if group member exists.
|
||||||
|
Otherwise, returns `False`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# First, run `ldapsearch`.
|
||||||
|
cmd_p1 = [
|
||||||
|
"ldapsearch",
|
||||||
|
"-x",
|
||||||
|
"-b",
|
||||||
|
"ou=Group,dc=cgcs,dc=local",
|
||||||
|
f"(cn={group})",
|
||||||
|
]
|
||||||
|
p1 = subprocess.Popen(
|
||||||
|
cmd_p1, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Second, verify if the `ldapsearch` output contains the word `memberUid`.
|
||||||
|
# If it does, it means that the group not only exists, but also contains
|
||||||
|
# members.
|
||||||
|
cmd_p2 = ["grep", f"memberUid: {member}"]
|
||||||
|
p2 = subprocess.Popen(cmd_p2, stdin=p1.stdout, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
p1.stdout.close()
|
||||||
|
p2.communicate()
|
||||||
|
|
||||||
|
if p2.returncode == 0:
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def add_group_member(member: str, group: str) -> None:
|
||||||
|
"""Add group member.
|
||||||
|
|
||||||
|
:param member: The member name.
|
||||||
|
:param group: The group name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ["ldapaddusertogroup", member, group]
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(
|
||||||
|
f"Failed to add user `{member}` to group `{group}`: {stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_group_member(member: str, group: str) -> None:
|
||||||
|
"""Delete group member.
|
||||||
|
|
||||||
|
:param member: The member name.
|
||||||
|
:param group: The group name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ["ldapdeleteuserfromgroup", member, group]
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(
|
||||||
|
f"Failed to delete user `{member}` from group `{group}`: {stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def list_group_members(group: str) -> List[str]:
|
||||||
|
"""List group members.
|
||||||
|
|
||||||
|
:param group: The group name.
|
||||||
|
:returns: List[str] -- The list of members belonging to
|
||||||
|
the specified group.
|
||||||
|
"""
|
||||||
|
|
||||||
|
members = []
|
||||||
|
|
||||||
|
# First, run `ldapsearch`.
|
||||||
|
cmd_p1 = [
|
||||||
|
"ldapsearch",
|
||||||
|
"-x",
|
||||||
|
"-b",
|
||||||
|
"ou=Group,dc=cgcs,dc=local",
|
||||||
|
f"(cn={group})",
|
||||||
|
]
|
||||||
|
p1 = subprocess.Popen(
|
||||||
|
cmd_p1, stdin=subprocess.PIPE, stdout=subprocess.PIPE
|
||||||
|
)
|
||||||
|
|
||||||
|
# Second, verify if the `ldapsearch` output contains the word `memberUid`.
|
||||||
|
# If it does, it means that the group not only exists, but also contains
|
||||||
|
# members.
|
||||||
|
cmd_p2 = ["grep", "-Poh", "(?<=memberUid: )(.*)"]
|
||||||
|
p2 = subprocess.Popen(cmd_p2, stdin=p1.stdout, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
p1.stdout.close()
|
||||||
|
stdout, _ = p2.communicate()
|
||||||
|
|
||||||
|
if p2.returncode == 0:
|
||||||
|
for user in stdout.decode().split():
|
||||||
|
if user:
|
||||||
|
members.append(user)
|
||||||
|
|
||||||
|
return members
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2021 Wind River Systems, Inc.
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -18,6 +18,8 @@ from sysinv.helm import lifecycle_utils as lifecycle_utils
|
|||||||
from sysinv.helm.lifecycle_constants import LifecycleConstants
|
from sysinv.helm.lifecycle_constants import LifecycleConstants
|
||||||
|
|
||||||
from k8sapp_openstack import utils as app_utils
|
from k8sapp_openstack import utils as app_utils
|
||||||
|
from k8sapp_openstack.common import constants as app_constants
|
||||||
|
from k8sapp_openstack.helpers import ldap
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -97,6 +99,8 @@ class OpenstackAppLifecycleOperator(base.AppLifecycleOperator):
|
|||||||
"""
|
"""
|
||||||
hook_info[LifecycleConstants.EXTRA][self.WAS_APPLIED] = app.active
|
hook_info[LifecycleConstants.EXTRA][self.WAS_APPLIED] = app.active
|
||||||
|
|
||||||
|
self._pre_apply_ldap_actions()
|
||||||
|
|
||||||
def post_apply(self, context, conductor_obj, app, hook_info):
|
def post_apply(self, context, conductor_obj, app, hook_info):
|
||||||
""" Post apply actions
|
""" Post apply actions
|
||||||
|
|
||||||
@ -156,6 +160,8 @@ class OpenstackAppLifecycleOperator(base.AppLifecycleOperator):
|
|||||||
conductor_obj._update_vim_config(context)
|
conductor_obj._update_vim_config(context)
|
||||||
conductor_obj._update_radosgw_config(context)
|
conductor_obj._update_radosgw_config(context)
|
||||||
|
|
||||||
|
self._post_remove_ldap_actions()
|
||||||
|
|
||||||
def _delete_app_specific_resources_post_remove(self, app_op, app, hook_info):
|
def _delete_app_specific_resources_post_remove(self, app_op, app, hook_info):
|
||||||
"""Delete application specific resources.
|
"""Delete application specific resources.
|
||||||
|
|
||||||
@ -291,3 +297,26 @@ class OpenstackAppLifecycleOperator(base.AppLifecycleOperator):
|
|||||||
not installed. Otherwise, False.
|
not installed. Otherwise, False.
|
||||||
"""
|
"""
|
||||||
return app_utils.https_enabled() and not app_utils.is_openstack_https_certificates_ready()
|
return app_utils.https_enabled() and not app_utils.is_openstack_https_certificates_ready()
|
||||||
|
|
||||||
|
def _pre_apply_ldap_actions(self):
|
||||||
|
"""Perform pre apply LDAP-related actions."""
|
||||||
|
|
||||||
|
# Create `openstack` group.
|
||||||
|
has_group = ldap.check_group(app_constants.HELM_NS_OPENSTACK)
|
||||||
|
if not has_group:
|
||||||
|
ldap.add_group(app_constants.HELM_NS_OPENSTACK)
|
||||||
|
|
||||||
|
# Create the volume mount directory.
|
||||||
|
app_utils.create_openstack_volume_mount()
|
||||||
|
|
||||||
|
def _post_remove_ldap_actions(self):
|
||||||
|
"""Perform post remove LDAP-related actions."""
|
||||||
|
|
||||||
|
# Try to delete the volume mount directory.
|
||||||
|
# If successful, delete `openstack` group.
|
||||||
|
# Otherwise, do nothing.
|
||||||
|
deleted = app_utils.delete_openstack_volume_mount()
|
||||||
|
if deleted:
|
||||||
|
has_group = ldap.check_group(app_constants.HELM_NS_OPENSTACK)
|
||||||
|
if has_group:
|
||||||
|
ldap.delete_group(app_constants.HELM_NS_OPENSTACK)
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
#
|
#
|
||||||
# Copyright (c) 2022 Wind River Systems, Inc.
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
from sysinv.common import constants
|
from sysinv.common import constants
|
||||||
|
from sysinv.common import utils as cutils
|
||||||
from sysinv.db import api as dbapi
|
from sysinv.db import api as dbapi
|
||||||
|
|
||||||
|
from k8sapp_openstack.common import constants as app_constants
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def https_enabled():
|
def https_enabled():
|
||||||
db = dbapi.get_instance()
|
db = dbapi.get_instance()
|
||||||
@ -47,3 +56,156 @@ def is_openstack_https_ready():
|
|||||||
installed in the system.
|
installed in the system.
|
||||||
"""
|
"""
|
||||||
return https_enabled() and is_openstack_https_certificates_ready()
|
return https_enabled() and is_openstack_https_certificates_ready()
|
||||||
|
|
||||||
|
|
||||||
|
def change_file_group_ownership(
|
||||||
|
file: str,
|
||||||
|
group: str,
|
||||||
|
recursive: bool = False
|
||||||
|
) -> None:
|
||||||
|
"""Change file's group ownership.
|
||||||
|
|
||||||
|
:param file: The file path.
|
||||||
|
:param group: The group name.
|
||||||
|
:param recursive: bool -- The flag that indicates whether permissions
|
||||||
|
should be changed recursively or not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ["chgrp", group, file]
|
||||||
|
|
||||||
|
if recursive:
|
||||||
|
cmd.insert(1, "-R")
|
||||||
|
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(
|
||||||
|
f"Failed to change group ownership of `{file}` "
|
||||||
|
f"to `{group}`: {stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def change_file_owner(
|
||||||
|
file: str,
|
||||||
|
user: str = "",
|
||||||
|
group: str = "",
|
||||||
|
recursive: bool = False
|
||||||
|
) -> None:
|
||||||
|
"""Change file's owner (chown).
|
||||||
|
|
||||||
|
:param file: The file path.
|
||||||
|
:param user: The desired user.
|
||||||
|
:param group: The desired group.
|
||||||
|
:param recursive: bool -- The flag that indicates whether ownerships
|
||||||
|
should be changed recursively or not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
ownership = ""
|
||||||
|
|
||||||
|
if user:
|
||||||
|
ownership += user
|
||||||
|
|
||||||
|
if group:
|
||||||
|
ownership += f":{group}"
|
||||||
|
|
||||||
|
if not ownership:
|
||||||
|
return
|
||||||
|
|
||||||
|
cmd = ["chown", ownership, file]
|
||||||
|
|
||||||
|
if recursive:
|
||||||
|
cmd.insert(1, "-R")
|
||||||
|
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(
|
||||||
|
f"Failed to change ownership of `{file}` "
|
||||||
|
f"to `{ownership}`: {stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def change_file_mode(
|
||||||
|
file: str,
|
||||||
|
mode: str,
|
||||||
|
recursive: bool = False
|
||||||
|
) -> None:
|
||||||
|
"""Change file's mode (chmod).
|
||||||
|
|
||||||
|
|
||||||
|
:param file: The file path.
|
||||||
|
:param mode: The desired mode.
|
||||||
|
:param recursive: bool -- The flag that indicates whether modes should be
|
||||||
|
changed recursively or not.
|
||||||
|
"""
|
||||||
|
|
||||||
|
cmd = ["chmod", mode, file]
|
||||||
|
|
||||||
|
if recursive:
|
||||||
|
cmd.insert(1, "-R")
|
||||||
|
|
||||||
|
_, stderr = cutils.trycmd(*cmd, run_as_root=True)
|
||||||
|
|
||||||
|
if stderr:
|
||||||
|
LOG.warning(
|
||||||
|
f"Failed to change mode of `{file}` to `{mode}`: {stderr}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def create_openstack_volume_mount() -> None:
|
||||||
|
"""Create OpenStack volume mount directory."""
|
||||||
|
|
||||||
|
p = Path(app_constants.OPENSTACK_VOLUME_MOUNT_DIR)
|
||||||
|
p.mkdir(exist_ok=True)
|
||||||
|
|
||||||
|
# Change modes of the volume mount directory.
|
||||||
|
change_file_mode(
|
||||||
|
str(p),
|
||||||
|
mode="770",
|
||||||
|
recursive=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Change ownership of the volume mount directory.
|
||||||
|
change_file_owner(
|
||||||
|
str(p),
|
||||||
|
user="sysadmin",
|
||||||
|
group=app_constants.HELM_NS_OPENSTACK,
|
||||||
|
recursive=True
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_openstack_volume_mount() -> bool:
|
||||||
|
"""Delete OpenStack volume mount.
|
||||||
|
|
||||||
|
:returns: bool -- True, if volume mount directory was successfully deleted.
|
||||||
|
False, if otherwise.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Search for additional files that might have been created by users.
|
||||||
|
directories = [app_constants.OPENSTACK_VOLUME_MOUNT_DIR]
|
||||||
|
while directories:
|
||||||
|
p = Path(directories.pop(0))
|
||||||
|
for pathname in p.glob("*"):
|
||||||
|
if pathname.is_dir():
|
||||||
|
directories.append(str(pathname))
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
# Ignore files in the root directory.
|
||||||
|
if str(p) == app_constants.OPENSTACK_VOLUME_MOUNT_DIR:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# If there is at least one file created by users outside the
|
||||||
|
# root directory, that is, in a user subdirectory, it means
|
||||||
|
# that we can't remove the volume mount directory.
|
||||||
|
LOG.warning(
|
||||||
|
f"Unable to delete OpenStack volume mount directory "
|
||||||
|
f"`{app_constants.OPENSTACK_VOLUME_MOUNT_DIR}`. "
|
||||||
|
f"There are one or more user files in subdirectories."
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
shutil.rmtree(
|
||||||
|
app_constants.OPENSTACK_VOLUME_MOUNT_DIR, ignore_errors=True
|
||||||
|
)
|
||||||
|
|
||||||
|
return True
|
||||||
|
@ -1,19 +1,20 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Clears OpenStack service aliases.
|
||||||
|
#
|
||||||
|
|
||||||
{{/*
|
SERVICES=(
|
||||||
Copyright (c) 2023 Wind River Systems, Inc.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/}}
|
|
||||||
|
|
||||||
SERVICES="
|
|
||||||
openstack
|
|
||||||
nova
|
|
||||||
cinder
|
cinder
|
||||||
glance
|
glance
|
||||||
heat
|
heat
|
||||||
"
|
nova
|
||||||
|
openstack
|
||||||
|
)
|
||||||
|
|
||||||
for service in ${SERVICES}; do
|
for service in "${SERVICES[@]}"; do
|
||||||
unalias "${service}" 2> /dev/null
|
unalias "${service}" 2> /dev/null
|
||||||
done
|
done
|
||||||
|
@ -1,21 +1,68 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
#
|
||||||
{{/*
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
Copyright (c) 2023 Wind River Systems, Inc.
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
SPDX-License-Identifier: Apache-2.0
|
#
|
||||||
*/}}
|
# Copies setup scripts to the volume mount directory and creates an openrc
|
||||||
|
# file for admin access to the OpenStack clients container.
|
||||||
|
#
|
||||||
|
|
||||||
set -ex
|
set -ex
|
||||||
|
|
||||||
|
TMP_DIR=/tmp
|
||||||
OPENSTACK_DIR=/var/opt/openstack
|
OPENSTACK_DIR=/var/opt/openstack
|
||||||
|
|
||||||
OPENSTACK_SCRIPTS=(
|
OPENSTACK_SETUP_SCRIPTS=(
|
||||||
/tmp/clear-aliases.sh
|
clear-aliases.sh
|
||||||
/tmp/setup-aliases.sh
|
setup-aliases.sh
|
||||||
/tmp/wrapper.sh
|
clients-wrapper.sh
|
||||||
|
local_openstackrc
|
||||||
)
|
)
|
||||||
|
|
||||||
mkdir -p ${OPENSTACK_DIR}/sysadmin
|
# Store ownership of the volume mount directory to use it later on other files.
|
||||||
cp ${OPENSTACK_SCRIPTS[@]} ${OPENSTACK_DIR}
|
ownership=$(ls -nd "${OPENSTACK_DIR}" | awk '{print $3":"$4}')
|
||||||
chmod -R 755 ${OPENSTACK_DIR}
|
|
||||||
|
# Copy setup scripts to volume mount directory and adjust their mode/ownership
|
||||||
|
# to make them only usable by their corresponding owners and/or groups.
|
||||||
|
for setup_script in "${OPENSTACK_SETUP_SCRIPTS[@]}"; do
|
||||||
|
|
||||||
|
cp "${TMP_DIR}/${setup_script}" "${OPENSTACK_DIR}"
|
||||||
|
chmod 550 "${OPENSTACK_DIR}/${setup_script}"
|
||||||
|
chown "${ownership}" "${OPENSTACK_DIR}/${setup_script}"
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create openrc file for admin access.
|
||||||
|
ADMIN_OPENRC="${OPENSTACK_DIR}/admin-openrc"
|
||||||
|
|
||||||
|
touch "${ADMIN_OPENRC}"
|
||||||
|
chmod 600 "${ADMIN_OPENRC}"
|
||||||
|
chown "${ownership}" "${ADMIN_OPENRC}"
|
||||||
|
|
||||||
|
cat << EOF >> "${ADMIN_OPENRC}"
|
||||||
|
source /etc/platform/openrc --no_credentials
|
||||||
|
|
||||||
|
if [[ "$?" -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "${OPENSTACK_DIR}/setup-aliases.sh"
|
||||||
|
|
||||||
|
if [[ "$?" -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export OS_USERNAME={{ .Values.endpoints.identity.auth.admin.username }}
|
||||||
|
export OS_PASSWORD={{ .Values.endpoints.identity.auth.admin.password }}
|
||||||
|
|
||||||
|
export OS_AUTH_URL=\
|
||||||
|
{{ .Values.endpoints.identity.scheme.default }}://\
|
||||||
|
{{ .Values.endpoints.identity.name }}.openstack.svc.\
|
||||||
|
{{ .Values.endpoints.cluster_domain_suffix }}\
|
||||||
|
{{ .Values.endpoints.identity.path.default }}
|
||||||
|
|
||||||
|
export PS1='[\u@\h \W(keystone_\$OS_USERNAME)]\$ '
|
||||||
|
|
||||||
|
return 0
|
||||||
|
EOF
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
#!/bin/bash -i
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# OpenStack clients wrapper responsible for executing commands
|
||||||
|
# passed as arguments in a containerized environment.
|
||||||
|
#
|
||||||
|
|
||||||
|
OPENSTACK_DIR=/var/opt/openstack
|
||||||
|
|
||||||
|
OPENSTACK_VARIABLES=(
|
||||||
|
OS_AUTH_TYPE
|
||||||
|
OS_AUTH_URL
|
||||||
|
OS_CACERT
|
||||||
|
OS_IDENTITY_API_SERVICE
|
||||||
|
OS_INTERFACE
|
||||||
|
OS_PASSWORD
|
||||||
|
OS_PROJECT_DOMAIN_ID
|
||||||
|
OS_PROJECT_DOMAIN_NAME
|
||||||
|
OS_PROJECT_ID
|
||||||
|
OS_PROJECT_NAME
|
||||||
|
OS_REGION_NAME
|
||||||
|
OS_USERNAME
|
||||||
|
OS_USER_DOMAIN_NAME
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ -z "${KUBECONFIG}" ]]; then
|
||||||
|
KUBECONFIG=/etc/kubernetes/admin.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
ENV_ARGUMENTS=()
|
||||||
|
for variable in "${OPENSTACK_VARIABLES[@]}"; do
|
||||||
|
if [[ ! -z "$(printenv ${variable})" ]]; then
|
||||||
|
ENV_ARGUMENTS+=("${variable}=$(printenv ${variable})")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
CONTROLLER=$(echo "${PS1@P}" | grep -Po 'controller-\d+' | cut -d $'\n' -f 1)
|
||||||
|
if [[ -z "${CONTROLLER}" ]]; then
|
||||||
|
echo "OpenStack CLIs can only be accessed from a controller node."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
POD=$(
|
||||||
|
kubectl --kubeconfig "${KUBECONFIG}" -n openstack get pods \
|
||||||
|
| grep -i "clients-${CONTROLLER}.*Running" | awk '{print $1}'
|
||||||
|
)
|
||||||
|
if [[ -z "${POD}" ]]; then
|
||||||
|
echo "Could not find \`clients\` pod in ${CONTROLLER}."
|
||||||
|
echo "Make sure the pod is running and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if grep -q "^${USER}:" /etc/passwd; then
|
||||||
|
kubectl --kubeconfig "${KUBECONFIG}" -n openstack exec -it "${POD}" \
|
||||||
|
-c clients -- env ${ENV_ARGUMENTS[@]} /bin/bash -c "$*"
|
||||||
|
else
|
||||||
|
if [[ ! -d "${OPENSTACK_DIR}/${USER}" ]]; then
|
||||||
|
mkdir -p "${OPENSTACK_DIR}/${USER}"
|
||||||
|
chgrp -R openstack "${OPENSTACK_DIR}/${USER}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
kubectl --kubeconfig "${KUBECONFIG}" -n openstack exec -it "${POD}" \
|
||||||
|
-c clients -- env ${ENV_ARGUMENTS[@]} /bin/bash -c "cd ${USER}; $*"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
# Creates and/or loads local file "~/$USER-openrc-openstack".
|
||||||
|
#
|
||||||
|
# Assumes the Keystone username is the same as the logged in username.
|
||||||
|
#
|
||||||
|
|
||||||
|
OPENSTACK_DIR=/var/opt/openstack
|
||||||
|
OPENSTACK_OPENRC=${HOME}/${USER}-openrc-openstack
|
||||||
|
|
||||||
|
# Check if local openrc file exists.
|
||||||
|
if [[ -e "${OPENSTACK_OPENRC}" ]]; then
|
||||||
|
|
||||||
|
# If it does, source it.
|
||||||
|
source "${OPENSTACK_OPENRC}"
|
||||||
|
return $?
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Otherwise, create and source it.
|
||||||
|
read -s -p "Enter password for Keystone user \`${USER}\`: " password
|
||||||
|
|
||||||
|
touch "${OPENSTACK_OPENRC}"
|
||||||
|
chmod 600 "${OPENSTACK_OPENRC}"
|
||||||
|
|
||||||
|
cat << EOF >> "${OPENSTACK_OPENRC}"
|
||||||
|
source /etc/platform/openrc --no_credentials
|
||||||
|
|
||||||
|
if [[ "$?" -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
source "${OPENSTACK_DIR}/setup-aliases.sh"
|
||||||
|
|
||||||
|
if [[ "$?" -ne 0 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export OS_USERNAME="${USER}"
|
||||||
|
export OS_PASSWORD="${password}"
|
||||||
|
|
||||||
|
export OS_AUTH_URL=\
|
||||||
|
{{ .Values.endpoints.identity.scheme.default }}://\
|
||||||
|
{{ .Values.endpoints.identity.name }}.openstack.svc.\
|
||||||
|
{{ .Values.endpoints.cluster_domain_suffix }}\
|
||||||
|
{{ .Values.endpoints.identity.path.default }}
|
||||||
|
|
||||||
|
export PS1='[\u@\h \W(keystone_\$OS_USERNAME)]\$ '
|
||||||
|
|
||||||
|
return 0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Created file \`${OPENSTACK_OPENRC}\`."
|
||||||
|
source "${OPENSTACK_OPENRC}"
|
||||||
|
return $?
|
@ -1,25 +1,29 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
#
|
||||||
{{/*
|
# Copyright (c) 2023 Wind River Systems, Inc.
|
||||||
Copyright (c) 2023 Wind River Systems, Inc.
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
SPDX-License-Identifier: Apache-2.0
|
#
|
||||||
*/}}
|
# Creates OpenStack service aliases.
|
||||||
|
#
|
||||||
|
# All aliases created redirect OpenStack commands to a wrapper script,
|
||||||
|
# which executes them in a containerized environment.
|
||||||
|
#
|
||||||
|
|
||||||
if [[ ${BASH_SOURCE} = '/'* ]]; then
|
if [[ ${BASH_SOURCE} = '/'* ]]; then
|
||||||
PATH_TO_SCRIPT=$(dirname ${BASH_SOURCE})
|
PATH_TO_SCRIPT=$(dirname "${BASH_SOURCE}")
|
||||||
else
|
else
|
||||||
PATH_TO_SCRIPT=$(pwd)/$(dirname ${BASH_SOURCE})
|
PATH_TO_SCRIPT=$(pwd)/$(dirname "${BASH_SOURCE}")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SERVICES="
|
SERVICES=(
|
||||||
openstack
|
|
||||||
nova
|
|
||||||
cinder
|
cinder
|
||||||
glance
|
glance
|
||||||
heat
|
heat
|
||||||
"
|
nova
|
||||||
|
openstack
|
||||||
|
)
|
||||||
|
|
||||||
for service in ${SERVICES}; do
|
for service in "${SERVICES[@]}"; do
|
||||||
alias "${service}"="${PATH_TO_SCRIPT}/wrapper.sh ${service}"
|
alias "${service}"="${PATH_TO_SCRIPT}/clients-wrapper.sh ${service}"
|
||||||
done
|
done
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
#!/bin/bash -i
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Copyright (c) 2023 Wind River Systems, Inc.
|
|
||||||
|
|
||||||
SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/}}
|
|
||||||
|
|
||||||
OPENSTACK_VARIABLES="
|
|
||||||
OS_AUTH_TYPE
|
|
||||||
OS_AUTH_URL
|
|
||||||
OS_CACERT
|
|
||||||
OS_IDENTITY_API_SERVICE
|
|
||||||
OS_INTERFACE
|
|
||||||
OS_PASSWORD
|
|
||||||
OS_PROJECT_DOMAIN_ID
|
|
||||||
OS_PROJECT_DOMAIN_NAME
|
|
||||||
OS_PROJECT_ID
|
|
||||||
OS_PROJECT_NAME
|
|
||||||
OS_REGION_NAME
|
|
||||||
OS_USERNAME
|
|
||||||
OS_USER_DOMAIN_NAME
|
|
||||||
"
|
|
||||||
|
|
||||||
ENV_ARGUMENTS=()
|
|
||||||
for variable in ${OPENSTACK_VARIABLES}; do
|
|
||||||
if [[ ! -z "$(printenv ${variable})" ]]; then
|
|
||||||
ENV_ARGUMENTS+=("${variable}=$(printenv ${variable})")
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
CONTROLLER=$(echo ${PS1@P} | grep -Po 'controller-\d+')
|
|
||||||
if [[ -z "${CONTROLLER}" ]]; then
|
|
||||||
echo "OpenStack CLIs can only be accessed from a controller node."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
POD=$(kubectl -n openstack get pods | grep -i "clients-${CONTROLLER}.*Running" | awk '{print $1}')
|
|
||||||
if [[ -z "${POD}" ]]; then
|
|
||||||
echo "Could not find \`clients\` pod in ${CONTROLLER}."
|
|
||||||
echo "Make sure the pod is running and try again."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
kubectl -n openstack exec -it ${POD} -c clients -- env ${ENV_ARGUMENTS[@]} $*
|
|
@ -17,12 +17,14 @@ metadata:
|
|||||||
data:
|
data:
|
||||||
clients-init.sh: |
|
clients-init.sh: |
|
||||||
{{ tuple "bin/_clients-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_clients-init.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
|
clients-wrapper.sh: |
|
||||||
|
{{ tuple "bin/_clients-wrapper.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
clear-aliases.sh: |
|
clear-aliases.sh: |
|
||||||
{{ tuple "bin/_clear-aliases.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_clear-aliases.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
setup-aliases.sh: |
|
setup-aliases.sh: |
|
||||||
{{ tuple "bin/_setup-aliases.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_setup-aliases.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
wrapper.sh: |
|
local_openstackrc: |
|
||||||
{{ tuple "bin/_wrapper.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
{{ tuple "bin/_local_openstackrc.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
|
@ -53,6 +53,10 @@ spec:
|
|||||||
mountPath: /tmp/clients-init.sh
|
mountPath: /tmp/clients-init.sh
|
||||||
subPath: clients-init.sh
|
subPath: clients-init.sh
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
- name: clients-bin
|
||||||
|
mountPath: /tmp/clients-wrapper.sh
|
||||||
|
subPath: clients-wrapper.sh
|
||||||
|
readOnly: true
|
||||||
- name: clients-bin
|
- name: clients-bin
|
||||||
mountPath: /tmp/clear-aliases.sh
|
mountPath: /tmp/clear-aliases.sh
|
||||||
subPath: clear-aliases.sh
|
subPath: clear-aliases.sh
|
||||||
@ -62,8 +66,8 @@ spec:
|
|||||||
subPath: setup-aliases.sh
|
subPath: setup-aliases.sh
|
||||||
readOnly: true
|
readOnly: true
|
||||||
- name: clients-bin
|
- name: clients-bin
|
||||||
mountPath: /tmp/wrapper.sh
|
mountPath: /tmp/local_openstackrc
|
||||||
subPath: wrapper.sh
|
subPath: local_openstackrc
|
||||||
readOnly: true
|
readOnly: true
|
||||||
- name: host-var-opt
|
- name: host-var-opt
|
||||||
mountPath: /var/opt
|
mountPath: /var/opt
|
||||||
|
Loading…
x
Reference in New Issue
Block a user