Files
2026-06-23 11:27:54 +08:00

198 lines
6.8 KiB
Python

#!/usr/bin/env python3
# Copyright (c) 2024-2025 Broadcom. All Rights Reserved.
# The term "Broadcom" refers to Broadcom Inc.
# and/or its subsidiaries.
import argparse
import datetime
import logging
import logging.config
import os
import pathlib
import sys
import yaml
from lib.console import init_env_colormap, print_text, print_text_error
from lib.constants import VCERT_NAME, VCERT_VERSION, VCERT_DESC, VCERT_PROGRAM, WARNING_TEXT, TOP_DIR
from lib.environment import Environment
from lib.exceptions import MenuExitException
from lib.menu import Menu, MenuInput
from lib.host_utils import init_env_host, VcVersion, get_vc_version, make_directory, remove_directory
from lib.services import check_services_status
from lib.vmdir import init_env_identity_source, init_env_cac
from operation.common import verify_sso_credential, populate_sso_credential
def init_logging():
tools_dir = os.path.dirname(os.path.abspath(__file__))
config_file = os.path.join(tools_dir, 'config/logging.yaml')
with open(config_file, 'r') as stream:
config = yaml.load(stream, Loader=yaml.FullLoader)
log_dir = pathlib.Path(config['handlers']['file']['filename']).parent
try:
os.makedirs(log_dir, exist_ok=True)
except PermissionError:
# this may necessary for remote execution on a restricted environment
tmp_dir = pathlib.Path('/tmp')
new_log_dir = tmp_dir.joinpath(log_dir.relative_to('/'))
os.makedirs(new_log_dir, exist_ok=True)
log_file = pathlib.Path(config['handlers']['file']['filename']).name
new_log_file = pathlib.Path(new_log_dir, log_file)
config['handlers']['file']['filename'] = str(new_log_file)
logging.config.dictConfig(config)
def init_environment(args):
"""
Initialize environment variables
:param args: Command line arguments
"""
env = Environment.get_environment()
if args.environment is not None:
env.load_from_file(args.environment)
env.set_value('VCERT_NAME', VCERT_NAME)
env.set_value('VCERT_VERSION', VCERT_VERSION)
env.set_value('VCERT_DESC', VCERT_DESC)
init_env_host()
init_env_colormap()
init_env_identity_source()
init_env_cac()
check_vc_version()
check_services_status()
if args.password is not None:
if args.user is None:
# args.user = 'administrator@vsphere.local'
args.user = "administrator@{}".format(env.get_value('SSO_DOMAIN'))
if not verify_sso_credential(args.user, args.password):
print("Error: failed to authenticate user {}".format(args.user))
exit(1)
env.set_value('SSO_USERNAME', args.user)
env.set_value('SSO_PASSWORD', args.password)
if env.get_value('SSO_USERNAME') is None:
env.add_restricted_key('SSO_USERNAME', populate_sso_credential)
env.add_restricted_key('SSO_PASSWORD', populate_sso_credential)
def get_timestamp():
return datetime.datetime.utcnow().strftime('%Y%m%d')
def init_working_directory():
# working directory
timestamp = get_timestamp()
work_dir = "{}/{}".format(TOP_DIR, timestamp)
if not make_directory(work_dir):
work_dir = "{}/{}".format(str(pathlib.Path('.').resolve()), timestamp)
request_dir = "{}/requests".format(work_dir)
backup_dir = "{}/backup".format(work_dir)
temp_dir = "{}/temp".format(work_dir)
script_dir = os.path.dirname(os.path.realpath(__file__))
for dir in [request_dir, backup_dir, temp_dir]:
make_directory(dir)
env = Environment.get_environment()
env.set_value('WORK_DIR', work_dir)
env.set_value('BACKUP_DIR', backup_dir)
env.set_value('REQUEST_DIR', request_dir)
env.set_value('TEMP_DIR', temp_dir)
env.set_value('SCRIPT_DIR', script_dir)
def cleanup_working_directory():
"""
Cleanup working directory. Remove directory only if there is no remaining contents
except for temporary directory
"""
env = Environment.get_environment()
remove_directory(env.get_value('BACKUP_DIR'))
remove_directory(env.get_value('REQUEST_DIR'))
remove_directory(env.get_value('TEMP_DIR'), remove_all=True)
remove_directory(env.get_value('WORK_DIR'))
def parse_arguments():
parser = argparse.ArgumentParser(prog=VCERT_PROGRAM, description=VCERT_DESC)
parser.add_argument('--version', action='version', version=VCERT_VERSION)
parser.add_argument('--env', required=False, dest='environment',
help='Config file for environment variables')
parser.add_argument('--run', required=False, dest='operation',
help='Run specific operation directly instead of showing menu')
parser.add_argument('--user', required=False, dest='user',
help='Specify an SSO administrator account')
parser.add_argument('--password', required=False, dest='password',
help='Password for the specified SSO administrator account')
return parser.parse_args(sys.argv[1:])
def check_vc_version():
"""
Check VC version. If the vCenter version is not supported, error message will be displayed
and the program exit immediately
"""
vc_version = get_vc_version()
if vc_version == VcVersion.Invalid:
vc_version_full = Environment.get_environment().get_value('VC_VERSION')
print_text_error("Error: Unsupported vCenter version: {}.\n"
"{} only supports versions {} to {}\n"
.format(
vc_version_full,
VCERT_DESC,
VcVersion.min(),
VcVersion.max()
)
)
sys.exit(1)
def show_warning_message():
"""
Show warning message before using the vCert. For development purpose, this message can be
suppressed using environment setting
"""
env = Environment.get_environment()
suppress_warning_message = env.get_value('VCERT_SUPPRESS_WARNING_MESSAGE') is True
if suppress_warning_message:
return
print_text(WARNING_TEXT, end='')
menu_input = MenuInput('', acceptable_inputs=['Y', 'N'], default_input='N')
if menu_input.get_input() == 'N':
sys.exit(0)
def run_operation(op_config):
try:
Menu.run_operation_from_config(op_config)
except MenuExitException:
pass
def run_menu():
menu = Menu.load_menu_from_config('config/menu_main.yaml')
try:
menu.run()
except MenuExitException:
pass
if __name__ == '__main__':
init_logging()
args = parse_arguments()
init_environment(args)
init_working_directory()
Menu.set_menu_conditions()
try:
if args.operation:
run_operation(args.operation)
else:
show_warning_message()
run_menu()
finally:
cleanup_working_directory()