add vmware-tools
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
# Copyright (c) 2024-2025 Broadcom. All Rights Reserved.
|
||||
# The term "Broadcom" refers to Broadcom Inc.
|
||||
# and/or its subsidiaries.
|
||||
|
||||
import glob
|
||||
import importlib
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
from lib.console import print_header, print_text_error
|
||||
from lib.environment import Environment
|
||||
from lib.exceptions import OperationFailed, CommandExecutionError
|
||||
from lib.host_utils import get_config_file_path
|
||||
from lib.input import MenuInput
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ValueSource(object):
|
||||
"""
|
||||
Class for providing operation arguments as part of config file
|
||||
"""
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
|
||||
def get_value(self):
|
||||
return self.value
|
||||
|
||||
|
||||
class EnvironmentSource(object):
|
||||
"""
|
||||
Class for providing operation argument from environment variable
|
||||
"""
|
||||
def __init__(self, key):
|
||||
self.key = key
|
||||
|
||||
def get_value(self):
|
||||
"""
|
||||
Return value from environment
|
||||
"""
|
||||
env = Environment.get_environment()
|
||||
return env.get_value(self.key)
|
||||
|
||||
|
||||
class InputSource(object):
|
||||
"""
|
||||
Class for providing operation arguments via user input dialog
|
||||
"""
|
||||
def __init__(self, text, acceptable_inputs, default_input=None, allow_empty_input=True, case_insensitive=False,
|
||||
masked=False):
|
||||
"""
|
||||
InputSource constructor. All arguments will be passed to MenuInput
|
||||
"""
|
||||
self.text = text
|
||||
self.acceptable_inputs = acceptable_inputs
|
||||
self.default_input = default_input
|
||||
self.allow_empty_input = allow_empty_input
|
||||
self.case_insensitive = case_insensitive
|
||||
self.masked = masked
|
||||
|
||||
def get_value(self):
|
||||
"""
|
||||
Return value obtained from MenuInput execution
|
||||
"""
|
||||
source_input = MenuInput(self.text, self.acceptable_inputs, self.default_input, self.allow_empty_input,
|
||||
self.case_insensitive, self.masked)
|
||||
return source_input.get_input()
|
||||
|
||||
|
||||
class OperationArgument(object):
|
||||
"""
|
||||
Class for defining operation argument
|
||||
"""
|
||||
def __init__(self, name, source):
|
||||
self.name = name
|
||||
self.source = source
|
||||
|
||||
|
||||
class Operation(object):
|
||||
"""
|
||||
Class for defining operation object
|
||||
"""
|
||||
def __init__(self, title, module_name, method_name, condition_key):
|
||||
"""
|
||||
Operation constructor method
|
||||
|
||||
:param title: text to be displayed when the operation is executed
|
||||
:param module_name: module to be load to find the method for this operation
|
||||
:param method_name: method to be called for this operation
|
||||
:param condition_key: key to be used to evaluate if the operation is disabled
|
||||
"""
|
||||
env = Environment.get_environment()
|
||||
sys.path.append(env.get_value('SCRIPT_DIR'))
|
||||
self.title = title
|
||||
self.module = importlib.import_module(module_name)
|
||||
obj = self.module
|
||||
for attr_name in method_name.split('.'):
|
||||
obj = getattr(obj, attr_name)
|
||||
self.method = obj
|
||||
self.arguments = []
|
||||
self.condition_key = condition_key
|
||||
|
||||
def add_argument(self, name, source):
|
||||
self.arguments.append(OperationArgument(name, source))
|
||||
|
||||
def get_argument_values(self):
|
||||
"""
|
||||
Get operation arguments as dict. This method will also reset CURRENT_MENU
|
||||
environment with this mapping
|
||||
"""
|
||||
args = dict()
|
||||
env = Environment.get_environment()
|
||||
env.set_value('CURRENT_MENU', args)
|
||||
for arg in self.arguments:
|
||||
value = arg.source.get_value()
|
||||
args[arg.name] = value
|
||||
return args
|
||||
|
||||
def is_disabled(self):
|
||||
"""
|
||||
Check if the operation is disabled
|
||||
"""
|
||||
if self.condition_key:
|
||||
return Environment.get_environment().get_value(self.condition_key) is not True
|
||||
else:
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Execute the operation
|
||||
"""
|
||||
if self.is_disabled():
|
||||
print_text_error('Operation is disabled!')
|
||||
print()
|
||||
return
|
||||
|
||||
if self.title:
|
||||
print_header(self.title)
|
||||
try:
|
||||
return self.method(**self.get_argument_values())
|
||||
except CommandExecutionError as e:
|
||||
raise OperationFailed(str(e))
|
||||
|
||||
|
||||
class OperationGroup(object):
|
||||
"""
|
||||
Class for defining operation that aggregate other operations
|
||||
"""
|
||||
def __init__(self, title):
|
||||
self.title = title
|
||||
self.operations = []
|
||||
|
||||
def add_operation(self, op):
|
||||
self.operations.append(op)
|
||||
|
||||
def run(self):
|
||||
for op in self.operations:
|
||||
op.run()
|
||||
|
||||
@staticmethod
|
||||
def load_operation_from_config_obj(config):
|
||||
"""
|
||||
Load operation from loaded config object
|
||||
|
||||
:param config: config file to be loaded
|
||||
"""
|
||||
entry_point = config['entry_point']
|
||||
operation = Operation(config.get('title'), entry_point['module'], entry_point['method'],
|
||||
config.get('condition'))
|
||||
arguments = config.get('arguments')
|
||||
if arguments:
|
||||
for arg in config.get('arguments'):
|
||||
arg_name = arg['name']
|
||||
if arg.get('value') is not None:
|
||||
operation.add_argument(arg_name, ValueSource(arg['value']))
|
||||
continue
|
||||
|
||||
source_config = arg['source']
|
||||
if source_config['type'] == 'input':
|
||||
operation.add_argument(
|
||||
arg_name,
|
||||
InputSource(text=source_config['input_text'],
|
||||
acceptable_inputs=source_config.get('acceptable_inputs'),
|
||||
default_input=source_config.get('default_input'),
|
||||
case_insensitive=(source_config.get('case_insensitive') is True),
|
||||
masked=(source_config.get('masked') is True)))
|
||||
elif source_config['type'] == 'environment':
|
||||
operation.add_argument(arg_name, EnvironmentSource(source_config['key']))
|
||||
return operation
|
||||
|
||||
@staticmethod
|
||||
def load_operation_from_config(config_file):
|
||||
"""
|
||||
Load operation from a yaml config file
|
||||
|
||||
:param config_file: config file to be loaded
|
||||
:return: Return Operation or OperationGroup object
|
||||
"""
|
||||
env = Environment.get_environment()
|
||||
config_file = get_config_file_path(config_file)
|
||||
logger.info("Loading operation from config file {}".format(config_file))
|
||||
with open(config_file, 'r') as file:
|
||||
config = yaml.safe_load(file)
|
||||
if config['type'] == "operation":
|
||||
return Operation.load_operation_from_config_obj(config)
|
||||
|
||||
op_group = Operation.OperationGroup(config.get('title'))
|
||||
for operation in config['operations']:
|
||||
if operation['type'] == 'single':
|
||||
if operation.get('config'):
|
||||
op = Operation.load_operation_from_config(operation['config'])
|
||||
else:
|
||||
op = Operation.load_operation_from_config_obj(operation)
|
||||
op_group.add_operation(op)
|
||||
continue
|
||||
# logger.info("Parsing multiple operations in {}".format(glob.glob(operation['config'])))
|
||||
|
||||
# Only use the SCRIPT_DIR environment setting if the config
|
||||
# path isn't absolute.
|
||||
opconfig = operation['config']
|
||||
if os.path.isabs(opconfig):
|
||||
globPath = opconfig
|
||||
else:
|
||||
globPath = os.path.join(env.get_value('SCRIPT_DIR'), opconfig)
|
||||
|
||||
for config_file in sorted(glob.glob(globPath)):
|
||||
op = Operation.load_operation_from_config(config_file)
|
||||
op_group.add_operation(op)
|
||||
return op_group
|
||||
Reference in New Issue
Block a user