From 94b499f5717178ed8be6f64a0fd9087d75d1340c Mon Sep 17 00:00:00 2001 From: rkillen Date: Thu, 17 May 2018 18:57:52 -0500 Subject: [PATCH 1/4] Issue#95 - Provide update of topology and resources --- core/src/main/python/update.py | 491 ++++++++++++++++++ .../wlsdeploy/tool/create/domain_creator.py | 49 +- .../wlsdeploy/tool/deploy/topology_updater.py | 93 ++++ .../wlsdeploy/tool/util/topology_helper.py | 91 ++++ .../deploy/messages/wlsdeploy_rb.properties | 3 + installer/src/main/bin/updateDomain.cmd | 393 ++++++++++++++ installer/src/main/bin/updateDomain.sh | 332 ++++++++++++ 7 files changed, 1409 insertions(+), 43 deletions(-) create mode 100644 core/src/main/python/update.py create mode 100644 core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py create mode 100644 core/src/main/python/wlsdeploy/tool/util/topology_helper.py create mode 100644 installer/src/main/bin/updateDomain.cmd create mode 100644 installer/src/main/bin/updateDomain.sh diff --git a/core/src/main/python/update.py b/core/src/main/python/update.py new file mode 100644 index 0000000000..519e562e9c --- /dev/null +++ b/core/src/main/python/update.py @@ -0,0 +1,491 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 + +The entry point for the updateDomain tool. +""" +import javaos as os +import sys + +from java.io import IOException +from java.lang import IllegalArgumentException +from java.lang import IllegalStateException +from java.lang import String + +from oracle.weblogic.deploy.deploy import DeployException +from oracle.weblogic.deploy.exception import BundleAwareException +from oracle.weblogic.deploy.util import CLAException +from oracle.weblogic.deploy.util import FileUtils +from oracle.weblogic.deploy.util import PyWLSTException +from oracle.weblogic.deploy.util import TranslateException +from oracle.weblogic.deploy.util import VariableException +from oracle.weblogic.deploy.util import WebLogicDeployToolingVersion +from oracle.weblogic.deploy.util import WLSDeployArchive +from oracle.weblogic.deploy.util import WLSDeployArchiveIOException +from oracle.weblogic.deploy.validate import ValidateException + +sys.path.append(os.path.dirname(os.path.realpath(sys.argv[0]))) + +# imports from local packages start here +from wlsdeploy.aliases.aliases import Aliases +from wlsdeploy.aliases.wlst_modes import WlstModes +from wlsdeploy.exception import exception_helper +from wlsdeploy.exception.expection_types import ExceptionType +from wlsdeploy.logging.platform_logger import PlatformLogger +from wlsdeploy.tool.deploy import deployer_utils +from wlsdeploy.tool.deploy import model_deployer +from wlsdeploy.tool.deploy.topology_updater import TopologyUpdater +from wlsdeploy.tool.validate.validator import Validator +from wlsdeploy.tool.util import filter_helper +from wlsdeploy.tool.util.wlst_helper import WlstHelper +from wlsdeploy.util import getcreds +from wlsdeploy.util import variables +from wlsdeploy.util.cla_utils import CommandLineArgUtil +from wlsdeploy.util.model import Model +from wlsdeploy.util.model_context import ModelContext +from wlsdeploy.util.model_translator import FileToPython +from wlsdeploy.util.weblogic_helper import WebLogicHelper + + +_program_name = 'updateDomain' +_class_name = 'update' +__logger = PlatformLogger('wlsdeploy.update') +__wls_helper = WebLogicHelper(__logger) +__wlst_helper = WlstHelper(__logger, ExceptionType.DEPLOY) +__wlst_mode = WlstModes.OFFLINE +__tmp_model_dir = None + +__required_arguments = [ + CommandLineArgUtil.ORACLE_HOME_SWITCH, + CommandLineArgUtil.DOMAIN_HOME_SWITCH +] + +__optional_arguments = [ + # Used by shell script to locate WLST + CommandLineArgUtil.DOMAIN_TYPE_SWITCH, + CommandLineArgUtil.ARCHIVE_FILE_SWITCH, + CommandLineArgUtil.MODEL_FILE_SWITCH, + CommandLineArgUtil.PREVIOUS_MODEL_FILE_SWITCH, + CommandLineArgUtil.VARIABLE_FILE_SWITCH, + CommandLineArgUtil.ADMIN_URL_SWITCH, + CommandLineArgUtil.ADMIN_USER_SWITCH, + CommandLineArgUtil.ADMIN_PASS_SWITCH, + CommandLineArgUtil.USE_ENCRYPTION_SWITCH, + CommandLineArgUtil.PASSPHRASE_SWITCH +] + + +def __process_args(args): + """ + Process the command-line arguments and prompt the user for any missing information + :param args: the command-line arguments list + :raises CLAException: if an error occurs while validating and processing the command-line arguments + """ + global __wlst_mode + + cla_util = CommandLineArgUtil(_program_name, __required_arguments, __optional_arguments) + required_arg_map, optional_arg_map = cla_util.process_args(args) + + __verify_required_args_present(required_arg_map) + __process_model_args(optional_arg_map) + __wlst_mode = __process_online_args(optional_arg_map) + __process_encryption_args(optional_arg_map) + + combined_arg_map = optional_arg_map.copy() + combined_arg_map.update(required_arg_map) + + return ModelContext(_program_name, combined_arg_map) + + +def __verify_required_args_present(required_arg_map): + """ + Verify that the required args are present. + :param required_arg_map: the required arguments map + :raises CLAException: if one or more of the required arguments are missing + """ + _method_name = '__verify_required_args_present' + + for req_arg in __required_arguments: + if req_arg not in required_arg_map: + ex = exception_helper.create_cla_exception('WLSDPLY-20005', _program_name, req_arg) + ex.setExitCode(CommandLineArgUtil.USAGE_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return + + +def __validate_archive_file_arg(required_arg_map): + """ + Verify that the archive file exists. + :param required_arg_map: the required arguments map + :return: the archive file name + :raises CLAException: if the archive file is not valid + """ + _method_name = '__validate_archive_file_arg' + + archive_file_name = required_arg_map[CommandLineArgUtil.ARCHIVE_FILE_SWITCH] + try: + FileUtils.validateExistingFile(archive_file_name) + except IllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-20014', _program_name, archive_file_name, + iae.getLocalizedMessage(), error=iae) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return archive_file_name + + +def __process_model_args(optional_arg_map): + """ + Determine if the model file was passed separately or requires extraction from the archive. + :param optional_arg_map: the optional arguments map + :raises CLAException: If an error occurs validating the arguments or extracting the model from the archive + """ + _method_name = '__process_model_args' + global __tmp_model_dir + + archive_file_name = None + if CommandLineArgUtil.ARCHIVE_FILE_SWITCH in optional_arg_map: + archive_file_name = optional_arg_map[CommandLineArgUtil.ARCHIVE_FILE_SWITCH] + + try: + FileUtils.validateExistingFile(archive_file_name) + except IllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-20014', _program_name, archive_file_name, + iae.getLocalizedMessage(), error=iae) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + + if CommandLineArgUtil.MODEL_FILE_SWITCH in optional_arg_map: + model_file_name = optional_arg_map[CommandLineArgUtil.MODEL_FILE_SWITCH] + + try: + FileUtils.validateExistingFile(model_file_name) + except IllegalArgumentException, iae: + ex = exception_helper.create_cla_exception('WLSDPLY-20006', _program_name, model_file_name, + iae.getLocalizedMessage(), error=iae) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + elif archive_file_name is not None: + try: + archive_file = WLSDeployArchive(archive_file_name) + __tmp_model_dir = FileUtils.createTempDirectory(_program_name) + model_file_name = \ + FileUtils.fixupFileSeparatorsForJython(archive_file.extractModel(__tmp_model_dir).getAbsolutePath()) + except (IllegalArgumentException, IllegalStateException, WLSDeployArchiveIOException), archex: + ex = exception_helper.create_cla_exception('WLSDPLY-20010', _program_name, archive_file_name, + archex.getLocalizedMessage(), error=archex) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + optional_arg_map[CommandLineArgUtil.MODEL_FILE_SWITCH] = model_file_name + else: + ex = exception_helper.create_cla_exception('WLSDPLY-20015', _program_name, + CommandLineArgUtil.MODEL_FILE_SWITCH, + CommandLineArgUtil.ARCHIVE_FILE_SWITCH) + ex.setExitCode(CommandLineArgUtil.USAGE_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + return + + +def __process_online_args(optional_arg_map): + """ + Determine if we are update in online mode and if so, validate/prompt for the necessary parameters. + :param optional_arg_map: the optional arguments map + :return: the WLST mode + :raises CLAException: if an error occurs reading input from the user + """ + _method_name = '__process_online_args' + + mode = WlstModes.OFFLINE + if CommandLineArgUtil.ADMIN_URL_SWITCH in optional_arg_map: + if CommandLineArgUtil.ADMIN_USER_SWITCH not in optional_arg_map: + try: + username = getcreds.getuser('WLSDPLY-09001') + except IOException, ioe: + ex = exception_helper.create_cla_exception('WLSDPLY-09002', ioe.getLocalizedMessage(), error=ioe) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + optional_arg_map[CommandLineArgUtil.ADMIN_USER_SWITCH] = username + + if CommandLineArgUtil.ADMIN_PASS_SWITCH not in optional_arg_map: + try: + password = getcreds.getpass('WLSDPLY-09003') + except IOException, ioe: + ex = exception_helper.create_cla_exception('WLSDPLY-09004', ioe.getLocalizedMessage(), error=ioe) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + optional_arg_map[CommandLineArgUtil.ADMIN_PASS_SWITCH] = String(password) + + mode = WlstModes.ONLINE + return mode + + +def __process_encryption_args(optional_arg_map): + """ + Determine if the user is using our encryption and if so, get the passphrase. + :param optional_arg_map: the optional arguments map + :raises CLAException: if an error occurs reading the passphrase inout from the user + """ + _method_name = '__process_encryption_args' + + if CommandLineArgUtil.USE_ENCRYPTION_SWITCH in optional_arg_map and \ + CommandLineArgUtil.PASSPHRASE_SWITCH not in optional_arg_map: + try: + passphrase = getcreds.getpass('WLSDPLY-20002') + except IOException, ioe: + ex = exception_helper.create_cla_exception('WLSDPLY-20003', ioe.getLocalizedMessage(), + error=ioe) + ex.setExitCode(CommandLineArgUtil.ARG_VALIDATION_ERROR_EXIT_CODE) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + optional_arg_map[CommandLineArgUtil.PASSPHRASE_SWITCH] = String(passphrase) + return + + +def __update(model, model_context, aliases): + """ + The method that does the heavy lifting for update. + :param model: the model + :param model_context: the model context + :param aliases: the aliases + :raises DeployException: if an error occurs + """ + if __wlst_mode == WlstModes.ONLINE: + __update_online(model, model_context, aliases) + else: + __update_offline(model, model_context, aliases) + return + + +def __update_online(model, model_context, aliases): + """ + Online update orchestration + :param model: the model + :param model_context: the model context + :param aliases: the aliases object + :raises: DeployException: if an error occurs + """ + _method_name = '__update_online' + + admin_url = model_context.get_admin_url() + admin_user = model_context.get_admin_user() + admin_pwd = model_context.get_admin_password() + + __logger.info("WLSDPLY-09005", admin_url, method_name=_method_name, class_name=_class_name) + + try: + __wlst_helper.connect(admin_user, admin_pwd, admin_url) + deployer_utils.ensure_no_uncommitted_changes_or_edit_sessions() + __wlst_helper.edit() + __wlst_helper.start_edit() + except PyWLSTException, pwe: + ex = exception_helper.create_deploy_exception('WLSDPLY-09006', _program_name, admin_url, + pwe.getLocalizedMessage(), error=pwe) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + raise ex + + __logger.info("WLSDPLY-09007", admin_url, method_name=_method_name, class_name=_class_name) + + try: + topology_updater = TopologyUpdater(model, model_context, aliases, wlst_mode=WlstModes.ONLINE) + topology_updater.update() + + model_deployer.deploy_resources(model, model_context, aliases, wlst_mode=__wlst_mode) + except DeployException, de: + __release_edit_session_and_disconnect() + raise de + + try: + __wlst_helper.save() + __wlst_helper.activate() + except PyWLSTException, pwe: + ex = exception_helper.create_deploy_exception('WLSDPLY-09008', pwe.getLocalizedMessage(), error=pwe) + __logger.throwing(ex, class_name=_class_name, method_name=_method_name) + __release_edit_session_and_disconnect() + raise ex + + model_deployer.deploy_applications(model, model_context, aliases, wlst_mode=__wlst_mode) + + try: + __wlst_helper.disconnect() + except PyWLSTException, pwe: + # All the changes are made and active so don't raise an error that causes the program + # to indicate a failure...just log the error since the process is going to exit anyway. + __logger.warning('WLSDPLY-09009', _program_name, pwe.getLocalizedMessage(), error=pwe, + class_name=_class_name, method_name=_method_name) + return + + +def __update_offline(model, model_context, aliases): + """ + Offline update orchestration + :param model: the model + :param model_context: the model context + :param aliases: the aliases object + :raises: DeployException: if an error occurs + """ + _method_name = '__update_offline' + + domain_home = model_context.get_domain_home() + __logger.info("WLSDPLY-09010", domain_home, method_name=_method_name, class_name=_class_name) + + __wlst_helper.read_domain(domain_home) + + topology_updater = TopologyUpdater(model, model_context, aliases, wlst_mode=WlstModes.OFFLINE) + topology_updater.update() + + model_deployer.deploy_model_offline(model, model_context, aliases, wlst_mode=__wlst_mode) + + try: + __wlst_helper.update_domain() + except BundleAwareException, ex: + __close_domain_on_error() + raise ex + + try: + __wlst_helper.close_domain() + except BundleAwareException, ex: + # All the changes are made so don't raise an error that causes the program to indicate + # a failure...just log the error since the process is going to exit anyway. + __logger.warning('WLSDPLY-09011', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + return + + +def __release_edit_session_and_disconnect(): + """ + An online error recovery method. + """ + _method_name = '__release_edit_session_and_disconnect' + try: + __wlst_helper.stop_edit() + __wlst_helper.disconnect() + except BundleAwareException, ex: + # This method is only used for cleanup after an error so don't mask + # the original problem by throwing yet another exception... + __logger.warning('WLSDPLY-09012', ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + return + + +def __close_domain_on_error(): + """ + An offline error recovery method. + """ + _method_name = '__close_domain_on_error' + try: + __wlst_helper.close_domain() + except PyWLSTException, pwe: + # This method is only used for cleanup after an error so don't mask + # the original problem by throwing yet another exception... + __logger.warning('WLSDPLY-09013', pwe.getLocalizedMessage(), error=pwe, + class_name=_class_name, method_name=_method_name) + return + + +def __clean_up_temp_files(): + """ + If a temporary directory was created to extract the model from the archive, delete the directory and its contents. + """ + global __tmp_model_dir + + if __tmp_model_dir is not None: + FileUtils.deleteDirectory(__tmp_model_dir) + __tmp_model_dir = None + + +def validate_model(model_dictionary, model_context, aliases): + _method_name = 'validate_model' + + try: + validator = Validator(model_context, aliases, wlst_mode=__wlst_mode) + + # no need to pass the variable file for processing, substitution has already been performed + return_code = validator.validate_in_tool_mode(model_dictionary, variables_file_name=None, + archive_file_name=model_context.get_archive_file_name()) + except ValidateException, ex: + __logger.severe('WLSDPLY-20000', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + if return_code == Validator.ReturnCode.STOP: + __logger.severe('WLSDPLY-20001', _program_name, class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + +def main(args): + """ + The python entry point for updateDomain. + + :param args: + :return: + """ + _method_name = 'main' + + __logger.entering(args[0], class_name=_class_name, method_name=_method_name) + for index, arg in enumerate(args): + __logger.finer('sys.argv[{0}] = {1}', str(index), str(arg), class_name=_class_name, method_name=_method_name) + + __wlst_helper.silence() + + try: + model_context = __process_args(args) + except CLAException, ex: + exit_code = ex.getExitCode() + if exit_code != CommandLineArgUtil.HELP_EXIT_CODE: + __logger.severe('WLSDPLY-20008', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(exit_code) + + model_file = model_context.get_model_file() + try: + model_dictionary = FileToPython(model_file, True).parse() + except TranslateException, te: + __logger.severe('WLSDPLY-09014', _program_name, model_file, te.getLocalizedMessage(), error=te, + class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + try: + variable_map = {} + if model_context.get_variable_file(): + variable_map = variables.load_variables(model_context.get_variable_file()) + variables.substitute(model_dictionary, variable_map) + except VariableException, ex: + __logger.severe('WLSDPLY-20004', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + aliases = Aliases(model_context, wlst_mode=__wlst_mode) + validate_model(model_dictionary, model_context, aliases) + + if filter_helper.apply_filters(model_dictionary, "update"): + # if any filters were applied, re-validate the model + validate_model(model_dictionary, model_context, aliases) + + try: + model = Model(model_dictionary) + __update(model, model_context, aliases) + except DeployException, ex: + __logger.severe('WLSDPLY-09015', _program_name, ex.getLocalizedMessage(), error=ex, + class_name=_class_name, method_name=_method_name) + __clean_up_temp_files() + sys.exit(CommandLineArgUtil.PROG_ERROR_EXIT_CODE) + + __clean_up_temp_files() + return + + +if __name__ == "main": + WebLogicDeployToolingVersion.logVersionInfo(_program_name) + main(sys.argv) diff --git a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py index 6066c708e0..fa9614e0f9 100644 --- a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py @@ -7,14 +7,15 @@ from oracle.weblogic.deploy.create import RCURunner from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.wlst_modes import WlstModes from wlsdeploy.exception import exception_helper +from wlsdeploy.exception.expection_types import ExceptionType from wlsdeploy.tool.create.creator import Creator -from wlsdeploy.tool.deploy import deployer_utils from wlsdeploy.tool.deploy import model_deployer from wlsdeploy.tool.util.archive_helper import ArchiveHelper +from wlsdeploy.tool.util.topology_helper import TopologyHelper from wlsdeploy.util import dictionary_utils from wlsdeploy.util import model as model_helper -from wlsdeploy.util.model import Model from wlsdeploy.aliases.model_constants import ACTIVE_TYPE from wlsdeploy.aliases.model_constants import ADJUDICATOR @@ -27,7 +28,6 @@ from wlsdeploy.aliases.model_constants import AUTHORIZER from wlsdeploy.aliases.model_constants import CERT_PATH_PROVIDER from wlsdeploy.aliases.model_constants import CLUSTER -from wlsdeploy.aliases.model_constants import COHERENCE_CLUSTER_SYSTEM_RESOURCE from wlsdeploy.aliases.model_constants import CREDENTIAL_MAPPER from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_NAME from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_TYPE @@ -49,7 +49,6 @@ from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_NAME from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_TYPE from wlsdeploy.aliases.model_constants import DEFAULT_WLS_DOMAIN_NAME -from wlsdeploy.aliases.model_constants import DOMAIN_INFO from wlsdeploy.aliases.model_constants import DOMAIN_LIBRARIES from wlsdeploy.aliases.model_constants import DRIVER_NAME from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_PROPERTY_VALUE @@ -97,7 +96,7 @@ def __init__(self, model_dictionary, model_context, aliases): _method_name = '__init__' Creator.__init__(self, model_dictionary, model_context, aliases) - self._coherence_cluster_elements = [CLUSTER, SERVER, SERVER_TEMPLATE] + self.topology_helper = TopologyHelper(WlstModes.OFFLINE, self.aliases, ExceptionType.CREATE, self.logger) # domainInfo section is required to get the admin password, everything else # is optional and will use the template defaults @@ -172,9 +171,8 @@ def _create_named_mbeans(self, type_name, model_nodes, base_location, log_create :param log_created: whether or not to log created at INFO level, by default it is logged at the FINE level :raises: CreateException: if an error occurs """ - if type_name in self._coherence_cluster_elements: - self._check_coherence_cluster_references(model_nodes, base_location) - # continue with regular processing + self.topology_helper.check_coherence_cluster_references(type_name, model_nodes) + # continue with regular processing Creator._create_named_mbeans(self, type_name, model_nodes, base_location, log_created=log_created) @@ -1172,38 +1170,3 @@ def __fix_up_model_default_identity_asserter(self, base_location, model_name, mo default_value = self.alias_helper.get_model_attribute_default_value(location, ACTIVE_TYPE) subtype_dict[ACTIVE_TYPE] = default_value return - - def _check_coherence_cluster_references(self, named_nodes, location): - """ - If a named element has the Coherence cluster system resource attribute, confirm that the resource exists. - If the resource does not exist, create a placeholder resource to allow assignment. - :param named_nodes: a dictionary containing the named model elements - :param location: the location of the cluster - :return: - """ - for name in named_nodes: - child_nodes = dictionary_utils.get_dictionary_element(named_nodes, name) - resource_name = dictionary_utils.get_element(child_nodes, COHERENCE_CLUSTER_SYSTEM_RESOURCE) - if resource_name is not None: - self._create_placeholder_coherence_cluster(resource_name) - - def _create_placeholder_coherence_cluster(self, cluster_name): - """ - Create a placeholder Coherence cluster system resource to be referenced from a topology element. - The new cluster will be created at the root domain level. - Clusters referenced from the model's resources section should not require placeholder entries. - :param cluster_name: the name of the Coherence cluster system resource to be added - """ - _method_name = '_create_placeholder_coherence_cluster' - original_location = self.wlst_helper.get_pwd() - cluster_location = LocationContext().append_location(COHERENCE_CLUSTER_SYSTEM_RESOURCE) - existing_names = deployer_utils.get_existing_object_list(cluster_location, self.alias_helper) - - if cluster_name not in existing_names: - self.logger.info('WLSDPLY-12230', cluster_name, class_name=self.__class_name, method_name=_method_name) - - cluster_token = self.alias_helper.get_name_token(cluster_location) - cluster_location.add_name_token(cluster_token, cluster_name) - deployer_utils.create_and_cd(cluster_location, existing_names, self.alias_helper) - - self.wlst_helper.cd(original_location) diff --git a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py new file mode 100644 index 0000000000..69b6cbd0b1 --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py @@ -0,0 +1,93 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" +from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.model_constants import CLUSTER +from wlsdeploy.aliases.model_constants import MACHINE +from wlsdeploy.aliases.model_constants import MIGRATABLE_TARGET +from wlsdeploy.aliases.model_constants import SECURITY +from wlsdeploy.aliases.model_constants import SECURITY_CONFIGURATION +from wlsdeploy.aliases.model_constants import SERVER +from wlsdeploy.aliases.model_constants import SERVER_TEMPLATE +from wlsdeploy.aliases.model_constants import UNIX_MACHINE +from wlsdeploy.aliases.wlst_modes import WlstModes +from wlsdeploy.exception.expection_types import ExceptionType +from wlsdeploy.tool.deploy import deployer_utils +from wlsdeploy.tool.deploy.deployer import Deployer +from wlsdeploy.tool.util.topology_helper import TopologyHelper +from wlsdeploy.util import dictionary_utils + + +class TopologyUpdater(Deployer): + """ + Deploy relevant resources at the domain level using WLST. Entry point, deploy() + """ + _class_name = "TopologyUpdater" + + def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE): + Deployer.__init__(self, model, model_context, aliases, wlst_mode) + self._topology = self.model.get_model_topology() + self._resources = self.model.get_model_resources() + self._topology_helper = TopologyHelper(self.wlst_mode, self.aliases, ExceptionType.DEPLOY, self.logger) + + # Override + def _add_named_elements(self, type_name, model_nodes, location): + """ + Override default behavior to create placeholders for referenced Coherence clusters. + :param type_name: the model folder type + :param model_nodes: the model dictionary of the specified model folder type + :param location: the location object to use to create the MBeans + :raises: DeployException: if an error occurs + """ + self._topology_helper.check_coherence_cluster_references(type_name, model_nodes) + # continue with regular processing + + Deployer._add_named_elements(self, type_name, model_nodes, location) + + def update(self): + """ + Deploy resource model elements at the domain level, including multi-tenant elements. + """ + domain_token = deployer_utils.get_domain_token(self.alias_helper) + location = LocationContext() + location.add_name_token(domain_token, self.model_context.get_domain_name()) + + # create a list, then remove each element as it is processed + folder_list = self.alias_helper.get_model_topology_top_level_folder_names() + + # /Security cannot be updated on existing domain + folder_list.remove(SECURITY) + + # TODO: process security configuration + folder_list.remove(SECURITY_CONFIGURATION) + + self._process_section(self._topology, folder_list, MACHINE, location) + self._process_section(self._topology, folder_list, UNIX_MACHINE, location) + + # avoid circular references between clusters and server templates + self._topology_helper.create_placeholder_server_templates(self._topology) + + self._process_section(self._topology, folder_list, CLUSTER, location) + self._process_section(self._topology, folder_list, SERVER_TEMPLATE, location) + self._process_section(self._topology, folder_list, SERVER, location) + + self._process_section(self._topology, folder_list, MIGRATABLE_TARGET, location) + + # process remaining top-level folders. copy list to avoid concurrent update in loop + remaining = list(folder_list) + for folder_name in remaining: + self._process_section(self._topology, folder_list, folder_name, location) + + # TODO: update targeting + + def _process_section(self, folder_dict, folder_list, key, location): + if key in folder_dict: + nodes = dictionary_utils.get_dictionary_element(folder_dict, key) + sub_location = LocationContext(location).append_location(key) + if self.alias_helper.supports_multiple_mbean_instances(sub_location): + self._add_named_elements(key, nodes, location) + else: + self._add_model_elements(key, nodes, location) + + folder_list.remove(key) diff --git a/core/src/main/python/wlsdeploy/tool/util/topology_helper.py b/core/src/main/python/wlsdeploy/tool/util/topology_helper.py new file mode 100644 index 0000000000..7f9a4f7c1c --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/util/topology_helper.py @@ -0,0 +1,91 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" + +import wlsdeploy.tool.deploy.deployer_utils as deployer_utils +import wlsdeploy.util.dictionary_utils as dictionary_utils + +from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.model_constants import CLUSTER +from wlsdeploy.aliases.model_constants import COHERENCE_CLUSTER_SYSTEM_RESOURCE +from wlsdeploy.aliases.model_constants import SERVER +from wlsdeploy.aliases.model_constants import SERVER_TEMPLATE +from wlsdeploy.tool.util.alias_helper import AliasHelper +from wlsdeploy.tool.util.wlst_helper import WlstHelper +from wlsdeploy.util.weblogic_helper import WebLogicHelper + + +class TopologyHelper(object): + """ + Shared code for topology section of model. Domain create and update use this code. + """ + __class_name = 'TopologyHelper' + + def __init__(self, wlst_mode, aliases, exception_type, logger): + self.wlst_mode = wlst_mode + self.aliases = aliases + self.logger = logger + self.alias_helper = AliasHelper(aliases, self.logger, exception_type) + self.wls_helper = WebLogicHelper(self.logger) + self.wlst_helper = WlstHelper(self.logger, exception_type) + + self._coherence_cluster_elements = [CLUSTER, SERVER, SERVER_TEMPLATE] + + def check_coherence_cluster_references(self, type_name, model_nodes): + """ + If the specified type has a Coherence cluster system resource attribute, verify that any referenced resource + exists. If the resource does not exist, create an empty placeholder resource to allow assignment. + :param type_name: the model folder type + :param model_nodes: a dictionary containing the named model elements + :raises: BundleAwareException of the specified type: if an error occurs + """ + if type_name in self._coherence_cluster_elements: + for name in model_nodes: + child_nodes = dictionary_utils.get_dictionary_element(model_nodes, name) + resource_name = dictionary_utils.get_element(child_nodes, COHERENCE_CLUSTER_SYSTEM_RESOURCE) + if resource_name is not None: + self._create_placeholder_coherence_cluster(resource_name) + + def _create_placeholder_coherence_cluster(self, cluster_name): + """ + Create a placeholder Coherence cluster system resource to be referenced from a topology element. + The new cluster will be created at the root domain level. + :param cluster_name: the name of the Coherence cluster system resource to be added + """ + _method_name = '_create_placeholder_coherence_cluster' + original_location = self.wlst_helper.get_pwd() + cluster_location = LocationContext().append_location(COHERENCE_CLUSTER_SYSTEM_RESOURCE) + existing_names = deployer_utils.get_existing_object_list(cluster_location, self.alias_helper) + + if cluster_name not in existing_names: + self.logger.info('WLSDPLY-12230', cluster_name, class_name=self.__class_name, method_name=_method_name) + + cluster_token = self.alias_helper.get_name_token(cluster_location) + cluster_location.add_name_token(cluster_token, cluster_name) + deployer_utils.create_and_cd(cluster_location, existing_names, self.alias_helper) + + self.wlst_helper.cd(original_location) + + def create_placeholder_server_templates(self, topology): + """ + Create a placeholder server template for each name in the topology. + This is necessary because there is a circular dependency between clusters and server templates. + :param topology: the topology model nodes + """ + _method_name = 'create_placeholder_server_templates' + original_location = self.wlst_helper.get_pwd() + template_location = LocationContext().append_location(SERVER_TEMPLATE) + existing_names = deployer_utils.get_existing_object_list(template_location, self.alias_helper) + + template_nodes = dictionary_utils.get_dictionary_element(topology, SERVER_TEMPLATE) + for template_name in template_nodes: + if template_name not in existing_names: + self.logger.info('WLSDPLY-19400', template_name, class_name=self.__class_name, + method_name=_method_name) + + template_token = self.alias_helper.get_name_token(template_location) + template_location.add_name_token(template_token, template_name) + deployer_utils.create_and_cd(template_location, existing_names, self.alias_helper) + + self.wlst_helper.cd(original_location) diff --git a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties index 8eaa2c1a43..7c43843bf0 100644 --- a/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties +++ b/core/src/main/resources/oracle/weblogic/deploy/messages/wlsdeploy_rb.properties @@ -1105,6 +1105,9 @@ WLSDPLY-19305=Failed to extract domain library {0} because it does not exist in WLSDPLY-19306=Unable to extract domain library {0} from archive file {1}: {2} WLSDPLY-19307=Unable to extract classpath libraries from archive file {0} to domain directory {1}: {2} +# wlsdeploy/tool/util/topology_helper.py +WLSDPLY-19400=Creating placeholder for server template {0} + # Common tooling messages used by multiple tools WLSDPLY-20000={0} encountered an unexpected validation error: {1} WLSDPLY-20001={0} did not create the domain because validation failed diff --git a/installer/src/main/bin/updateDomain.cmd b/installer/src/main/bin/updateDomain.cmd new file mode 100644 index 0000000000..53d457e785 --- /dev/null +++ b/installer/src/main/bin/updateDomain.cmd @@ -0,0 +1,393 @@ +@ECHO OFF +@rem ************************************************************************** +@rem updateDomain.cmd +@rem +@rem Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +@rem The Universal Permissive License (UPL), Version 1.0 +@rem +@rem NAME +@rem updateDomain.cmd - WLS Deploy tool to update an existing domain. +@rem +@rem DESCRIPTION +@rem This script updates the domain configuration, adds resources, and +@rem deploys applications. +@rem +@rem +@rem This script uses the following command-line arguments directly, the rest +@rem of the arguments are passed down to the underlying python program: +@rem +@rem - -oracle_home The directory of the existing Oracle Home to use. +@rem This directory must exist and it is the caller^'s +@rem responsibility to verify that it does. This +@rem argument is required. +@rem +@rem - -domain_type The type of domain to create. This argument is +@rem is optional. If not specified, it defaults to WLS. +@rem +@rem - -wlst_path The path to the Oracle Home product directory under +@rem which to find the wlst.cmd script. This is only +@rem needed for pre-12.2.1 upper stack products like SOA. +@rem +@rem For example, for SOA 12.1.3, -wlst_path should be +@rem specified as %ORACLE_HOME%\soa +@rem +@rem This script uses the following variables: +@rem +@rem JAVA_HOME - The location of the JDK to use. The caller must set +@rem this variable to a valid Java 7 (or later) JDK. +@rem +@rem WLSDEPLOY_HOME - The location of the WLS Deploy installation. +@rem If the caller sets this, the callers location will be +@rem honored provided it is an existing directory. +@rem Otherwise, the location will be calculated from the +@rem location of this script. +@rem +@rem WLSDEPLOY_PROPERTIES - Extra system properties to pass to WLST. The caller +@rem can use this environment variable to add additional +@rem system properties to the WLST environment. +@rem + +SETLOCAL + +SET WLSDEPLOY_PROGRAM_NAME=updateDomain + +SET SCRIPT_PATH=%~dp0 +FOR %%i IN ("%SCRIPT_PATH%") DO SET SCRIPT_PATH=%%~fsi +IF %SCRIPT_PATH:~-1%==\ SET SCRIPT_PATH=%SCRIPT_PATH:~0,-1% + +IF NOT DEFINED WLSDEPLOY_HOME ( + SET WLSDEPLOY_HOME=%SCRIPT_PATH%\.. +) ELSE ( + IF NOT EXIST "%WLSDEPLOY_HOME%" ( + ECHO Specified WLSDEPLOY_HOME of "%WLSDEPLOY_HOME%" does not exist >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) +FOR %%i IN ("%WLSDEPLOY_HOME%") DO SET WLSDEPLOY_HOME=%%~fsi +IF %WLSDEPLOY_HOME:~-1%==\ SET WLSDEPLOY_HOME=%WLSDEPLOY_HOME:~0,-1% + +@rem +@rem Make sure that the JAVA_HOME environment variable is set to point to a +@rem JDK 7 or higher JVM (and that it isn't OpenJDK). +@rem +IF NOT DEFINED JAVA_HOME ( + ECHO Please set the JAVA_HOME environment variable to point to a Java 7 installation >&2 + SET RETURN_CODE=2 + GOTO exit_script +) ELSE ( + IF NOT EXIST "%JAVA_HOME%" ( + ECHO Your JAVA_HOME environment variable to points to a non-existent directory: %JAVA_HOME% >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) +FOR %%i IN ("%JAVA_HOME%") DO SET JAVA_HOME=%%~fsi +IF %JAVA_HOME:~-1%==\ SET JAVA_HOME=%JAVA_HOME:~0,-1% + +IF EXIST %JAVA_HOME%\bin\java.exe ( + FOR %%i IN ("%JAVA_HOME%\bin\java.exe") DO SET JAVA_EXE=%%~fsi +) ELSE ( + ECHO Java executable does not exist at %JAVA_HOME%\bin\java.exe does not exist >&2 + SET RETURN_CODE=2 + GOTO exit_script +) + +FOR /F %%i IN ('%JAVA_EXE% -version 2^>^&1') DO ( + IF "%%i" == "OpenJDK" ( + ECHO JAVA_HOME %JAVA_HOME% contains OpenJDK^, which is not supported >&2 + SET RETURN_CODE=2 + GOTO exit_script + ) +) + +@rem +@rem Check to see if no args were given and print the usage message +@rem +IF "%~1" == "" ( + SET RETURN_CODE=0 + GOTO usage +) + +@rem +@rem Find the args required to determine the WLST script to run +@rem + +SET ORACLE_HOME= +SET DOMAIN_TYPE= +SET WLST_PATH_DIR= +SET MIN_JDK_VERSION=7 + +:arg_loop +IF "%1" == "-help" ( + SET RETURN_CODE=0 + GOTO usage +) +IF "%1" == "-oracle_home" ( + SET ORACLE_HOME=%2 + SHIFT + GOTO arg_continue +) +IF "%1" == "-domain_type" ( + SET DOMAIN_TYPE=%2 + SHIFT + GOTO arg_continue +) +IF "%1" == "-wlst_path" ( + SET WLST_PATH_DIR=%2 + SHIFT + GOTO arg_continue +) +IF "%1" == "-use_encryption" ( + SET MIN_JDK_VERSION=8 + GOTO arg_continue +) +@REM If none of the above, unknown argument so skip it +:arg_continue +SHIFT +IF NOT "%~1" == "" ( + GOTO arg_loop +) + +@rem +@rem Validate the JVM version based on whether or not the user asked us to use encryption +@rem +FOR /F tokens^=2-5^ delims^=.-_^" %%j IN ('%JAVA_EXE% -fullversion 2^>^&1') DO ( + SET "JVM_FULL_VERSION=%%j.%%k.%%l_%%m" + SET "JVM_VERSION=%%k" +) + +IF %JVM_VERSION% LSS %MIN_JDK_VERSION% ( + IF %JVM_VERSION% LSS 7 ( + ECHO You are using an unsupported JDK version %JVM_FULL_VERSION% >&2 + ) ELSE ( + ECHO JDK version 1.8 or higher is required when using encryption >&2 + ) + SET RETURN_CODE=2 + GOTO exit_script +) ELSE ( + ECHO JDK version is %JVM_FULL_VERSION%, setting JAVA_VENDOR to Sun... + SET JAVA_VENDOR=Sun +) + +@rem +@rem Check for values of required arguments for this script to continue. +@rem The underlying WLST script has other required arguments. +@rem +IF "%ORACLE_HOME%" == "" ( + ECHO Required argument ORACLE_HOME not provided >&2 + SET RETURN_CODE=99 + GOTO usage +) + +@rem +@rem If the WLST_PATH_DIR is specified, validate that it contains the wlst.cmd script +@rem +IF DEFINED WLST_PATH_DIR ( + FOR %%i IN ("%WLST_PATH_DIR%") DO SET WLST_PATH_DIR=%%~fsi + IF NOT EXIST "%WLST_PATH_DIR%" ( + ECHO WLST_PATH_DIR specified does not exist: %WLST_PATH_DIR% >&2 + SET RETURN_CODE=98 + GOTO exit_script + ) + set "WLST=%WLST_PATH_DIR%\common\bin\wlst.cmd" + IF NOT EXIST "%WLST%" ( + ECHO WLST executable %WLST% not found under specified WLST_PATH_DIR %WLST_PATH_DIR% >&2 + SET RETURN_CODE=98 + GOTO exit_script + ) + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst +) + +@rem +@rem Find the location for wlst.cmd +@rem +SET WLST= +SET USE_JRF_WLST=FALSE +IF DEFINED DOMAIN_TYPE ( + IF "%DOMAIN_TYPE%" == "WLS" ( + SET USE_JRF_WLST=FALSE + GOTO domain_type_recognized + ) + IF "%DOMAIN_TYPE%" == "RestrictedJRF" ( + SET USE_JRF_WLST=TRUE + GOTO domain_type_recognized + ) + IF "%DOMAIN_TYPE%" == "JRF" ( + SET USE_JRF_WLST=TRUE + GOTO domain_type_recognized + ) + ECHO Domain type %DOMAIN_TYPE% not recognized by shell script...assuming JRF is required + SET USE_JRF_WLST=TRUE +) + +:domain_type_recognized +IF "%USE_JRF_WLST%" == "TRUE" ( + IF EXIST "%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) +) ELSE ( + IF EXIST "%ORACLE_HOME%\wlserver_10.3\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\wlserver_10.3\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) + IF EXIST "%ORACLE_HOME%\wlserver_12.1\common\bin\wlst.cmd" ( + SET WLST=%ORACLE_HOME%\wlserver_12.1\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + GOTO found_wlst + ) + IF EXIST "%ORACLE_HOME%\wlserver\common\bin\wlst.cmd" ( + IF EXIST "%ORACLE_HOME%\wlserver\.product.properties" ( + @rem WLS 12.1.2 or WLS 12.1.3 + SET WLST=%ORACLE_HOME%\wlserver\common\bin\wlst.cmd + SET CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + ) ELSE ( + @rem WLS 12.2.1+ + SET WLST=%ORACLE_HOME%\oracle_common\common\bin\wlst.cmd + SET WLST_EXT_CLASSPATH=%WLSDEPLOY_HOME%\lib\weblogic-deploy-core.jar + ) + GOTO found_wlst + ) +) + +IF NOT EXIST "%WLST%" ( + ECHO Unable to locate wlst.cmd script in ORACLE_HOME %ORACLE_HOME% >&2 + SET RETURN_CODE=98 + GOTO exit_script +) +:found_wlst + +SET LOG_CONFIG_CLASS=oracle.weblogic.deploy.logging.WLSDeployLoggingConfig +SET WLST_PROPERTIES=-Dcom.oracle.cie.script.throwException=true +SET "WLST_PROPERTIES=-Djava.util.logging.config.class=%LOG_CONFIG_CLASS% %WLST_PROPERTIES%" +SET "WLST_PROPERTIES=%WLST_PROPERTIES% %WLSDEPLOY_PROPERTIES%" + +IF NOT DEFINED WLSDEPLOY_LOG_PROPERTIES ( + SET WLSDEPLOY_LOG_PROPERTIES=%WLSDEPLOY_HOME%\etc\logging.properties +) +IF NOT DEFINED WLSDEPLOY_LOG_DIRECTORY ( + SET WLSDEPLOY_LOG_DIRECTORY=%WLSDEPLOY_HOME%\logs +) + +ECHO JAVA_HOME = %JAVA_HOME% +ECHO WLST_EXT_CLASSPATH = %WLST_EXT_CLASSPATH% +ECHO CLASSPATH = %CLASSPATH% +ECHO WLST_PROPERTIES = %WLST_PROPERTIES% + +SET PY_SCRIPTS_PATH=%WLSDEPLOY_HOME%\lib\python +ECHO %WLST% %PY_SCRIPTS_PATH%\update.py %* + +"%WLST%" "%PY_SCRIPTS_PATH%\update.py" %* + +SET RETURN_CODE=%ERRORLEVEL% +IF "%RETURN_CODE%" == "103" ( + ECHO. + ECHO updateDomain.cmd completed successfully but the domain requires a restart for the changes to take effect ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +IF "%RETURN_CODE%" == "102" ( + ECHO. + ECHO updateDomain.cmd completed successfully but the effected servers require a restart ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +IF "%RETURN_CODE%" == "101" ( + ECHO. + ECHO updateDomain.cmd was unable to complete due to configuration changes that require a domain restart. Please restart the domain and re-invoke the updateDomain.cmd script with the same arguments ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +IF "%RETURN_CODE%" == "100" ( + GOTO usage +) +IF "%RETURN_CODE%" == "99" ( + GOTO usage +) +IF "%RETURN_CODE%" == "98" ( + ECHO. + ECHO updateDomain.cmd failed due to a parameter validation error >&2 + GOTO exit_script +) +IF "%RETURN_CODE%" == "2" ( + ECHO. + ECHO updateDomain.cmd failed ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +IF "%RETURN_CODE%" == "1" ( + ECHO. + ECHO updateDomain.cmd completed but with some issues ^(exit code = %RETURN_CODE%^) >&2 + GOTO exit_script +) +IF "%RETURN_CODE%" == "0" ( + ECHO. + ECHO updateDomain.cmd completed successfully ^(exit code = %RETURN_CODE%^) + GOTO exit_script +) +@rem Unexpected return code so just print the message and exit... +ECHO. +ECHO updateDomain.cmd failed ^(exit code = %RETURN_CODE%^) >&2 +GOTO exit_script + +:usage +ECHO. +ECHO Usage: %~nx0 [-help] [-use_encryption] +ECHO -oracle_home ^ +ECHO -domain_home ^ +ECHO [-archive_file ^] +ECHO [-model_file ^] +ECHO [-prev_model_file ^] +ECHO [-variable_file ^] +ECHO [-domain_type ^] +ECHO [-wlst_path ^] +ECHO [-admin_url ^ +ECHO -admin_user ^ +ECHO ] +ECHO. +ECHO where: +ECHO oracle-home - the existing Oracle Home directory for the domain +ECHO. +ECHO domain-home - the domain home directory +ECHO. +ECHO archive-file - the path to the archive file to use +ECHO. +ECHO model-file - the location of the model file to use, +ECHO the default is to get the model from the archive +ECHO. +ECHO prev-model-file - the location of the previous model file. +ECHO. +ECHO This is used to remove apps and resources that +ECHO were previously deployed in addition to +ECHO (re)deploying the current apps and resources +ECHO. +ECHO variable-file - the location of the property file containing +ECHO the variable values for all variables used in +ECHO the model +ECHO. +ECHO domain-type - the type of domain (e.g., WLS, JRF). +ECHO Used to locate wlst.cmd if wlst-path not specified +ECHO. +ECHO wlst-path - the Oracle Home subdirectory of the wlst.cmd +ECHO script to use (e.g., ^\soa) +ECHO. +ECHO admin-url - the admin server URL (used for online deploy) +ECHO. +ECHO admin-user - the admin username (used for online deploy) +ECHO. +ECHO The -use_encryption switch tells the program that one or more of the +ECHO passwords in the model or variables files are encrypted. The program will +ECHO prompt for the decryption passphrase to use to decrypt the passwords. +ECHO Please note that Java 8 or higher is required when using this feature. +ECHO. + +:exit_script +IF DEFINED USE_CMD_EXIT ( + EXIT %RETURN_CODE% +) ELSE ( + EXIT /B %RETURN_CODE% +) + +ENDLOCAL diff --git a/installer/src/main/bin/updateDomain.sh b/installer/src/main/bin/updateDomain.sh new file mode 100644 index 0000000000..dd500aaca6 --- /dev/null +++ b/installer/src/main/bin/updateDomain.sh @@ -0,0 +1,332 @@ +#!/bin/sh +# ***************************************************************************** +# updateDomain.sh +# +# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +# The Universal Permissive License (UPL), Version 1.0 +# +# NAME +# updateDomain.sh - WLS Deploy tool to update an existing domain. +# +# DESCRIPTION +# This script updates the domain configuration, adds resources, and +# deploys applications. +# +# +# This script uses the following command-line arguments directly, the rest +# of the arguments are passed down to the underlying python program: +# +# - -oracle_home The directory of the existing Oracle Home to use. +# This directory must exist and it is the caller^'s +# responsibility to verify that it does. This +# argument is required. +# +# - -domain_type The type of domain to create. This argument is +# is optional. If not specified, it defaults to WLS. +# +# - -wlst_path The path to the Oracle Home product directory under +# which to find the wlst.cmd script. This is only +# needed for pre-12.2.1 upper stack products like SOA. +# +# For example, for SOA 12.1.3, -wlst_path should be +# specified as $ORACLE_HOME/soa +# +# This script uses the following variables: +# +# JAVA_HOME - The location of the JDK to use. The caller must set +# this variable to a valid Java 7 (or later) JDK. +# +# WLSDEPLOY_HOME - The location of the WLS Deploy installation. +# If the caller sets this, the callers location will be +# honored provided it is an existing directory. +# Otherwise, the location will be calculated from the +# location of this script. +# +# WLSDEPLOY_PROPERTIES - Extra system properties to pass to WLST. The caller +# can use this environment variable to add additional +# system properties to the WLST environment. +# + +usage() { + echo "" + echo "Usage: $1 [-help] [-use_encryption]" + echo " -oracle_home " + echo " -domain_home " + echo " [-archive_file ]" + echo " [-model_file ]" + echo " [-prev_model_file ]" + echo " [-variable_file ]" + echo " [-domain_type ]" + echo " [-wlst_path ]" + echo " [-admin_url " + echo " -admin_user " + echo " ]" + echo "" + echo " where:" + echo " oracle-home - the existing Oracle Home directory for the domain" + echo "" + echo " domain-home - the domain home directory" + echo "" + echo " archive-file - the path to the archive file to use" + echo "" + echo " model-file - the location of the model file to use," + echo " the default is to get the model from the archive" + echo "" + echo " prev-model-file - the location of the previous model file." + echo "" + echo " This is used to remove apps and resources that" + echo " were previously deployed in addition to" + echo " (re)deploy the current apps and resources" + echo "" + echo " variable-file - the location of the property file containing" + echo " the variable values for all variables used in" + echo " the model" + echo "" + echo " domain-type - the type of domain (e.g., WLS, JRF)." + echo " Used to locate wlst.cmd if wlst-path not specified" + echo "" + echo " wlst-path - the Oracle Home subdirectory of the wlst.cmd" + echo " script to use (e.g., /soa)" + echo "" + echo " admin-url - the admin server URL (used for online deploy)" + echo "" + echo " admin-user - the admin username (used for online deploy)" + echo "" + echo " The -use_encryption switch tells the program that one or more of the" + echo " passwords in the model or variables files are encrypted. The program will" + echo " prompt for the decryption passphrase to use to decrypt the passwords." + echo " Please note that Java 8 or higher is required when using this feature." + echo "" +} + +umask 27 + +WLSDEPLOY_PROGRAM_NAME="updateDomain"; export WLSDEPLOY_PROGRAM_NAME + +if [ "${WLSDEPLOY_HOME}" = "" ]; then + BASEDIR="$( cd "$( dirname $0 )" && pwd )" + WLSDEPLOY_HOME=`cd "${BASEDIR}/.." ; pwd` + export WLSDEPLOY_HOME +elif [ ! -d ${WLSDEPLOY_HOME} ]; then + echo "Specified WLSDEPLOY_HOME of ${WLSDEPLOY_HOME} does not exist" >&2 + exit 2 +fi + +# +# Make sure that the JAVA_HOME environment variable is set to point to a +# JDK 7 or higher JVM (and that it isn't OpenJDK). +# +if [ "${JAVA_HOME}" = "" ]; then + echo "Please set the JAVA_HOME environment variable to point to a Java 7 installation" >&2 + exit 2 +elif [ ! -d "${JAVA_HOME}" ]; then + echo "Your JAVA_HOME environment variable to points to a non-existent directory: ${JAVA_HOME}" >&2 + exit 2 +fi + +if [ -x "${JAVA_HOME}/bin/java" ]; then + JAVA_EXE=${JAVA_HOME}/bin/java +else + echo "Java executable at ${JAVA_HOME}/bin/java either does not exist or is not executable" >&2 + exit 2 +fi + +JVM_OUTPUT=`${JAVA_EXE} -version 2>&1` +case "${JVM_OUTPUT}" in + *OpenJDK*) + echo "JAVA_HOME ${JAVA_HOME} contains OpenJDK, which is not supported" >&2 + exit 2 + ;; +esac + +# +# Check to see if no args were given and print the usage message +# +if [[ $# = 0 ]]; then + usage `basename $0` + exit 0 +fi + +SCRIPT_ARGS="$*" +MIN_JDK_VERSION=7 + +# +# Find the args required to determine the WLST script to run +# + +while [[ $# > 1 ]]; do + key="$1" + case $key in + -help) + usage `basename $0` + exit 0 + ;; + -oracle_home) + ORACLE_HOME="$2" + shift + ;; + -domain_type) + DOMAIN_TYPE="$2" + shift + ;; + -wlst_path) + WLST_PATH_DIR="$2" + shift + ;; + -use_encryption) + MIN_JDK_VERSION=8 + ;; + *) + # unknown option + ;; + esac + shift # past arg or value +done + +# +# Validate the JVM version based on whether or not the user asked us to use encryption +# +JVM_FULL_VERSION=`${JAVA_EXE} -fullversion 2>&1 | awk -F "\"" '{ print $2 }'` +JVM_VERSION=`echo ${JVM_FULL_VERSION} | awk -F "." '{ print $2 }'` + +if [ ${JVM_VERSION} -lt ${MIN_JDK_VERSION} ]; then + if [ ${JVM_VERSION} -lt 7 ]; then + echo "You are using an unsupported JDK version ${JVM_FULL_VERSION}" >&2 + else + echo "JDK version 1.8 or higher is required when using encryption" >&2 + fi + exit 2 +else + echo "JDK version is ${JVM_FULL_VERSION}" +fi + +# +# Check for values of required arguments for this script to continue. +# The underlying WLST script has other required arguments. +# +if [ "${ORACLE_HOME}" = "" ]; then + echo "Required argument ORACLE_HOME not provided" >&2 + usage `basename $0` + exit 99 +elif [ ! -d ${ORACLE_HOME} ]; then + echo "The specified ORACLE_HOME does not exist: ${ORACLE_HOME}" >&2 + exit 98 +fi + +# +# If the WLST_PATH_DIR is specified, validate that it contains the wlst.cmd script +# +if [ "${WLST_PATH_DIR}" != "" ]; then + if [ ! -d ${WLST_PATH_DIR} ]; then + echo "WLST_PATH_DIR specified does not exist: ${WLST_PATH_DIR}" >&2 + exit 98 + fi + WLST=${WLST_PATH_DIR}/common/bin/wlst.sh + if [ ! -x "${WLST}" ]; then + echo "WLST executable ${WLST} not found under specified WLST_PATH_DIR: ${WLST_PATH_DIR}" >&2 + exit 98 + fi + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH +else + # + # Find the location for wlst.sh + # + WLST="" + USE_JRF_WLST=FALSE + if [ "${DOMAIN_TYPE}" = "WLS" ]; then + USE_JRF_WLST=FALSE + elif [ "${DOMAIN_TYPE}" = "RestrictedJRF" ]; then + USE_JRF_WLST=TRUE + elif [ "${DOMAIN_TYPE}" = "JRF" ]; then + USE_JRF_WLST=TRUE + else + echo "Domain type ${DOMAIN_TYPE} not recognized by shell script...assuming JRF is required" + fi + + if [ "${USE_JRF_WLST}" = "TRUE" ]; then + if [ -x ${ORACLE_HOME}/oracle_common/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/oracle_common/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH + fi + else + if [ -x ${ORACLE_HOME}/wlserver_10.3/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/wlserver_10.3/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + elif [ -x ${ORACLE_HOME}/wlserver_12.1/common/bin/wlst.sh ]; then + WLST=${ORACLE_HOME}/wlserver_12.1/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + elif [ -x ${ORACLE_HOME}/wlserver/common/bin/wlst.sh -a -f ${ORACLE_HOME}/wlserver/.product.properties ]; then + WLST=${ORACLE_HOME}/wlserver/common/bin/wlst.sh + CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export CLASSPATH + else + WLST=${ORACLE_HOME}/oracle_common/common/bin/wlst.sh + WLST_EXT_CLASSPATH=${WLSDEPLOY_HOME}/lib/weblogic-deploy-core.jar; export WLST_EXT_CLASSPATH + fi + fi + + if [ "${WLST}" = "" ]; then + echo "Unable to determine WLS version in ${ORACLE_HOME} to determine WLST shell script to call" >&2 + exit 98 + fi +fi + +LOG_CONFIG_CLASS=oracle.weblogic.deploy.logging.WLSDeployLoggingConfig +WLST_PROPERTIES=-Dcom.oracle.cie.script.throwException=true +WLST_PROPERTIES="-Djava.util.logging.config.class=${LOG_CONFIG_CLASS} ${WLST_PROPERTIES} ${WLSDEPLOY_PROPERTIES}" +export WLST_PROPERTIES + +if [ "${WLSDEPLOY_LOG_PROPERTIES}" = "" ]; then + WLSDEPLOY_LOG_PROPERTIES=${WLSDEPLOY_HOME}/etc/logging.properties; export WLSDEPLOY_LOG_PROPERTIES +fi + +if [ "${WLSDEPLOY_LOG_DIRECTORY}" = "" ]; then + WLSDEPLOY_LOG_DIRECTORY=${WLSDEPLOY_HOME}/logs; export WLSDEPLOY_LOG_DIRECTORY +fi + +echo "JAVA_HOME = ${JAVA_HOME}" +echo "WLST_EXT_CLASSPATH = ${WLST_EXT_CLASSPATH}" +echo "CLASSPATH = ${CLASSPATH}" +echo "WLST_PROPERTIES = ${WLST_PROPERTIES}" + +PY_SCRIPTS_PATH=${WLSDEPLOY_HOME}/lib/python +echo "${WLST} ${PY_SCRIPTS_PATH}/update.py ${SCRIPT_ARGS}" + +"${WLST}" "${PY_SCRIPTS_PATH}/update.py" ${SCRIPT_ARGS} + +RETURN_CODE=$? +if [ ${RETURN_CODE} -eq 103 ]; then + echo "" + echo "updateDomain.sh completed successfully but the domain requires a restart for the changes to take effect (exit code = ${RETURN_CODE})" +elif [ ${RETURN_CODE} -eq 102 ]; then + echo "" + echo "updateDomain.sh completed successfully but the affected servers require a restart (exit code = ${RETURN_CODE})" +elif [ ${RETURN_CODE} -eq 101 ]; then + echo "" + echo "updateDomain.sh was unable to complete due to configuration changes that require a domain restart. Please restart the domain and re-invoke the updateDomain.sh script with the same arguments (exit code = ${RETURN_CODE})" +elif [ ${RETURN_CODE} -eq 100 ]; then + usage `basename $0` + RETURN_CODE=0 +elif [ ${RETURN_CODE} -eq 99 ]; then + usage `basename $0` + echo "" + echo "updateDomain.sh failed due to the usage error shown above" >&2 +elif [ ${RETURN_CODE} -eq 98 ]; then + echo "" + echo "updateDomain.sh failed due to a parameter validation error" >&2 +elif [ ${RETURN_CODE} -eq 2 ]; then + echo "" + echo "updateDomain.sh failed (exit code = ${RETURN_CODE})" >&2 +elif [ ${RETURN_CODE} -eq 1 ]; then + echo "" + echo "updateDomain.sh completed but with some issues (exit code = ${RETURN_CODE})" >&2 +elif [ ${RETURN_CODE} -eq 0 ]; then + echo "" + echo "updateDomain.sh completed successfully (exit code = ${RETURN_CODE})" +else + # Unexpected return code so just print the message and exit... + echo "" + echo "updateDomain.sh failed (exit code = ${RETURN_CODE})" >&2 +fi +exit ${RETURN_CODE} From b9c9557f605f9d660dc154b112d47786101a08ca Mon Sep 17 00:00:00 2001 From: rkillen Date: Fri, 18 May 2018 16:54:24 -0500 Subject: [PATCH 2/4] Issue#95 - Provide update of security provider elements --- .../python/wlsdeploy/tool/create/creator.py | 12 +- .../wlsdeploy/tool/create/domain_creator.py | 373 +---------------- .../tool/create/security_provider_creator.py | 391 ++++++++++++++++++ .../wlsdeploy/tool/deploy/topology_updater.py | 7 +- .../wlsdeploy/tool/util/topology_helper.py | 6 +- 5 files changed, 418 insertions(+), 371 deletions(-) create mode 100644 core/src/main/python/wlsdeploy/tool/create/security_provider_creator.py diff --git a/core/src/main/python/wlsdeploy/tool/create/creator.py b/core/src/main/python/wlsdeploy/tool/create/creator.py index f82f056044..ac00832110 100644 --- a/core/src/main/python/wlsdeploy/tool/create/creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/creator.py @@ -31,15 +31,17 @@ class Creator(object): """ __class_name = 'Creator' - def __init__(self, model, model_context, aliases): - self.logger = PlatformLogger('wlsdeploy.create') + def __init__(self, model, model_context, aliases, exception_type=ExceptionType.CREATE, + logger=PlatformLogger('wlsdeploy.create')): + + self.logger = logger self.aliases = aliases - self.alias_helper = AliasHelper(self.aliases, self.logger, ExceptionType.CREATE) - self.wlst_helper = WlstHelper(self.logger, ExceptionType.CREATE) + self.alias_helper = AliasHelper(self.aliases, self.logger, exception_type) + self.wlst_helper = WlstHelper(self.logger, exception_type) self.model = Model(model) self.model_context = model_context self.wls_helper = WebLogicHelper(self.logger) - self.attribute_setter = AttributeSetter(self.aliases, self.logger, ExceptionType.CREATE) + self.attribute_setter = AttributeSetter(self.aliases, self.logger, exception_type) # Must be initialized by the subclass since only it has # the knowledge required to compute the domain name. self.archive_helper = None diff --git a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py index fa9614e0f9..860e616c17 100644 --- a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py @@ -3,53 +3,18 @@ The Universal Permissive License (UPL), Version 1.0 """ import javaos as os - from oracle.weblogic.deploy.create import RCURunner from wlsdeploy.aliases.location_context import LocationContext -from wlsdeploy.aliases.wlst_modes import WlstModes -from wlsdeploy.exception import exception_helper -from wlsdeploy.exception.expection_types import ExceptionType -from wlsdeploy.tool.create.creator import Creator -from wlsdeploy.tool.deploy import model_deployer -from wlsdeploy.tool.util.archive_helper import ArchiveHelper -from wlsdeploy.tool.util.topology_helper import TopologyHelper -from wlsdeploy.util import dictionary_utils -from wlsdeploy.util import model as model_helper - -from wlsdeploy.aliases.model_constants import ACTIVE_TYPE -from wlsdeploy.aliases.model_constants import ADJUDICATOR from wlsdeploy.aliases.model_constants import ADMIN_PASSWORD from wlsdeploy.aliases.model_constants import ADMIN_SERVER_NAME from wlsdeploy.aliases.model_constants import ADMIN_USERNAME from wlsdeploy.aliases.model_constants import APP_DIR -from wlsdeploy.aliases.model_constants import AUDITOR -from wlsdeploy.aliases.model_constants import AUTHENTICATION_PROVIDER -from wlsdeploy.aliases.model_constants import AUTHORIZER -from wlsdeploy.aliases.model_constants import CERT_PATH_PROVIDER from wlsdeploy.aliases.model_constants import CLUSTER -from wlsdeploy.aliases.model_constants import CREDENTIAL_MAPPER -from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_TYPE from wlsdeploy.aliases.model_constants import DEFAULT_ADMIN_SERVER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_AUDITOR_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_AUDITOR_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_AUTHENTICATOR_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_AUTHENTICATOR_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_IDENTITY_ASSERTER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_IDENTITY_ASSERTER_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_AUTHORIZER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_AUTHORIZER_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_CERT_PATH_PROVIDER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_CERT_PATH_PROVIDER_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_CREDENTIAL_MAPPER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_CREDENTIAL_MAPPER_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_PASSWORD_VALIDATOR_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_PASSWORD_VALIDATOR_TYPE -from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_NAME -from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_TYPE from wlsdeploy.aliases.model_constants import DEFAULT_WLS_DOMAIN_NAME from wlsdeploy.aliases.model_constants import DOMAIN_LIBRARIES +from wlsdeploy.aliases.model_constants import DOMAIN_NAME from wlsdeploy.aliases.model_constants import DRIVER_NAME from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_PROPERTY_VALUE from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_USER_PROPERTY @@ -57,18 +22,14 @@ from wlsdeploy.aliases.model_constants import JDBC_DRIVER_PARAMS_PROPERTIES from wlsdeploy.aliases.model_constants import JDBC_RESOURCE from wlsdeploy.aliases.model_constants import JDBC_SYSTEM_RESOURCE -from wlsdeploy.aliases.model_constants import DOMAIN_NAME from wlsdeploy.aliases.model_constants import MACHINE from wlsdeploy.aliases.model_constants import MIGRATABLE_TARGET from wlsdeploy.aliases.model_constants import NAME from wlsdeploy.aliases.model_constants import PARTITION from wlsdeploy.aliases.model_constants import PASSWORD from wlsdeploy.aliases.model_constants import PASSWORD_ENCRYPTED -from wlsdeploy.aliases.model_constants import PASSWORD_VALIDATOR -from wlsdeploy.aliases.model_constants import REALM from wlsdeploy.aliases.model_constants import RESOURCE_GROUP from wlsdeploy.aliases.model_constants import RESOURCE_GROUP_TEMPLATE -from wlsdeploy.aliases.model_constants import ROLE_MAPPER from wlsdeploy.aliases.model_constants import SECURITY from wlsdeploy.aliases.model_constants import SECURITY_CONFIGURATION from wlsdeploy.aliases.model_constants import SERVER @@ -83,6 +44,15 @@ from wlsdeploy.aliases.model_constants import URL from wlsdeploy.aliases.model_constants import USER from wlsdeploy.aliases.model_constants import VIRTUAL_TARGET +from wlsdeploy.exception import exception_helper +from wlsdeploy.exception.expection_types import ExceptionType +from wlsdeploy.tool.create.creator import Creator +from wlsdeploy.tool.create.security_provider_creator import SecurityProviderCreator +from wlsdeploy.tool.deploy import model_deployer +from wlsdeploy.tool.util.archive_helper import ArchiveHelper +from wlsdeploy.tool.util.topology_helper import TopologyHelper +from wlsdeploy.util import dictionary_utils +from wlsdeploy.util import model as model_helper class DomainCreator(Creator): @@ -96,7 +66,9 @@ def __init__(self, model_dictionary, model_context, aliases): _method_name = '__init__' Creator.__init__(self, model_dictionary, model_context, aliases) - self.topology_helper = TopologyHelper(WlstModes.OFFLINE, self.aliases, ExceptionType.CREATE, self.logger) + self.topology_helper = TopologyHelper(self.aliases, ExceptionType.CREATE, self.logger) + self.security_provider_creator = SecurityProviderCreator(model_dictionary, model_context, aliases, + ExceptionType.CREATE, self.logger) # domainInfo section is required to get the admin password, everything else # is optional and will use the template defaults @@ -449,7 +421,7 @@ def __apply_base_domain_config(self, topology_folder_list): # SecurityConfiguration is special since the subfolder name does not change when you change the domain name. # It only changes once the domain is written and re-read... security_config_location = LocationContext().add_name_token(domain_name_token, self.__default_domain_name) - self.__create_security_configuration(security_config_location) + self.security_provider_creator.create_security_configuration(security_config_location) topology_folder_list.remove(SECURITY_CONFIGURATION) self.__create_machines(location) @@ -527,68 +499,6 @@ def __create_machines(self, location): self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return - def __create_security_configuration(self, location): - """ - Create the /SecurityConfiguration folder objects, if any. - :param location: the location to use - :raises: CreateException: if an error occurs - """ - _method_name = '__create_security_configuration' - - self.logger.entering(str(location), class_name=self.__class_name, method_name=_method_name) - security_configuration_nodes = dictionary_utils.get_dictionary_element(self._topology, SECURITY_CONFIGURATION) - - self.__handle_default_security_providers(location, security_configuration_nodes) - if len(security_configuration_nodes) > 0: - self._create_mbean(SECURITY_CONFIGURATION, security_configuration_nodes, location, log_created=True) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - - def __handle_default_security_providers(self, base_location, security_configuration_dict): - _method_name = '__handle_default_security_providers' - - self.logger.entering(str(base_location), class_name=self.__class_name, method_name=_method_name) - location = self.__get_default_realm_location() - if security_configuration_dict is None or len(security_configuration_dict) == 0: - if self.__fix_default_authentication_provider_names: - self.__handle_default_authentication_providers(location) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - - if REALM in security_configuration_dict and 'myrealm' in security_configuration_dict[REALM]: - myrealm = security_configuration_dict[REALM]['myrealm'] - if ADJUDICATOR in myrealm: - adj_providers = myrealm[ADJUDICATOR] - self.__handle_default_adjudicators(location, adj_providers) - if AUDITOR in myrealm: - audit_providers = myrealm[AUDITOR] - self.__handle_default_auditors(location, audit_providers) - if AUTHENTICATION_PROVIDER in myrealm: - atn_providers = myrealm[AUTHENTICATION_PROVIDER] - self.__handle_default_authentication_providers(location, atn_providers) - elif self.__fix_default_authentication_provider_names: - self.__handle_default_authentication_providers(location) - if AUTHORIZER in myrealm: - atz_providers = myrealm[AUTHORIZER] - self.__handle_default_authorizers(location, atz_providers) - if CERT_PATH_PROVIDER in myrealm: - cert_path_providers = myrealm[CERT_PATH_PROVIDER] - self.__handle_default_cert_path_providers(location, cert_path_providers) - if CREDENTIAL_MAPPER in myrealm: - credential_mapping_providers = myrealm[CREDENTIAL_MAPPER] - self.__handle_default_credential_mappers(location, credential_mapping_providers) - if PASSWORD_VALIDATOR in myrealm: - password_validation_providers = myrealm[PASSWORD_VALIDATOR] - self.__handle_default_password_validators(location, password_validation_providers) - if ROLE_MAPPER in myrealm: - role_mapping_providers = myrealm[ROLE_MAPPER] - self.__handle_default_role_mappers(location, role_mapping_providers) - elif self.__fix_default_authentication_provider_names: - self.__handle_default_authentication_providers(location) - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - def __create_clusters_and_servers(self, location): """ Create the /Cluster, /ServerTemplate, and /Server folder objects. @@ -915,258 +825,3 @@ def __set_admin_server_name(self): else: self._admin_server_name = self.__default_admin_server_name return - - def __get_default_realm_location(self): - """ - Ensure that the default realm exists and get the location object for it. - :return: the location object to use to work on the default realm while creating a domain. - """ - location = LocationContext().append_location(SECURITY_CONFIGURATION) - # SecurityConfiguration is special since the subfolder name does not change when - # you change the domain name. It only changes once the domain is written and re-read... - token_name = self.alias_helper.get_name_token(location) - if token_name is not None: - location.add_name_token(token_name, self.__default_domain_name) - - wlst_create_path = self.alias_helper.get_wlst_create_path(location) - self.wlst_helper.cd(wlst_create_path) - existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_create_path) - - wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) - wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) - if wlst_type not in existing_folder_names: - self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location, wlst_create_path) - else: - self.wlst_helper.cd(wlst_attribute_path) - - existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_attribute_path) - location.append_location(REALM) - wlst_type = self.alias_helper.get_wlst_mbean_type(location) - token_name = self.alias_helper.get_name_token(location) - - if wlst_type not in existing_folder_names: - self.__default_security_realm_name = self.wls_helper.get_default_security_realm_name() - if token_name is not None: - location.add_name_token(token_name, self.__default_security_realm_name) - wlst_name = self.alias_helper.get_wlst_mbean_name(location) - self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location) - else: - wlst_list_path = self.alias_helper.get_wlst_list_path(location) - existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_list_path) - if len(existing_folder_names) > 0: - self.__default_security_realm_name = existing_folder_names[0] - if token_name is not None: - location.add_name_token(token_name, self.__default_security_realm_name) - wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) - self.wlst_helper.cd(wlst_attribute_path) - return location - - def __handle_default_adjudicators(self, base_location, adj_providers): - if adj_providers is None or len(adj_providers) == 0 or DEFAULT_ADJUDICATOR_NAME is None: - return - - if self.__need_to_delete_default_provider(adj_providers, DEFAULT_ADJUDICATOR_NAME, DEFAULT_ADJUDICATOR_TYPE): - self.__delete_provider(base_location, DEFAULT_ADJUDICATOR_NAME, ADJUDICATOR) - return - - def __handle_default_auditors(self, base_location, audit_providers): - if audit_providers is None or len(audit_providers) == 0 or DEFAULT_AUDITOR_NAME is None: - return - - if self.__need_to_delete_default_provider(audit_providers, DEFAULT_AUDITOR_NAME, DEFAULT_AUDITOR_TYPE): - self.__delete_provider(base_location, DEFAULT_AUDITOR_NAME, AUDITOR) - return - - def __handle_default_authentication_providers(self, base_location, atn_providers=None): - _method_name = '__handle_default_authentication_providers' - - self.logger.entering(str(base_location), class_name=self.__class_name, method_name=_method_name) - if atn_providers is None or len(atn_providers) == 0 or \ - (DEFAULT_AUTHENTICATOR_NAME is None and DEFAULT_IDENTITY_ASSERTER_NAME is None): - if self.__fix_default_authentication_provider_names: - # delete and recreate the default authenticator and default identity asserter with the correct names. - self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_AUTHENTICATOR_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_AUTHENTICATOR_TYPE) - self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_IDENTITY_ASSERTER_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) - self.__set_default_identity_aserter_attributes(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - - atn_names = atn_providers.keys() - if atn_names[0] == DEFAULT_AUTHENTICATOR_NAME: - default_authenticator = atn_providers[DEFAULT_AUTHENTICATOR_NAME] - type_keys = default_authenticator.keys() - if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == DEFAULT_AUTHENTICATOR_TYPE): - delete_default_authenticator = False - else: - delete_default_authenticator = True - else: - delete_default_authenticator = True - - if len(atn_names) > 1 and atn_names[1] == DEFAULT_IDENTITY_ASSERTER_NAME: - default_identity_asserter = atn_providers - type_keys = default_identity_asserter.keys() - if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == DEFAULT_IDENTITY_ASSERTER_TYPE): - delete_default_identity_asserter = False - else: - delete_default_identity_asserter = True - else: - delete_default_identity_asserter = True - - if delete_default_authenticator: - if self.__fix_default_authentication_provider_names: - name = 'Provider' - else: - name = DEFAULT_AUTHENTICATOR_NAME - self.__delete_provider(base_location, name, AUTHENTICATION_PROVIDER) - elif self.__fix_default_authentication_provider_names: - # delete and recreate the default authenticator with the correct name now. - self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_AUTHENTICATOR_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_AUTHENTICATOR_TYPE) - - if delete_default_identity_asserter: - if self.__fix_default_authentication_provider_names: - name = 'Provider' - else: - name = DEFAULT_IDENTITY_ASSERTER_NAME - self.__delete_provider(base_location, name, AUTHENTICATION_PROVIDER) - self.__fix_up_model_default_identity_asserter(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE, - atn_providers) - elif self.__fix_default_authentication_provider_names: - # delete and recreate the default identity asserter with the correct name now. - self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_IDENTITY_ASSERTER_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) - self.__set_default_identity_aserter_attributes(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, - AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - - def __handle_default_authorizers(self, base_location, authorization_providers): - if authorization_providers is None or len(authorization_providers) == 0 or DEFAULT_AUTHORIZER_NAME is None: - return - - if self.__need_to_delete_default_provider(authorization_providers, DEFAULT_AUTHORIZER_NAME, - DEFAULT_AUTHORIZER_TYPE): - self.__delete_provider(base_location, DEFAULT_AUTHORIZER_NAME, AUTHORIZER) - return - - def __handle_default_cert_path_providers(self, base_location, cert_path_providers): - if cert_path_providers is None or len(cert_path_providers) == 0 or DEFAULT_CERT_PATH_PROVIDER_NAME is None: - return - - if self.__need_to_delete_default_provider(cert_path_providers, DEFAULT_CERT_PATH_PROVIDER_NAME, - DEFAULT_CERT_PATH_PROVIDER_TYPE): - self.__delete_provider(base_location, DEFAULT_CERT_PATH_PROVIDER_NAME, CERT_PATH_PROVIDER) - return - - def __handle_default_credential_mappers(self, base_location, credential_mapping_providers): - if credential_mapping_providers is None or len(credential_mapping_providers) == 0 or \ - DEFAULT_CREDENTIAL_MAPPER_NAME is None: - return - - if self.__need_to_delete_default_provider(credential_mapping_providers, DEFAULT_CREDENTIAL_MAPPER_NAME, - DEFAULT_CREDENTIAL_MAPPER_TYPE): - self.__delete_provider(base_location, DEFAULT_CREDENTIAL_MAPPER_NAME, CREDENTIAL_MAPPER) - return - - def __handle_default_password_validators(self, base_location, password_validation_providers): - if password_validation_providers is None or len(password_validation_providers) == 0 or \ - DEFAULT_PASSWORD_VALIDATOR_NAME is None: - return - - if self.__need_to_delete_default_provider(password_validation_providers, DEFAULT_PASSWORD_VALIDATOR_NAME, - DEFAULT_PASSWORD_VALIDATOR_TYPE): - self.__delete_provider(base_location, DEFAULT_PASSWORD_VALIDATOR_NAME, PASSWORD_VALIDATOR) - return - - def __handle_default_role_mappers(self, base_location, role_mapping_providers): - if role_mapping_providers is None or len(role_mapping_providers) == 0 or DEFAULT_ROLE_MAPPER_NAME is None: - return - - if self.__need_to_delete_default_provider(role_mapping_providers, DEFAULT_ROLE_MAPPER_NAME, - DEFAULT_ROLE_MAPPER_TYPE): - self.__delete_provider(base_location, DEFAULT_ROLE_MAPPER_NAME, ROLE_MAPPER) - return - - def __need_to_delete_default_provider(self, providers_dict, default_name, default_type): - provider_names = providers_dict.keys() - if provider_names[0] == default_name: - default_provider = providers_dict[default_name] - type_keys = default_provider.keys() - if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == default_type): - delete_default_provider = False - else: - delete_default_provider = True - else: - delete_default_provider = True - return delete_default_provider - - def __delete_provider(self, base_location, model_name, model_base_type): - location = LocationContext(base_location).append_location(model_base_type) - token_name = self.alias_helper.get_name_token(location) - if token_name is not None: - location.add_name_token(token_name, model_name) - - wlst_create_path = self.alias_helper.get_wlst_create_path(location) - wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) - self.wlst_helper.cd(wlst_create_path) - self.wlst_helper.delete(wlst_name, wlst_type) - return - - def __delete_and_recreate_provider(self, base_location, old_wlst_name, model_name, model_base_type, model_subtype): - self.__delete_provider(base_location, old_wlst_name, model_base_type) - - location = LocationContext(base_location).append_location(model_base_type) - token_name = self.alias_helper.get_name_token(location) - if token_name is not None: - location.add_name_token(token_name, model_name) - - wlst_create_path = self.alias_helper.get_wlst_create_path(location) - wlst_base_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) - location.append_location(model_subtype) - wlst_type = self.alias_helper.get_wlst_mbean_type(location) - self.wlst_helper.cd(wlst_create_path) - self.wlst_helper.create(wlst_name, wlst_type, wlst_base_type) - return - - def __set_default_identity_aserter_attributes(self, base_location, model_name, model_base_type, model_subtype): - location = LocationContext(base_location).append_location(model_base_type) - token_name = self.alias_helper.get_name_token(location) - if token_name is not None: - location.add_name_token(token_name, model_name) - location.append_location(model_subtype) - - wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) - default_value = self.alias_helper.get_model_attribute_default_value(location, ACTIVE_TYPE) - wlst_name = self.alias_helper.get_wlst_attribute_name(location, ACTIVE_TYPE) - self.wlst_helper.cd(wlst_attribute_path) - self.wlst_helper.set(wlst_name, default_value) - return - - # - # Since we are allowing the provider to be recreated, if needed, from the model, - # we need to add the ActiveType attribute to the model if and only if no - # attributes are specified in the model. - # - def __fix_up_model_default_identity_asserter(self, base_location, model_name, model_base_type, - model_subtype, atn_providers): - if atn_providers is not None and DEFAULT_IDENTITY_ASSERTER_NAME in atn_providers: - default_identity_asserter = \ - dictionary_utils.get_dictionary_element(atn_providers, DEFAULT_IDENTITY_ASSERTER_NAME) - if DEFAULT_IDENTITY_ASSERTER_TYPE in default_identity_asserter: - subtype_dict = dictionary_utils.get_dictionary_element(default_identity_asserter, - DEFAULT_IDENTITY_ASSERTER_TYPE) - if len(subtype_dict) == 0: - location = LocationContext(base_location).append_location(model_base_type) - token_name = self.alias_helper.get_name_token(location) - if token_name is not None: - location.add_name_token(token_name, model_name) - location.append_location(model_subtype) - - default_value = self.alias_helper.get_model_attribute_default_value(location, ACTIVE_TYPE) - subtype_dict[ACTIVE_TYPE] = default_value - return diff --git a/core/src/main/python/wlsdeploy/tool/create/security_provider_creator.py b/core/src/main/python/wlsdeploy/tool/create/security_provider_creator.py new file mode 100644 index 0000000000..bc1b9e603a --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/create/security_provider_creator.py @@ -0,0 +1,391 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" + +from wlsdeploy.aliases.location_context import LocationContext +from wlsdeploy.aliases.model_constants import ACTIVE_TYPE +from wlsdeploy.aliases.model_constants import ADJUDICATOR +from wlsdeploy.aliases.model_constants import AUDITOR +from wlsdeploy.aliases.model_constants import AUTHENTICATION_PROVIDER +from wlsdeploy.aliases.model_constants import AUTHORIZER +from wlsdeploy.aliases.model_constants import CERT_PATH_PROVIDER +from wlsdeploy.aliases.model_constants import CREDENTIAL_MAPPER +from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_ADJUDICATOR_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_AUDITOR_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_AUDITOR_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_AUTHENTICATOR_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_AUTHENTICATOR_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_AUTHORIZER_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_AUTHORIZER_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_CERT_PATH_PROVIDER_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_CERT_PATH_PROVIDER_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_CREDENTIAL_MAPPER_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_CREDENTIAL_MAPPER_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_IDENTITY_ASSERTER_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_IDENTITY_ASSERTER_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_PASSWORD_VALIDATOR_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_PASSWORD_VALIDATOR_TYPE +from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_NAME +from wlsdeploy.aliases.model_constants import DEFAULT_ROLE_MAPPER_TYPE +from wlsdeploy.aliases.model_constants import PASSWORD_VALIDATOR +from wlsdeploy.aliases.model_constants import REALM +from wlsdeploy.aliases.model_constants import ROLE_MAPPER +from wlsdeploy.aliases.model_constants import SECURITY_CONFIGURATION +from wlsdeploy.tool.create.creator import Creator +from wlsdeploy.tool.deploy import deployer_utils +from wlsdeploy.tool.util.alias_helper import AliasHelper +from wlsdeploy.tool.util.wlst_helper import WlstHelper +from wlsdeploy.util import dictionary_utils +from wlsdeploy.util.weblogic_helper import WebLogicHelper + + +class SecurityProviderCreator(Creator): + """ + The class that drives security provider creation and updates. + Shared by create domain and update domain. + """ + __class_name = 'SecurityProviderHelper' + + def __init__(self, model_dictionary, model_context, aliases, exception_type, logger): + Creator.__init__(self, model_dictionary, model_context, aliases, exception_type, logger) + + self.logger = logger + self.alias_helper = AliasHelper(aliases, self.logger, exception_type) + self.wlst_helper = WlstHelper(self.logger, exception_type) + self.wls_helper = WebLogicHelper(self.logger) + + self._topology = self.model.get_model_topology() + + # + # Creating domains with the wls.jar template is busted for pre-12.1.2 domains with regards to the + # names of the default authentication providers (both the DefaultAuthenticator and the + # DefaultIdentityAsserter names are 'Provider', making it impossible to work with in WLST. If + # the WLS version is earlier than fix this as part of domain creation... + # + self.__fix_default_authentication_provider_names = \ + self.wls_helper.do_default_authentication_provider_names_need_fixing() + return + + def create_security_configuration(self, location): + """ + Create the /SecurityConfiguration folder objects, if any. + :param location: the location to use + :raises: BundleAwareException of the specified type: if an error occurs + """ + _method_name = '__create_security_configuration' + + self.logger.entering(str(location), class_name=self.__class_name, method_name=_method_name) + security_configuration_nodes = dictionary_utils.get_dictionary_element(self._topology, SECURITY_CONFIGURATION) + + self.__handle_default_security_providers(location, security_configuration_nodes) + if len(security_configuration_nodes) > 0: + self._create_mbean(SECURITY_CONFIGURATION, security_configuration_nodes, location, log_created=True) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + def __handle_default_security_providers(self, base_location, security_configuration_dict): + _method_name = '__handle_default_security_providers' + + self.logger.entering(str(base_location), class_name=self.__class_name, method_name=_method_name) + location = self.__get_default_realm_location() + if security_configuration_dict is None or len(security_configuration_dict) == 0: + if self.__fix_default_authentication_provider_names: + self.__handle_default_authentication_providers(location) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + if REALM in security_configuration_dict and 'myrealm' in security_configuration_dict[REALM]: + myrealm = security_configuration_dict[REALM]['myrealm'] + if ADJUDICATOR in myrealm: + adj_providers = myrealm[ADJUDICATOR] + self.__handle_default_adjudicators(location, adj_providers) + if AUDITOR in myrealm: + audit_providers = myrealm[AUDITOR] + self.__handle_default_auditors(location, audit_providers) + if AUTHENTICATION_PROVIDER in myrealm: + atn_providers = myrealm[AUTHENTICATION_PROVIDER] + self.__handle_default_authentication_providers(location, atn_providers) + elif self.__fix_default_authentication_provider_names: + self.__handle_default_authentication_providers(location) + if AUTHORIZER in myrealm: + atz_providers = myrealm[AUTHORIZER] + self.__handle_default_authorizers(location, atz_providers) + if CERT_PATH_PROVIDER in myrealm: + cert_path_providers = myrealm[CERT_PATH_PROVIDER] + self.__handle_default_cert_path_providers(location, cert_path_providers) + if CREDENTIAL_MAPPER in myrealm: + credential_mapping_providers = myrealm[CREDENTIAL_MAPPER] + self.__handle_default_credential_mappers(location, credential_mapping_providers) + if PASSWORD_VALIDATOR in myrealm: + password_validation_providers = myrealm[PASSWORD_VALIDATOR] + self.__handle_default_password_validators(location, password_validation_providers) + if ROLE_MAPPER in myrealm: + role_mapping_providers = myrealm[ROLE_MAPPER] + self.__handle_default_role_mappers(location, role_mapping_providers) + elif self.__fix_default_authentication_provider_names: + self.__handle_default_authentication_providers(location) + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + def __get_default_realm_location(self): + """ + Ensure that the default realm exists and get the location object for it. + :return: the location object to use to work on the default realm while creating a domain. + """ + location = LocationContext().append_location(SECURITY_CONFIGURATION) + + # SecurityConfiguration is special since the subfolder name does not change when + # you change the domain name. It only changes once the domain is written and re-read... + token_name = self.alias_helper.get_name_token(location) + if token_name is not None: + existing_names = deployer_utils.get_existing_object_list(location, self.alias_helper) + if len(existing_names) > 0: + domain_name = existing_names[0] + location.add_name_token(token_name, domain_name) + + wlst_create_path = self.alias_helper.get_wlst_create_path(location) + self.wlst_helper.cd(wlst_create_path) + existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_create_path) + + wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) + wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) + if wlst_type not in existing_folder_names: + self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location, wlst_create_path) + else: + self.wlst_helper.cd(wlst_attribute_path) + + existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_attribute_path) + location.append_location(REALM) + wlst_type = self.alias_helper.get_wlst_mbean_type(location) + token_name = self.alias_helper.get_name_token(location) + + if wlst_type not in existing_folder_names: + self.__default_security_realm_name = self.wls_helper.get_default_security_realm_name() + if token_name is not None: + location.add_name_token(token_name, self.__default_security_realm_name) + wlst_name = self.alias_helper.get_wlst_mbean_name(location) + self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location) + else: + wlst_list_path = self.alias_helper.get_wlst_list_path(location) + existing_folder_names = self.wlst_helper.get_existing_object_list(wlst_list_path) + if len(existing_folder_names) > 0: + self.__default_security_realm_name = existing_folder_names[0] + if token_name is not None: + location.add_name_token(token_name, self.__default_security_realm_name) + wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) + self.wlst_helper.cd(wlst_attribute_path) + return location + + def __handle_default_adjudicators(self, base_location, adj_providers): + if adj_providers is None or len(adj_providers) == 0 or DEFAULT_ADJUDICATOR_NAME is None: + return + + if self.__need_to_delete_default_provider(adj_providers, DEFAULT_ADJUDICATOR_NAME, DEFAULT_ADJUDICATOR_TYPE): + self.__delete_provider(base_location, DEFAULT_ADJUDICATOR_NAME, ADJUDICATOR) + return + + def __handle_default_auditors(self, base_location, audit_providers): + if audit_providers is None or len(audit_providers) == 0 or DEFAULT_AUDITOR_NAME is None: + return + + if self.__need_to_delete_default_provider(audit_providers, DEFAULT_AUDITOR_NAME, DEFAULT_AUDITOR_TYPE): + self.__delete_provider(base_location, DEFAULT_AUDITOR_NAME, AUDITOR) + return + + def __handle_default_authentication_providers(self, base_location, atn_providers=None): + _method_name = '__handle_default_authentication_providers' + + self.logger.entering(str(base_location), class_name=self.__class_name, method_name=_method_name) + if atn_providers is None or len(atn_providers) == 0 or \ + (DEFAULT_AUTHENTICATOR_NAME is None and DEFAULT_IDENTITY_ASSERTER_NAME is None): + if self.__fix_default_authentication_provider_names: + # delete and recreate the default authenticator and default identity asserter with the correct names. + self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_AUTHENTICATOR_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_AUTHENTICATOR_TYPE) + self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_IDENTITY_ASSERTER_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) + self.__set_default_identity_asserter_attributes(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, + AUTHENTICATION_PROVIDER, + DEFAULT_IDENTITY_ASSERTER_TYPE) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + atn_names = atn_providers.keys() + if atn_names[0] == DEFAULT_AUTHENTICATOR_NAME: + default_authenticator = atn_providers[DEFAULT_AUTHENTICATOR_NAME] + type_keys = default_authenticator.keys() + if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == DEFAULT_AUTHENTICATOR_TYPE): + delete_default_authenticator = False + else: + delete_default_authenticator = True + else: + delete_default_authenticator = True + + if len(atn_names) > 1 and atn_names[1] == DEFAULT_IDENTITY_ASSERTER_NAME: + default_identity_asserter = atn_providers + type_keys = default_identity_asserter.keys() + if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == DEFAULT_IDENTITY_ASSERTER_TYPE): + delete_default_identity_asserter = False + else: + delete_default_identity_asserter = True + else: + delete_default_identity_asserter = True + + if delete_default_authenticator: + if self.__fix_default_authentication_provider_names: + name = 'Provider' + else: + name = DEFAULT_AUTHENTICATOR_NAME + self.__delete_provider(base_location, name, AUTHENTICATION_PROVIDER) + elif self.__fix_default_authentication_provider_names: + # delete and recreate the default authenticator with the correct name now. + self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_AUTHENTICATOR_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_AUTHENTICATOR_TYPE) + + if delete_default_identity_asserter: + if self.__fix_default_authentication_provider_names: + name = 'Provider' + else: + name = DEFAULT_IDENTITY_ASSERTER_NAME + self.__delete_provider(base_location, name, AUTHENTICATION_PROVIDER) + self.__fix_up_model_default_identity_asserter(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE, + atn_providers) + elif self.__fix_default_authentication_provider_names: + # delete and recreate the default identity asserter with the correct name now. + self.__delete_and_recreate_provider(base_location, 'Provider', DEFAULT_IDENTITY_ASSERTER_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) + self.__set_default_identity_asserter_attributes(base_location, DEFAULT_IDENTITY_ASSERTER_NAME, + AUTHENTICATION_PROVIDER, DEFAULT_IDENTITY_ASSERTER_TYPE) + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + def __handle_default_authorizers(self, base_location, authorization_providers): + if authorization_providers is None or len(authorization_providers) == 0 or DEFAULT_AUTHORIZER_NAME is None: + return + + if self.__need_to_delete_default_provider(authorization_providers, DEFAULT_AUTHORIZER_NAME, + DEFAULT_AUTHORIZER_TYPE): + self.__delete_provider(base_location, DEFAULT_AUTHORIZER_NAME, AUTHORIZER) + return + + def __handle_default_cert_path_providers(self, base_location, cert_path_providers): + if cert_path_providers is None or len(cert_path_providers) == 0 or DEFAULT_CERT_PATH_PROVIDER_NAME is None: + return + + if self.__need_to_delete_default_provider(cert_path_providers, DEFAULT_CERT_PATH_PROVIDER_NAME, + DEFAULT_CERT_PATH_PROVIDER_TYPE): + self.__delete_provider(base_location, DEFAULT_CERT_PATH_PROVIDER_NAME, CERT_PATH_PROVIDER) + return + + def __handle_default_credential_mappers(self, base_location, credential_mapping_providers): + if credential_mapping_providers is None or len(credential_mapping_providers) == 0 or \ + DEFAULT_CREDENTIAL_MAPPER_NAME is None: + return + + if self.__need_to_delete_default_provider(credential_mapping_providers, DEFAULT_CREDENTIAL_MAPPER_NAME, + DEFAULT_CREDENTIAL_MAPPER_TYPE): + self.__delete_provider(base_location, DEFAULT_CREDENTIAL_MAPPER_NAME, CREDENTIAL_MAPPER) + return + + def __handle_default_password_validators(self, base_location, password_validation_providers): + if password_validation_providers is None or len(password_validation_providers) == 0 or \ + DEFAULT_PASSWORD_VALIDATOR_NAME is None: + return + + if self.__need_to_delete_default_provider(password_validation_providers, DEFAULT_PASSWORD_VALIDATOR_NAME, + DEFAULT_PASSWORD_VALIDATOR_TYPE): + self.__delete_provider(base_location, DEFAULT_PASSWORD_VALIDATOR_NAME, PASSWORD_VALIDATOR) + return + + def __handle_default_role_mappers(self, base_location, role_mapping_providers): + if role_mapping_providers is None or len(role_mapping_providers) == 0 or DEFAULT_ROLE_MAPPER_NAME is None: + return + + if self.__need_to_delete_default_provider(role_mapping_providers, DEFAULT_ROLE_MAPPER_NAME, + DEFAULT_ROLE_MAPPER_TYPE): + self.__delete_provider(base_location, DEFAULT_ROLE_MAPPER_NAME, ROLE_MAPPER) + return + + def __need_to_delete_default_provider(self, providers_dict, default_name, default_type): + provider_names = providers_dict.keys() + if provider_names[0] == default_name: + default_provider = providers_dict[default_name] + type_keys = default_provider.keys() + if len(type_keys) == 0 or (len(type_keys) == 1 and type_keys[0] == default_type): + delete_default_provider = False + else: + delete_default_provider = True + else: + delete_default_provider = True + return delete_default_provider + + def __delete_provider(self, base_location, model_name, model_base_type): + location = LocationContext(base_location).append_location(model_base_type) + token_name = self.alias_helper.get_name_token(location) + if token_name is not None: + location.add_name_token(token_name, model_name) + + wlst_create_path = self.alias_helper.get_wlst_create_path(location) + wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) + self.wlst_helper.cd(wlst_create_path) + self.wlst_helper.delete(wlst_name, wlst_type) + return + + def __delete_and_recreate_provider(self, base_location, old_wlst_name, model_name, model_base_type, model_subtype): + self.__delete_provider(base_location, old_wlst_name, model_base_type) + + location = LocationContext(base_location).append_location(model_base_type) + token_name = self.alias_helper.get_name_token(location) + if token_name is not None: + location.add_name_token(token_name, model_name) + + wlst_create_path = self.alias_helper.get_wlst_create_path(location) + wlst_base_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name(location) + location.append_location(model_subtype) + wlst_type = self.alias_helper.get_wlst_mbean_type(location) + self.wlst_helper.cd(wlst_create_path) + self.wlst_helper.create(wlst_name, wlst_type, wlst_base_type) + return + + def __set_default_identity_asserter_attributes(self, base_location, model_name, model_base_type, model_subtype): + location = LocationContext(base_location).append_location(model_base_type) + token_name = self.alias_helper.get_name_token(location) + if token_name is not None: + location.add_name_token(token_name, model_name) + location.append_location(model_subtype) + + wlst_attribute_path = self.alias_helper.get_wlst_attributes_path(location) + default_value = self.alias_helper.get_model_attribute_default_value(location, ACTIVE_TYPE) + wlst_name = self.alias_helper.get_wlst_attribute_name(location, ACTIVE_TYPE) + self.wlst_helper.cd(wlst_attribute_path) + self.wlst_helper.set(wlst_name, default_value) + return + + # + # Since we are allowing the provider to be recreated, if needed, from the model, + # we need to add the ActiveType attribute to the model if and only if no + # attributes are specified in the model. + # + def __fix_up_model_default_identity_asserter(self, base_location, model_name, model_base_type, + model_subtype, atn_providers): + if atn_providers is not None and DEFAULT_IDENTITY_ASSERTER_NAME in atn_providers: + default_identity_asserter = \ + dictionary_utils.get_dictionary_element(atn_providers, DEFAULT_IDENTITY_ASSERTER_NAME) + if DEFAULT_IDENTITY_ASSERTER_TYPE in default_identity_asserter: + subtype_dict = dictionary_utils.get_dictionary_element(default_identity_asserter, + DEFAULT_IDENTITY_ASSERTER_TYPE) + if len(subtype_dict) == 0: + location = LocationContext(base_location).append_location(model_base_type) + token_name = self.alias_helper.get_name_token(location) + if token_name is not None: + location.add_name_token(token_name, model_name) + location.append_location(model_subtype) + + default_value = self.alias_helper.get_model_attribute_default_value(location, ACTIVE_TYPE) + subtype_dict[ACTIVE_TYPE] = default_value + return diff --git a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py index 69b6cbd0b1..55205ccf1a 100644 --- a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py +++ b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py @@ -13,6 +13,7 @@ from wlsdeploy.aliases.model_constants import UNIX_MACHINE from wlsdeploy.aliases.wlst_modes import WlstModes from wlsdeploy.exception.expection_types import ExceptionType +from wlsdeploy.tool.create.security_provider_creator import SecurityProviderCreator from wlsdeploy.tool.deploy import deployer_utils from wlsdeploy.tool.deploy.deployer import Deployer from wlsdeploy.tool.util.topology_helper import TopologyHelper @@ -29,7 +30,9 @@ def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE): Deployer.__init__(self, model, model_context, aliases, wlst_mode) self._topology = self.model.get_model_topology() self._resources = self.model.get_model_resources() - self._topology_helper = TopologyHelper(self.wlst_mode, self.aliases, ExceptionType.DEPLOY, self.logger) + self._topology_helper = TopologyHelper(self.aliases, ExceptionType.DEPLOY, self.logger) + self._security_provider_creator = SecurityProviderCreator(model.get_model(), model_context, aliases, + ExceptionType.DEPLOY, self.logger) # Override def _add_named_elements(self, type_name, model_nodes, location): @@ -59,7 +62,7 @@ def update(self): # /Security cannot be updated on existing domain folder_list.remove(SECURITY) - # TODO: process security configuration + self._security_provider_creator.create_security_configuration(location) folder_list.remove(SECURITY_CONFIGURATION) self._process_section(self._topology, folder_list, MACHINE, location) diff --git a/core/src/main/python/wlsdeploy/tool/util/topology_helper.py b/core/src/main/python/wlsdeploy/tool/util/topology_helper.py index 7f9a4f7c1c..937526b95e 100644 --- a/core/src/main/python/wlsdeploy/tool/util/topology_helper.py +++ b/core/src/main/python/wlsdeploy/tool/util/topology_helper.py @@ -13,7 +13,6 @@ from wlsdeploy.aliases.model_constants import SERVER_TEMPLATE from wlsdeploy.tool.util.alias_helper import AliasHelper from wlsdeploy.tool.util.wlst_helper import WlstHelper -from wlsdeploy.util.weblogic_helper import WebLogicHelper class TopologyHelper(object): @@ -22,12 +21,9 @@ class TopologyHelper(object): """ __class_name = 'TopologyHelper' - def __init__(self, wlst_mode, aliases, exception_type, logger): - self.wlst_mode = wlst_mode - self.aliases = aliases + def __init__(self, aliases, exception_type, logger): self.logger = logger self.alias_helper = AliasHelper(aliases, self.logger, exception_type) - self.wls_helper = WebLogicHelper(self.logger) self.wlst_helper = WlstHelper(self.logger, exception_type) self._coherence_cluster_elements = [CLUSTER, SERVER, SERVER_TEMPLATE] From d958add9d6854e15e37a2a41b7d4754826289984 Mon Sep 17 00:00:00 2001 From: rkillen Date: Mon, 21 May 2018 13:26:42 -0500 Subject: [PATCH 3/4] Issue#95 - Provide update of domain and classpath libraries --- .../wlsdeploy/tool/create/domain_creator.py | 67 +++------------- .../wlsdeploy/tool/deploy/topology_updater.py | 9 +++ .../wlsdeploy/tool/util/library_helper.py | 80 +++++++++++++++++++ 3 files changed, 100 insertions(+), 56 deletions(-) create mode 100644 core/src/main/python/wlsdeploy/tool/util/library_helper.py diff --git a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py index 860e616c17..103d7e777a 100644 --- a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py @@ -13,7 +13,6 @@ from wlsdeploy.aliases.model_constants import CLUSTER from wlsdeploy.aliases.model_constants import DEFAULT_ADMIN_SERVER_NAME from wlsdeploy.aliases.model_constants import DEFAULT_WLS_DOMAIN_NAME -from wlsdeploy.aliases.model_constants import DOMAIN_LIBRARIES from wlsdeploy.aliases.model_constants import DOMAIN_NAME from wlsdeploy.aliases.model_constants import DRIVER_NAME from wlsdeploy.aliases.model_constants import DRIVER_PARAMS_PROPERTY_VALUE @@ -50,6 +49,7 @@ from wlsdeploy.tool.create.security_provider_creator import SecurityProviderCreator from wlsdeploy.tool.deploy import model_deployer from wlsdeploy.tool.util.archive_helper import ArchiveHelper +from wlsdeploy.tool.util.library_helper import LibraryHelper from wlsdeploy.tool.util.topology_helper import TopologyHelper from wlsdeploy.util import dictionary_utils from wlsdeploy.util import model as model_helper @@ -66,10 +66,6 @@ def __init__(self, model_dictionary, model_context, aliases): _method_name = '__init__' Creator.__init__(self, model_dictionary, model_context, aliases) - self.topology_helper = TopologyHelper(self.aliases, ExceptionType.CREATE, self.logger) - self.security_provider_creator = SecurityProviderCreator(model_dictionary, model_context, aliases, - ExceptionType.CREATE, self.logger) - # domainInfo section is required to get the admin password, everything else # is optional and will use the template defaults if model_helper.get_model_domain_info_key() not in model_dictionary: @@ -79,6 +75,10 @@ def __init__(self, model_dictionary, model_context, aliases): self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex + self.topology_helper = TopologyHelper(self.aliases, ExceptionType.CREATE, self.logger) + self.security_provider_creator = SecurityProviderCreator(model_dictionary, model_context, aliases, + ExceptionType.CREATE, self.logger) + self._domain_typedef = self.model_context.get_domain_typedef() self._topology = self.model.get_model_topology() self._domain_info = self.model.get_model_domain_info() @@ -102,6 +102,10 @@ def __init__(self, model_dictionary, model_context, aliases): if archive_file_name is not None: self.archive_helper = ArchiveHelper(archive_file_name, self._domain_home, self.logger, exception_helper.ExceptionType.CREATE) + + self.library_helper = LibraryHelper(self.model, self.model_context, self.aliases, self._domain_home, + ExceptionType.CREATE, self.logger) + # # Creating domains with the wls.jar template is busted for pre-12.1.2 domains with regards to the # names of the default authentication providers (both the DefaultAuthenticator and the @@ -227,8 +231,8 @@ def __create_domain(self): for file_to_extract in self.files_to_extract_from_archive: self.archive_helper.extract_file(file_to_extract) - self.__install_domain_libraries(self._domain_home) - self.__extract_classpath_libraries(self._domain_home) + self.library_helper.install_domain_libraries() + self.library_helper.extract_classpath_libraries() self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return @@ -350,55 +354,6 @@ def __create_domain_with_select_template(self, domain_home): self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return - def __install_domain_libraries(self, domain_home): - """ - Extract the domain libraries listed in the model, if any, to the /lib directory. - :param domain_home: the domain home directory - :raises: CreateException: if an error occurs - """ - _method_name = '__install_domain_libraries' - - self.logger.entering(domain_home, class_name=self.__class_name, method_name=_method_name) - domain_info_dict = self.model.get_model_domain_info() - if DOMAIN_LIBRARIES not in domain_info_dict or len(domain_info_dict[DOMAIN_LIBRARIES]) == 0: - self.logger.info('WLSDPLY-12213', class_name=self.__class_name, method_name=_method_name) - else: - domain_libs = dictionary_utils.get_dictionary_element(domain_info_dict, DOMAIN_LIBRARIES) - if self.archive_helper is None: - ex = exception_helper.create_create_exception('WLSDPLY-12214', domain_libs) - self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) - raise ex - - for domain_lib in domain_libs: - self.logger.info('WLSDPLY-12215', domain_lib, domain_home, - class_name=self.__class_name, method_name=_method_name) - self.archive_helper.extract_domain_library(domain_lib) - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - - def __extract_classpath_libraries(self, domain_home): - """ - Extract any classpath libraries in the archive to the domain home. - :param domain_home: the domain home directory - :raises: CreateException: if an error occurs - """ - _method_name = '__extract_classpath_libraries' - - self.logger.entering(domain_home, class_name=self.__class_name, method_name=_method_name) - if self.archive_helper is None: - self.logger.info('WLSDPLY-12216', class_name=self.__class_name, method_name=_method_name) - else: - num_cp_libs = self.archive_helper.extract_classpath_libraries() - if num_cp_libs > 0: - self.logger.info('WLSDPLY-12217', num_cp_libs, domain_home, - class_name=self.__class_name, method_name=_method_name) - else: - self.logger.info('WLSDPLY-12218', self.model_context.get_archive_file_name(), - class_name=self.__class_name, method_name=_method_name) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - def __apply_base_domain_config(self, topology_folder_list): """ Apply the base domain configuration from the model topology section. diff --git a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py index 55205ccf1a..71a5b16e23 100644 --- a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py +++ b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py @@ -16,6 +16,7 @@ from wlsdeploy.tool.create.security_provider_creator import SecurityProviderCreator from wlsdeploy.tool.deploy import deployer_utils from wlsdeploy.tool.deploy.deployer import Deployer +from wlsdeploy.tool.util.library_helper import LibraryHelper from wlsdeploy.tool.util.topology_helper import TopologyHelper from wlsdeploy.util import dictionary_utils @@ -34,6 +35,9 @@ def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE): self._security_provider_creator = SecurityProviderCreator(model.get_model(), model_context, aliases, ExceptionType.DEPLOY, self.logger) + self.library_helper = LibraryHelper(self.model, self.model_context, self.aliases, + model_context.get_domain_home(), ExceptionType.DEPLOY, self.logger) + # Override def _add_named_elements(self, type_name, model_nodes, location): """ @@ -84,6 +88,11 @@ def update(self): # TODO: update targeting + # files referenced in attributes are extracted as attributes are processed + + self.library_helper.install_domain_libraries() + self.library_helper.extract_classpath_libraries() + def _process_section(self, folder_dict, folder_list, key, location): if key in folder_dict: nodes = dictionary_utils.get_dictionary_element(folder_dict, key) diff --git a/core/src/main/python/wlsdeploy/tool/util/library_helper.py b/core/src/main/python/wlsdeploy/tool/util/library_helper.py new file mode 100644 index 0000000000..ed17c68ef5 --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/util/library_helper.py @@ -0,0 +1,80 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" + +import wlsdeploy.util.dictionary_utils as dictionary_utils + +from wlsdeploy.aliases.model_constants import DOMAIN_LIBRARIES +from wlsdeploy.exception import exception_helper +from wlsdeploy.tool.util.alias_helper import AliasHelper +from wlsdeploy.tool.util.archive_helper import ArchiveHelper +from wlsdeploy.tool.util.wlst_helper import WlstHelper + + +class LibraryHelper(object): + """ + Shared code for updating domain and classpath libraries. Domain create and update use this code. + """ + __class_name = 'LibraryHelper' + + def __init__(self, model, model_context, aliases, domain_home, exception_type, logger): + self.logger = logger + self.model = model + self.model_context = model_context + self.domain_home = domain_home + self.alias_helper = AliasHelper(aliases, self.logger, exception_type) + self.wlst_helper = WlstHelper(self.logger, exception_type) + + archive_file_name = self.model_context.get_archive_file_name() + if archive_file_name is not None: + self.archive_helper = ArchiveHelper(archive_file_name, self.domain_home, self.logger, exception_type) + + def install_domain_libraries(self): + """ + Extract the domain libraries listed in the model, if any, to the /lib directory. + :raises: BundleAwareException of the specified type: if an error occurs + """ + _method_name = 'install_domain_libraries' + print('\n' + _method_name) + + self.logger.entering(self.domain_home, class_name=self.__class_name, method_name=_method_name) + domain_info_dict = self.model.get_model_domain_info() + if DOMAIN_LIBRARIES not in domain_info_dict or len(domain_info_dict[DOMAIN_LIBRARIES]) == 0: + self.logger.info('WLSDPLY-12213', class_name=self.__class_name, method_name=_method_name) + else: + domain_libs = dictionary_utils.get_dictionary_element(domain_info_dict, DOMAIN_LIBRARIES) + if self.archive_helper is None: + ex = exception_helper.create_create_exception('WLSDPLY-12214', domain_libs) + self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) + raise ex + + for domain_lib in domain_libs: + self.logger.info('WLSDPLY-12215', domain_lib, self.domain_home, + class_name=self.__class_name, method_name=_method_name) + self.archive_helper.extract_domain_library(domain_lib) + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + def extract_classpath_libraries(self): + """ + Extract any classpath libraries in the archive to the domain home. + :raises: BundleAwareException of the specified type: if an error occurs + """ + _method_name = 'extract_classpath_libraries' + print('\n' + _method_name) + + self.logger.entering(self.domain_home, class_name=self.__class_name, method_name=_method_name) + if self.archive_helper is None: + self.logger.info('WLSDPLY-12216', class_name=self.__class_name, method_name=_method_name) + else: + num_cp_libs = self.archive_helper.extract_classpath_libraries() + if num_cp_libs > 0: + self.logger.info('WLSDPLY-12217', num_cp_libs, self.domain_home, + class_name=self.__class_name, method_name=_method_name) + else: + self.logger.info('WLSDPLY-12218', self.model_context.get_archive_file_name(), + class_name=self.__class_name, method_name=_method_name) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return From 4dfd77658266eb86dec6ae1bdf3026e2364a31b0 Mon Sep 17 00:00:00 2001 From: rkillen Date: Tue, 22 May 2018 15:17:46 -0500 Subject: [PATCH 4/4] Issue#95 - Provide update of server group targeting --- core/src/main/python/update.py | 12 +- .../python/wlsdeploy/tool/create/creator.py | 144 ----------- .../wlsdeploy/tool/create/domain_creator.py | 70 +----- .../wlsdeploy/tool/deploy/topology_updater.py | 9 +- .../wlsdeploy/tool/util/library_helper.py | 2 - .../wlsdeploy/tool/util/target_helper.py | 238 ++++++++++++++++++ 6 files changed, 263 insertions(+), 212 deletions(-) create mode 100644 core/src/main/python/wlsdeploy/tool/util/target_helper.py diff --git a/core/src/main/python/update.py b/core/src/main/python/update.py index 519e562e9c..1bf036caeb 100644 --- a/core/src/main/python/update.py +++ b/core/src/main/python/update.py @@ -32,12 +32,14 @@ from wlsdeploy.exception import exception_helper from wlsdeploy.exception.expection_types import ExceptionType from wlsdeploy.logging.platform_logger import PlatformLogger +from wlsdeploy.tool.create.domain_typedef import DomainTypedef from wlsdeploy.tool.deploy import deployer_utils from wlsdeploy.tool.deploy import model_deployer from wlsdeploy.tool.deploy.topology_updater import TopologyUpdater from wlsdeploy.tool.validate.validator import Validator from wlsdeploy.tool.util import filter_helper from wlsdeploy.tool.util.wlst_helper import WlstHelper +from wlsdeploy.util import dictionary_utils from wlsdeploy.util import getcreds from wlsdeploy.util import variables from wlsdeploy.util.cla_utils import CommandLineArgUtil @@ -91,10 +93,18 @@ def __process_args(args): __wlst_mode = __process_online_args(optional_arg_map) __process_encryption_args(optional_arg_map) + domain_type = dictionary_utils.get_element(optional_arg_map, CommandLineArgUtil.DOMAIN_TYPE_SWITCH) + if domain_type is None: + domain_type = 'WLS' + domain_typedef = DomainTypedef(_program_name, domain_type) + optional_arg_map[CommandLineArgUtil.DOMAIN_TYPEDEF] = domain_typedef + combined_arg_map = optional_arg_map.copy() combined_arg_map.update(required_arg_map) - return ModelContext(_program_name, combined_arg_map) + model_context = ModelContext(_program_name, combined_arg_map) + domain_typedef.set_model_context(model_context) + return model_context def __verify_required_args_present(required_arg_map): diff --git a/core/src/main/python/wlsdeploy/tool/create/creator.py b/core/src/main/python/wlsdeploy/tool/create/creator.py index ac00832110..a90163d569 100644 --- a/core/src/main/python/wlsdeploy/tool/create/creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/creator.py @@ -2,9 +2,7 @@ Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. The Universal Permissive License (UPL), Version 1.0 """ -import copy -from oracle.weblogic.deploy.util import PyOrderedDict as OrderedDict from oracle.weblogic.deploy.util import WLSDeployArchive from wlsdeploy.aliases.location_context import LocationContext @@ -17,13 +15,8 @@ from wlsdeploy.tool.util.wlst_helper import WlstHelper from wlsdeploy.util import dictionary_utils from wlsdeploy.util.model import Model -from wlsdeploy.util import string_utils from wlsdeploy.util.weblogic_helper import WebLogicHelper -from wlsdeploy.aliases.model_constants import CLUSTER -from wlsdeploy.aliases.model_constants import MODEL_LIST_DELIMITER -from wlsdeploy.aliases.model_constants import SERVER - class Creator(object): """ @@ -389,7 +382,6 @@ def _create_subfolders(self, location, model_nodes): self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return - def _is_type_valid(self, location, type_name): """ Verify that the specified location in valid for the current WLS version. @@ -447,139 +439,3 @@ def _format_model_path(self, location, name): path += '/' path += name return path - - def _get_existing_server_names(self): - """ - Get the list of server names from WLST. - :return: the list of server names - :raises: CreateException: is an error occurs reading from the aliases or WLST - """ - _method_name = '_get_existing_server_names' - - self.logger.entering(class_name=self.__class_name, method_name=_method_name) - server_location = LocationContext().append_location(SERVER) - server_list_path = self.alias_helper.get_wlst_list_path(server_location) - result = self.wlst_helper.get_existing_object_list(server_list_path) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) - return result - - def _get_clusters_and_members_map(self): - """ - Get a map keyed by cluster name with values that are a list of member server names - :return: the cluster name to member server names map - :raises: CreateException: is an error occurs reading from the aliases or WLST - """ - _method_name = '_get_clusters_and_members_map' - - self.logger.entering(class_name=self.__class_name, method_name=_method_name) - server_location = LocationContext().append_location(SERVER) - server_list_path = self.alias_helper.get_wlst_list_path(server_location) - server_names = self.wlst_helper.get_existing_object_list(server_list_path) - server_token = self.alias_helper.get_name_token(server_location) - cluster_map = OrderedDict() - for server_name in server_names: - server_location.add_name_token(server_token, server_name) - server_attributes_path = self.alias_helper.get_wlst_attributes_path(server_location) - self.wlst_helper.cd(server_attributes_path) - - server_attributes_map = self.wlst_helper.lsa() - cluster_name = dictionary_utils.get_element(server_attributes_map, CLUSTER) - if string_utils.is_empty(cluster_name): - # if server is not part of a cluster, continue with the next server - continue - - if cluster_name not in cluster_map: - cluster_map[cluster_name] = list() - cluster_map[cluster_name].append(server_name) - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=cluster_map) - return cluster_map - - def _get_server_group_targeting_limits(self, server_group_targeting_limits, clusters_map): - """ - Get any server group targeting limits specified in the model, converting any cluster - names to the list of members. This method assumes that the limits dictionary is not - None or empty. - :param server_group_targeting_limits: the raw server group targeting_limits from the model - :param clusters_map: the map of cluster names to member server names - :return: the map of server groups to server names to target - """ - _method_name = '_get_server_group_targeting_limits' - - self.logger.entering(str(server_group_targeting_limits), str(clusters_map), - class_name=self.__class_name, method_name=_method_name) - sg_targeting_limits = copy.deepcopy(server_group_targeting_limits) - for server_group_name, sg_targeting_limit in sg_targeting_limits.iteritems(): - if type(sg_targeting_limit) is str: - if MODEL_LIST_DELIMITER in sg_targeting_limit: - sg_targeting_limit = sg_targeting_limit.split(MODEL_LIST_DELIMITER) - else: - # convert a single value into a list of one... - new_list = list() - new_list.append(sg_targeting_limit) - sg_targeting_limit = new_list - - # Convert any references to a cluster name into the list of member server names - new_list = list() - for target_name in sg_targeting_limit: - target_name = target_name.strip() - if target_name in clusters_map: - cluster_members = dictionary_utils.get_element(clusters_map, target_name) - new_list.extend(cluster_members) - else: - # Assume it is a server name and add it to the new list - new_list.append(target_name) - sg_targeting_limits[server_group_name] = new_list - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=sg_targeting_limits) - return sg_targeting_limits - - def _get_server_to_server_groups_map(self, admin_server_name, server_names, server_groups, sg_targeting_limits): - """ - Get the map of server names to the list of server groups to target to that server. - :param admin_server_name: the admin server name - :param server_names: the list of server names - :param server_groups: the complete list of server groups that will, by default, be targeted to - all managed servers unless the server is listed in the targeting limits map - :param sg_targeting_limits: the targeting limits map - :return: the map of server names to the list of server groups to target to that server - """ - _method_name = '_get_server_to_server_groups_map' - - self.logger.entering(admin_server_name, str(server_names), str(server_groups), str(sg_targeting_limits), - class_name=self.__class_name, method_name=_method_name) - result = OrderedDict() - for server_name in server_names: - server_groups_for_server = self.__get_server_groups_for_server(server_name, sg_targeting_limits) - if server_groups_for_server is not None: - result[server_name] = server_groups_for_server - elif server_name != admin_server_name: - # By default, we only target managed servers unless explicitly listed in the targeting limits - result[server_name] = list(server_groups) - else: - result[admin_server_name] = list() - if admin_server_name not in result: - result[admin_server_name] = list() - self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) - return result - - def __get_server_groups_for_server(self, server_name, sg_targeting_limits): - """ - Get the servers groups to target for a given server name. - :param server_name: the server name - :param sg_targeting_limits: the targeting limits - :return: the list of server groups to target to the specified server name, or None - if the server name does not appear in the targeting limits - """ - _method_name = '__get_server_groups_for_server' - - self.logger.entering(server_name, str(sg_targeting_limits), - class_name=self.__class_name, method_name=_method_name) - result = None - for server_group, server_names_list in sg_targeting_limits.iteritems(): - if server_name in server_names_list: - if result is None: - result = list() - result.append(server_group) - self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) - return result diff --git a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py index 103d7e777a..1c4fdef6c2 100644 --- a/core/src/main/python/wlsdeploy/tool/create/domain_creator.py +++ b/core/src/main/python/wlsdeploy/tool/create/domain_creator.py @@ -32,7 +32,6 @@ from wlsdeploy.aliases.model_constants import SECURITY from wlsdeploy.aliases.model_constants import SECURITY_CONFIGURATION from wlsdeploy.aliases.model_constants import SERVER -from wlsdeploy.aliases.model_constants import SERVER_GROUP_TARGETING_LIMITS from wlsdeploy.aliases.model_constants import SERVER_START_MODE from wlsdeploy.aliases.model_constants import SERVER_TEMPLATE from wlsdeploy.aliases.model_constants import SET_OPTION_APP_DIR @@ -50,6 +49,7 @@ from wlsdeploy.tool.deploy import model_deployer from wlsdeploy.tool.util.archive_helper import ArchiveHelper from wlsdeploy.tool.util.library_helper import LibraryHelper +from wlsdeploy.tool.util.target_helper import TargetHelper from wlsdeploy.tool.util.topology_helper import TopologyHelper from wlsdeploy.util import dictionary_utils from wlsdeploy.util import model as model_helper @@ -106,6 +106,9 @@ def __init__(self, model_dictionary, model_context, aliases): self.library_helper = LibraryHelper(self.model, self.model_context, self.aliases, self._domain_home, ExceptionType.CREATE, self.logger) + self.target_helper = TargetHelper(self.model, self.model_context, self.aliases, ExceptionType.CREATE, + self.logger) + # # Creating domains with the wls.jar template is busted for pre-12.1.2 domains with regards to the # names of the default authentication providers (both the DefaultAuthenticator and the @@ -303,7 +306,7 @@ def __extend_domain(self, domain_home): self.__configure_fmw_infra_database() server_groups_to_target = self._domain_typedef.get_server_groups_to_target() - self.__target_server_groups_to_servers(server_groups_to_target) + self.target_helper.target_server_groups_to_servers(server_groups_to_target) self.logger.info('WLSDPLY-12209', self._domain_name, class_name=self.__class_name, method_name=_method_name) @@ -345,7 +348,7 @@ def __create_domain_with_select_template(self, domain_home): self.__configure_fmw_infra_database() server_groups_to_target = self._domain_typedef.get_server_groups_to_target() - self.__target_server_groups_to_servers(server_groups_to_target) + self.target_helper.target_server_groups_to_servers(server_groups_to_target) self.logger.info('WLSDPLY-12206', self._domain_name, domain_home, class_name=self.__class_name, method_name=_method_name) @@ -611,67 +614,6 @@ def __configure_fmw_infra_database(self): self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return - def __target_server_groups_to_servers(self, server_groups_to_target): - """ - Target the server groups to the servers. - :param server_groups_to_target: the list of server groups to target - :raises: CreateException: if an error occurs - """ - _method_name = '__target_server_groups_to_servers' - - self.logger.entering(server_groups_to_target, class_name=self.__class_name, method_name=_method_name) - if len(server_groups_to_target) == 0: - return - - location = LocationContext() - root_path = self.alias_helper.get_wlst_attributes_path(location) - self.wlst_helper.cd(root_path) - - # We need to get the effective list of servers for the domain. Since any servers - # referenced in the model have already been created but the templates may have - # defined new servers not listed in the model, get the list from WLST. - server_names = self._get_existing_server_names() - - # Get the clusters and and their members - cluster_map = self._get_clusters_and_members_map() - - # Get any limits that may have been defined in the model - domain_info = self.model.get_model_domain_info() - server_group_targeting_limits = \ - dictionary_utils.get_dictionary_element(domain_info, SERVER_GROUP_TARGETING_LIMITS) - if len(server_group_targeting_limits) > 0: - server_group_targeting_limits = \ - self._get_server_group_targeting_limits(server_group_targeting_limits, cluster_map) - - # Get the map of server names to server groups to target - server_to_server_groups_map = self._get_server_to_server_groups_map(self._admin_server_name, - server_names, - server_groups_to_target, - server_group_targeting_limits) - if len(server_names) > 1: - for server, server_groups in server_to_server_groups_map.iteritems(): - if len(server_groups) > 0: - server_name = self.wlst_helper.get_quoted_name_for_wlst(server) - self.logger.info('WLSDPLY-12224', str(server_groups), server_name, - class_name=self.__class_name, method_name=_method_name) - self.wlst_helper.set_server_groups(server_name, server_groups) - - elif len(server_group_targeting_limits) == 0: - # - # Domain has no managed servers and there were not targeting limits specified to target - # server groups to the admin server so make sure that the server groups are targeted to - # the admin server. - # - # This is really a best effort attempt. It works for JRF domains but it is certainly possible - # that it may cause problems with other custom domain types. Of course, creating a domain with - # no managed servers is not a primary use case of this tool so do it and hope for the best... - # - server_name = self.wlst_helper.get_quoted_name_for_wlst(server_names[0]) - self.wlst_helper.set_server_groups(server_name, server_groups_to_target) - - self.logger.exiting(class_name=self.__class_name, method_name=_method_name) - return - def __set_app_dir(self): """ Set the AppDir domain option. diff --git a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py index 71a5b16e23..fb041eafa3 100644 --- a/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py +++ b/core/src/main/python/wlsdeploy/tool/deploy/topology_updater.py @@ -17,6 +17,7 @@ from wlsdeploy.tool.deploy import deployer_utils from wlsdeploy.tool.deploy.deployer import Deployer from wlsdeploy.tool.util.library_helper import LibraryHelper +from wlsdeploy.tool.util.target_helper import TargetHelper from wlsdeploy.tool.util.topology_helper import TopologyHelper from wlsdeploy.util import dictionary_utils @@ -32,12 +33,17 @@ def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE): self._topology = self.model.get_model_topology() self._resources = self.model.get_model_resources() self._topology_helper = TopologyHelper(self.aliases, ExceptionType.DEPLOY, self.logger) + self._domain_typedef = self.model_context.get_domain_typedef() + self._security_provider_creator = SecurityProviderCreator(model.get_model(), model_context, aliases, ExceptionType.DEPLOY, self.logger) self.library_helper = LibraryHelper(self.model, self.model_context, self.aliases, model_context.get_domain_home(), ExceptionType.DEPLOY, self.logger) + self.target_helper = TargetHelper(self.model, self.model_context, self.aliases, ExceptionType.DEPLOY, + self.logger) + # Override def _add_named_elements(self, type_name, model_nodes, location): """ @@ -86,7 +92,8 @@ def update(self): for folder_name in remaining: self._process_section(self._topology, folder_list, folder_name, location) - # TODO: update targeting + server_groups_to_target = self._domain_typedef.get_server_groups_to_target() + self.target_helper.target_server_groups_to_servers(server_groups_to_target) # files referenced in attributes are extracted as attributes are processed diff --git a/core/src/main/python/wlsdeploy/tool/util/library_helper.py b/core/src/main/python/wlsdeploy/tool/util/library_helper.py index ed17c68ef5..8427147357 100644 --- a/core/src/main/python/wlsdeploy/tool/util/library_helper.py +++ b/core/src/main/python/wlsdeploy/tool/util/library_helper.py @@ -36,7 +36,6 @@ def install_domain_libraries(self): :raises: BundleAwareException of the specified type: if an error occurs """ _method_name = 'install_domain_libraries' - print('\n' + _method_name) self.logger.entering(self.domain_home, class_name=self.__class_name, method_name=_method_name) domain_info_dict = self.model.get_model_domain_info() @@ -63,7 +62,6 @@ def extract_classpath_libraries(self): :raises: BundleAwareException of the specified type: if an error occurs """ _method_name = 'extract_classpath_libraries' - print('\n' + _method_name) self.logger.entering(self.domain_home, class_name=self.__class_name, method_name=_method_name) if self.archive_helper is None: diff --git a/core/src/main/python/wlsdeploy/tool/util/target_helper.py b/core/src/main/python/wlsdeploy/tool/util/target_helper.py new file mode 100644 index 0000000000..d579105d20 --- /dev/null +++ b/core/src/main/python/wlsdeploy/tool/util/target_helper.py @@ -0,0 +1,238 @@ +""" +Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. +The Universal Permissive License (UPL), Version 1.0 +""" + +import copy +import oracle.weblogic.deploy.util.PyOrderedDict as OrderedDict +import wlsdeploy.util.dictionary_utils as dictionary_utils +from wlsdeploy.aliases.location_context import LocationContext + +from wlsdeploy.aliases.model_constants import ADMIN_SERVER_NAME +from wlsdeploy.aliases.model_constants import CLUSTER +from wlsdeploy.aliases.model_constants import DEFAULT_ADMIN_SERVER_NAME +from wlsdeploy.aliases.model_constants import MODEL_LIST_DELIMITER +from wlsdeploy.aliases.model_constants import SERVER +from wlsdeploy.aliases.model_constants import SERVER_GROUP_TARGETING_LIMITS +from wlsdeploy.tool.util.alias_helper import AliasHelper +from wlsdeploy.tool.util.wlst_helper import WlstHelper +from wlsdeploy.util import string_utils + + +class TargetHelper(object): + """ + Shared code for targeting clusters and servers. Domain create and update use this code. + """ + __class_name = 'TargetHelper' + + def __init__(self, model, model_context, aliases, exception_type, logger): + self.logger = logger + self.model = model + self.model_context = model_context + self.alias_helper = AliasHelper(aliases, self.logger, exception_type) + self.wlst_helper = WlstHelper(self.logger, exception_type) + + topology = model.get_model_topology() + if ADMIN_SERVER_NAME in topology: + self._admin_server_name = topology[ADMIN_SERVER_NAME] + else: + self._admin_server_name = DEFAULT_ADMIN_SERVER_NAME + + def target_server_groups_to_servers(self, server_groups_to_target): + """ + Target the server groups to the servers. + :param server_groups_to_target: the list of server groups to target + :raises: BundleAwareException of the specified type: if an error occurs + """ + _method_name = '__target_server_groups_to_servers' + + self.logger.entering(server_groups_to_target, class_name=self.__class_name, method_name=_method_name) + if len(server_groups_to_target) == 0: + return + + location = LocationContext() + root_path = self.alias_helper.get_wlst_attributes_path(location) + self.wlst_helper.cd(root_path) + + # We need to get the effective list of servers for the domain. Since any servers + # referenced in the model have already been created but the templates may have + # defined new servers not listed in the model, get the list from WLST. + server_names = self._get_existing_server_names() + + # Get the clusters and and their members + cluster_map = self._get_clusters_and_members_map() + + # Get any limits that may have been defined in the model + domain_info = self.model.get_model_domain_info() + server_group_targeting_limits = \ + dictionary_utils.get_dictionary_element(domain_info, SERVER_GROUP_TARGETING_LIMITS) + if len(server_group_targeting_limits) > 0: + server_group_targeting_limits = \ + self._get_server_group_targeting_limits(server_group_targeting_limits, cluster_map) + + # Get the map of server names to server groups to target + server_to_server_groups_map =\ + self._get_server_to_server_groups_map(self._admin_server_name, + server_names, + server_groups_to_target, + server_group_targeting_limits) # type: dict + + if len(server_names) > 1: + for server, server_groups in server_to_server_groups_map.iteritems(): + if len(server_groups) > 0: + server_name = self.wlst_helper.get_quoted_name_for_wlst(server) + self.logger.info('WLSDPLY-12224', str(server_groups), server_name, + class_name=self.__class_name, method_name=_method_name) + self.wlst_helper.set_server_groups(server_name, server_groups) + + elif len(server_group_targeting_limits) == 0: + # + # Domain has no managed servers and there were not targeting limits specified to target + # server groups to the admin server so make sure that the server groups are targeted to + # the admin server. + # + # This is really a best effort attempt. It works for JRF domains but it is certainly possible + # that it may cause problems with other custom domain types. Of course, creating a domain with + # no managed servers is not a primary use case of this tool so do it and hope for the best... + # + server_name = self.wlst_helper.get_quoted_name_for_wlst(server_names[0]) + self.wlst_helper.set_server_groups(server_name, server_groups_to_target) + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name) + return + + def _get_existing_server_names(self): + """ + Get the list of server names from WLST. + :return: the list of server names + :raises: BundleAwareException of the specified type: is an error occurs reading from the aliases or WLST + """ + _method_name = '_get_existing_server_names' + + self.logger.entering(class_name=self.__class_name, method_name=_method_name) + server_location = LocationContext().append_location(SERVER) + server_list_path = self.alias_helper.get_wlst_list_path(server_location) + result = self.wlst_helper.get_existing_object_list(server_list_path) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) + return result + + def _get_clusters_and_members_map(self): + """ + Get a map keyed by cluster name with values that are a list of member server names + :return: the cluster name to member server names map + :raises: BundleAwareException of the specified type: is an error occurs reading from the aliases or WLST + """ + _method_name = '_get_clusters_and_members_map' + + self.logger.entering(class_name=self.__class_name, method_name=_method_name) + server_location = LocationContext().append_location(SERVER) + server_list_path = self.alias_helper.get_wlst_list_path(server_location) + server_names = self.wlst_helper.get_existing_object_list(server_list_path) + server_token = self.alias_helper.get_name_token(server_location) + cluster_map = OrderedDict() + for server_name in server_names: + server_location.add_name_token(server_token, server_name) + server_attributes_path = self.alias_helper.get_wlst_attributes_path(server_location) + self.wlst_helper.cd(server_attributes_path) + + server_attributes_map = self.wlst_helper.lsa() + cluster_name = dictionary_utils.get_element(server_attributes_map, CLUSTER) + if string_utils.is_empty(cluster_name): + # if server is not part of a cluster, continue with the next server + continue + + if cluster_name not in cluster_map: + cluster_map[cluster_name] = list() + cluster_map[cluster_name].append(server_name) + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=cluster_map) + return cluster_map + + def _get_server_group_targeting_limits(self, server_group_targeting_limits, clusters_map): + """ + Get any server group targeting limits specified in the model, converting any cluster + names to the list of members. This method assumes that the limits dictionary is not + None or empty. + :param server_group_targeting_limits: the raw server group targeting_limits from the model + :param clusters_map: the map of cluster names to member server names + :return: the map of server groups to server names to target + """ + _method_name = '_get_server_group_targeting_limits' + + self.logger.entering(str(server_group_targeting_limits), str(clusters_map), + class_name=self.__class_name, method_name=_method_name) + sg_targeting_limits = copy.deepcopy(server_group_targeting_limits) + for server_group_name, sg_targeting_limit in sg_targeting_limits.iteritems(): + if type(sg_targeting_limit) is str: + if MODEL_LIST_DELIMITER in sg_targeting_limit: + sg_targeting_limit = sg_targeting_limit.split(MODEL_LIST_DELIMITER) + else: + # convert a single value into a list of one... + new_list = list() + new_list.append(sg_targeting_limit) + sg_targeting_limit = new_list + + # Convert any references to a cluster name into the list of member server names + new_list = list() + for target_name in sg_targeting_limit: + target_name = target_name.strip() + if target_name in clusters_map: + cluster_members = dictionary_utils.get_element(clusters_map, target_name) + new_list.extend(cluster_members) + else: + # Assume it is a server name and add it to the new list + new_list.append(target_name) + sg_targeting_limits[server_group_name] = new_list + + self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=sg_targeting_limits) + return sg_targeting_limits + + def _get_server_to_server_groups_map(self, admin_server_name, server_names, server_groups, sg_targeting_limits): + """ + Get the map of server names to the list of server groups to target to that server. + :param admin_server_name: the admin server name + :param server_names: the list of server names + :param server_groups: the complete list of server groups that will, by default, be targeted to + all managed servers unless the server is listed in the targeting limits map + :param sg_targeting_limits: the targeting limits map + :return: the map of server names to the list of server groups to target to that server + """ + _method_name = '_get_server_to_server_groups_map' + + self.logger.entering(admin_server_name, str(server_names), str(server_groups), str(sg_targeting_limits), + class_name=self.__class_name, method_name=_method_name) + result = OrderedDict() + for server_name in server_names: + server_groups_for_server = self.__get_server_groups_for_server(server_name, sg_targeting_limits) + if server_groups_for_server is not None: + result[server_name] = server_groups_for_server + elif server_name != admin_server_name: + # By default, we only target managed servers unless explicitly listed in the targeting limits + result[server_name] = list(server_groups) + else: + result[admin_server_name] = list() + if admin_server_name not in result: + result[admin_server_name] = list() + self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) + return result + + def __get_server_groups_for_server(self, server_name, sg_targeting_limits): + """ + Get the servers groups to target for a given server name. + :param server_name: the server name + :param sg_targeting_limits: the targeting limits + :return: the list of server groups to target to the specified server name, or None + if the server name does not appear in the targeting limits + """ + _method_name = '__get_server_groups_for_server' + + self.logger.entering(server_name, str(sg_targeting_limits), + class_name=self.__class_name, method_name=_method_name) + result = None + for server_group, server_names_list in sg_targeting_limits.iteritems(): + if server_name in server_names_list: + if result is None: + result = list() + result.append(server_group) + self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) + return result