class MBeanAttributes(object): """ The MBeanAttributes class is a wrapper class encapsulating MBean information for the different types of MBean attribute collections. An instance of this class contains all attributes for an MBean at a specific location. The methods in this class operates on the attributes the class encapsulates to provide attribute specific information. """ __interface_matcher = re.compile('Bean$') def __init__(self, model_context, exception_type, location): self.__model_context = model_context self.__exception_type = exception_type self.__location = location self.__aliases = Aliases( self.__model_context, wlst_mode=self.__model_context.get_target_wlst_mode()) self.__alias_helper = AliasHelper(self.__aliases, _logger, exception_type) self.__wlst_helper = WlstHelper(_logger, exception_type) self.__mbean_instance = None self.__mbean_name = '' def _get_mbean_instance(self): _method_name = '_get_mbean_instance' if self.__mbean_instance is None: attribute_path = self.__alias_helper.get_wlst_attributes_path( self.__location) self.__mbean_instance = self.__wlst_helper.get_mbean( attribute_path) if self.__mbean_instance is None: ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-01775', attribute_path) _logger.throwing(ex, class_name=self.__class__.__name__, method_name=_method_name) raise ex return self.__mbean_instance def _get_mbean_interface(self): _method_name = '__get_mbean_interface' _logger.entering(class_name=self.__class__.__name__, method_name=_method_name) interfaces = [ str(interface) for interface in self._get_mbean_interfaces() if re.search(self.__interface_matcher, str(interface)) is not None ] if len(interfaces) == 0: ex = exception_helper.create_exception( self.__exception_type, 'WLSDPLY-01777', str(self._get_mbean_interfaces()), self._get_mbean_instance()) _logger.throwing(ex, class_name=self.__class__.__name__, method_name=_method_name) raise ex else: if len(interfaces) > 1: _logger.fine('WLSDPLY-01770', interfaces, self._get_mbean_instance(), class_name=self.__class__.__name__, method_name=_method_name) mbean_interface = interfaces[0] self.__mbean_name = self._get_mbean_interfaces()[0].getSimpleName() _logger.exiting(class_name=self.__class__.__name__, method_name=_method_name, result=mbean_interface) return mbean_interface def _get_mbean_methods(self): return self.__get_mbean_class().getDeclaredMethods() def _get_mbean_name(self): return self.__mbean_name def _get_mbean_interfaces(self): return self.__get_mbean_class().getInterfaces() def __get_mbean_class(self): _method_name = '__get_mbean_class' mbean_class = None mbean_instance = self._get_mbean_instance() try: getter = getattr(mbean_instance, 'getClass') mbean_class = getter() except AttributeError: pass if mbean_class is None: ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-01776', mbean_instance) _logger.throwing(ex, class_name=self.__class__.__name__, method_name=_method_name) raise ex return mbean_class def _get_from_bean_proxy(self, getter): _method_name = '__get_from_bean_proxy' success = False value = None try: get_method = getattr(self._get_mbean_instance(), getter) if get_method is not None: value = get_method() _logger.finest('WLSDPLY-01784', getter, self._get_mbean_name(), class_name=self.__class__.__name__, method_name=_method_name) success = True else: _logger.finer('WLSDPLY-01786', self._get_mbean_name(), getter, class_name=self.__class__.__name__, method_name=_method_name) except (Exception, JException), e: _logger.finest('WLSDPLY-01785', self._get_mbean_name(), getter, str(e), class_name=self.__class__.__name__, method_name=_method_name) return success, value
class Discoverer(object): """ Discoverer contains the private methods used to facilitate discovery of the domain information by its subclasses. """ def __init__(self, model_context, base_location, wlst_mode, aliases=None, variable_injector=None): """ :param model_context: context about the model for this instance of discover domain :param base_location: to look for common weblogic resources. By default this is the global path or '/' """ self._model_context = model_context self._base_location = base_location self._wlst_mode = wlst_mode if aliases: self._aliases = aliases else: self._aliases = Aliases(self._model_context, wlst_mode=self._wlst_mode) self._alias_helper = AliasHelper(self._aliases, _logger, ExceptionType.DISCOVER) self._variable_injector = variable_injector self._att_handler_map = OrderedDict() self._custom_folder = CustomFolderHelper(self._aliases, _logger, self._model_context, ExceptionType.DISCOVER, self._variable_injector) self._weblogic_helper = WebLogicHelper(_logger) self._wlst_helper = WlstHelper(ExceptionType.DISCOVER) self._mbean_utils = MBeanUtils(self._model_context, self._alias_helper, ExceptionType.DISCOVER) self._wls_version = self._weblogic_helper.get_actual_weblogic_version() # methods for use only by the subclasses def _populate_model_parameters(self, dictionary, location): """ Populate the model dictionary with the attribute values discovered at the current location. Perform any special processing for a specific attribute before storing into the model dictionary. :param dictionary: where to store the discovered attributes :param location: context containing current location information :return: dictionary of model attribute name and wlst value """ _method_name = '_populate_model_parameters' wlst_path = self._alias_helper.get_wlst_attributes_path(location) _logger.finer('WLSDPLY-06100', wlst_path, class_name=_class_name, method_name=_method_name) if not self.wlst_cd(wlst_path, location): return wlst_lsa_params = self._get_attributes_for_current_location(location) _logger.finest('WLSDPLY-06102', self._wlst_helper.get_pwd(), wlst_lsa_params, class_name=_class_name, method_name=_method_name) wlst_get_params = self._get_required_attributes(location) _logger.finest('WLSDPLY-06103', str(location), wlst_get_params, class_name=_class_name, method_name=_method_name) if wlst_lsa_params is not None: for wlst_lsa_param in wlst_lsa_params: if wlst_lsa_param in wlst_get_params: success, wlst_value = self._get_attribute_value_with_get( wlst_lsa_param, wlst_path) if not success: continue else: _logger.finer('WLSDPLY-06131', wlst_lsa_param, class_name=_class_name, method_name=_method_name) wlst_value = wlst_lsa_params[wlst_lsa_param] self._add_to_dictionary(dictionary, location, wlst_lsa_param, wlst_value, wlst_path) # These will come after the lsa / get params in the ordered dictionary wlst_extra_params = self._get_additional_parameters(location) _logger.finest('WLSDPLY-06149', str(location), wlst_extra_params, class_name=_class_name, method_name=_method_name) if wlst_extra_params is not None: for wlst_extra_param in wlst_extra_params: if wlst_extra_param in wlst_get_params: success, wlst_value = self._get_attribute_value_with_get( wlst_extra_param, wlst_path) if success: self._add_to_dictionary(dictionary, location, wlst_extra_param, wlst_value, wlst_path) else: _logger.info('WLSDPLY-06152', wlst_extra_param, location.get_folder_path(), class_name=_class_name, method_name=_method_name) elif self._is_defined_attribute(location, wlst_extra_param): _logger.info('WLSDPLY-06154', wlst_extra_param, location.get_folder_path(), class_name=_class_name, method_name=_method_name) else: _logger.info('WLSDPLY-06153', wlst_extra_param, location.get_folder_path(), class_name=_class_name, method_name=_method_name) def _get_attribute_value_with_get(self, wlst_get_param, wlst_path): _method_name = '_get_attribute_value_with_get' _logger.finest('WLSDPLY-06104', wlst_get_param, class_name=_class_name, method_name=_method_name) success = False wlst_value = None try: wlst_value = self._wlst_helper.get(wlst_get_param) success = True except DiscoverException, pe: _logger.warning('WLSDPLY-06127', wlst_get_param, wlst_path, pe.getLocalizedMessage(), class_name=_class_name, method_name=_method_name) return success, wlst_value
class PrepareModel: """ This is the main driver for the caller. It compares two model files whether they are json or yaml format. """ def __init__(self, model_files, model_context, logger, output_dir=None): self.model_files = model_files self.output_dir = output_dir self.model_context = model_context self._aliases = Aliases(model_context=model_context, wlst_mode=WlstModes.OFFLINE) self._alias_helper = AliasHelper(self._aliases, logger, ExceptionType.COMPARE) self._logger = logger self._name_tokens_location = LocationContext() self._name_tokens_location.add_name_token('DOMAIN', "testdomain") self.current_dict = None self.cache = OrderedDict() self.secrets_to_generate = sets.Set() def __walk_model_section(self, model_section_key, model_dict, valid_section_folders): _method_name = '__validate_model_section' if model_section_key not in model_dict.keys(): return # only specific top-level sections have attributes attribute_location = self._alias_helper.get_model_section_attribute_location( model_section_key) valid_attr_infos = [] path_tokens_attr_keys = [] if attribute_location is not None: valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types( attribute_location) path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names( attribute_location) model_section_dict = model_dict[model_section_key] for section_dict_key, section_dict_value in model_section_dict.iteritems( ): # section_dict_key is either the name of a folder in the # section, or the name of an attribute in the section. validation_location = LocationContext() model_folder_path = model_section_key + ":/" if section_dict_key in valid_attr_infos: # section_dict_key is the name of an attribute in the section self.__walk_attribute(section_dict_key, section_dict_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, attribute_location) elif section_dict_key in valid_section_folders: # section_dict_key is a folder under the model section # Append section_dict_key to location context validation_location.append_location(section_dict_key) # Call self.__validate_section_folder() passing in section_dict_value as the model_node to process self.__walk_section_folder(section_dict_value, validation_location) def __walk_section_folder(self, model_node, validation_location): _method_name = '__validate_section_folder' model_folder_path = self._alias_helper.get_model_folder_path( validation_location) if self._alias_helper.supports_multiple_mbean_instances( validation_location): for name in model_node: expanded_name = name new_location = LocationContext(validation_location) name_token = self._alias_helper.get_name_token(new_location) if name_token is not None: new_location.add_name_token(name_token, expanded_name) value_dict = model_node[name] self.__walk_model_node(value_dict, new_location) elif self._alias_helper.requires_artificial_type_subfolder_handling( validation_location): for name in model_node: expanded_name = name new_location = LocationContext(validation_location) name_token = self._alias_helper.get_name_token(new_location) if name_token is not None: new_location.add_name_token(name_token, expanded_name) value_dict = model_node[name] self.__walk_model_node(value_dict, new_location) else: name_token = self._alias_helper.get_name_token(validation_location) if name_token is not None: name = self._name_tokens_location.get_name_for_token( name_token) if name is None: name = '%s-0' % name_token validation_location.add_name_token(name_token, name) self.__walk_model_node(model_node, validation_location) def __walk_model_node(self, model_node, validation_location): _method_name = '__process_model_node' valid_folder_keys = self._alias_helper.get_model_subfolder_names( validation_location) valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types( validation_location) model_folder_path = self._alias_helper.get_model_folder_path( validation_location) for key, value in model_node.iteritems(): if key in valid_folder_keys: new_location = LocationContext( validation_location).append_location(key) if self._alias_helper.is_artificial_type_folder(new_location): # key is an ARTIFICIAL_TYPE folder valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types( new_location) self.__walk_attributes(value, valid_attr_infos, new_location) else: self.__walk_section_folder(value, new_location) elif key in valid_attr_infos: # aliases.get_model_attribute_names_and_types(location) filters out # attributes that ARE NOT valid in the wlst_version being used, so if # we're in this section of code we know key is a bonafide "valid" attribute valid_data_type = valid_attr_infos[key] if valid_data_type in ['properties']: valid_prop_infos = {} properties = validation_utils.get_properties(value) self.__walk_properties(properties, valid_prop_infos, model_folder_path, validation_location) else: path_tokens_attr_keys = \ self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location) self.__walk_attribute(key, value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location) def __walk_attributes(self, attributes_dict, valid_attr_infos, validation_location): _method_name = '__validate_attributes' path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names( validation_location) model_folder_path = self._alias_helper.get_model_folder_path( validation_location) for attribute_name, attribute_value in attributes_dict.iteritems(): self.__walk_attribute(attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location) def __walk_attribute(self, attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location): _method_name = '__walk_attribute' if attribute_name in valid_attr_infos: expected_data_type = valid_attr_infos[attribute_name] if (expected_data_type == 'password') or (attribute_name == ADMIN_USERNAME): self.__substitute_password_with_token(model_folder_path, attribute_name, validation_location) self._logger.exiting(class_name=_class_name, method_name=_method_name) def __walk_properties(self, properties_dict, valid_prop_infos, model_folder_path, validation_location): _method_name = '__walk_properties' for property_name, property_value in properties_dict.iteritems(): valid_prop_infos[ property_name] = validation_utils.get_python_data_type( property_value) self.__walk_property(property_name, property_value, valid_prop_infos, model_folder_path, validation_location) def __walk_property(self, property_name, property_value, valid_prop_infos, model_folder_path, validation_location): _method_name = '__walk_property' self._logger.entering(property_name, property_value, str(valid_prop_infos), model_folder_path, class_name=_class_name, method_name=_method_name) if property_name in valid_prop_infos: expected_data_type = valid_prop_infos[property_name] if expected_data_type == 'password': self.__substitute_password_with_token(model_folder_path, property_name, validation_location) def __substitute_password_with_token(self, model_path, attribute_name, validation_location): """ Add the secret for the specified attribute to the cache. If the target specifies credentials_method: secrets, substitute the secret token into the model. :param model_path: text representation of the model path :param attribute_name: the name of the attribute or (property) :param validation_location: the model location """ model_path_tokens = model_path.split('/') tokens_length = len(model_path_tokens) variable_name = variable_injector_functions.format_variable_name( validation_location, attribute_name, self._aliases) if tokens_length > 1: credentials_method = self.model_context.get_target_configuration( ).get_credentials_method() # by default, don't do any assignment to attribute model_value = None # use attribute name for admin password if model_path_tokens[0] == 'domainInfo:' and model_path_tokens[ 1] == '': cache_key = attribute_name else: cache_key = variable_name # for normal secrets, assign the secret name to the attribute if credentials_method == SECRETS_METHOD: model_value = target_configuration_helper.format_as_secret_token( cache_key) self.cache[cache_key] = '' # for config override secrets, assign a placeholder password to the attribute. # config overrides will be used to override the value in the target domain. if credentials_method == CONFIG_OVERRIDES_SECRETS_METHOD: model_value = PASSWORD_PLACEHOLDER self.cache[cache_key] = '' if model_value is not None: p_dict = self.current_dict for index in range(0, len(model_path_tokens)): token = model_path_tokens[index] if token == '': break if token[-1] == ':': token = token[:-1] p_dict = p_dict[token] p_dict[attribute_name] = model_value def walk(self): """ Replace password attributes in each model file with secret tokens, and write each model. Generate a script to create the required secrets. Create any additional output specified for the target environment. """ _method_name = "walk" model_file_name = None try: model_file_list = self.model_files.split(',') for model_file in model_file_list: self.cache.clear() if os.path.splitext(model_file)[1].lower() == ".yaml": model_file_name = model_file FileToPython(model_file_name, True).parse() aliases = Aliases(model_context=self.model_context, wlst_mode=WlstModes.OFFLINE) validator = Validator(self.model_context, aliases, wlst_mode=WlstModes.OFFLINE) # Just merge and validate but without substitution model_dictionary = cla_helper.merge_model_files( model_file_name, None) variable_file = self.model_context.get_variable_file() if not os.path.exists(variable_file): variable_file = None return_code = validator.validate_in_tool_mode( model_dictionary, variables_file_name=variable_file, archive_file_name=None) if return_code == Validator.ReturnCode.STOP: self._logger.severe('WLSDPLY-05705', model_file_name) return VALIDATION_FAIL self.current_dict = model_dictionary self.__walk_model_section( model.get_model_domain_info_key(), self.current_dict, aliases.get_model_section_top_level_folder_names( DOMAIN_INFO)) self.__walk_model_section( model.get_model_topology_key(), self.current_dict, aliases.get_model_topology_top_level_folder_names()) self.__walk_model_section( model.get_model_resources_key(), self.current_dict, aliases.get_model_resources_top_level_folder_names()) self.current_dict = self._apply_filter_and_inject_variable( self.current_dict, self.model_context, validator) file_name = os.path.join(self.output_dir, os.path.basename(model_file_name)) fos = JFileOutputStream(file_name, False) writer = JPrintWriter(fos, True) pty = PythonToYaml(self.current_dict) pty._write_dictionary_to_yaml_file(self.current_dict, writer) writer.close() self.cache.clear() for key in self.secrets_to_generate: self.cache[key] = '' # use a merged, substituted, filtered model to get domain name and create additional target output. full_model_dictionary = cla_helper.load_model( _program_name, self.model_context, self._alias_helper, "discover", WlstModes.OFFLINE) target_configuration_helper.generate_k8s_script( self.model_context, self.cache, full_model_dictionary) # create any additional outputs from full model dictionary target_configuration_helper.create_additional_output( Model(full_model_dictionary), self.model_context, self._alias_helper, ExceptionType.VALIDATE) except ValidateException, te: self._logger.severe('WLSDPLY-20009', _program_name, model_file_name, te.getLocalizedMessage(), error=te, class_name=_class_name, method_name=_method_name) ex = exception_helper.create_compare_exception( te.getLocalizedMessage(), error=te) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) return VALIDATION_FAIL except VariableException, ve: self._logger.severe('WLSDPLY-20009', _program_name, model_file_name, ve.getLocalizedMessage(), error=ve, class_name=_class_name, method_name=_method_name) ex = exception_helper.create_compare_exception( ve.getLocalizedMessage(), error=ve) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) return VALIDATION_FAIL
class Creator(object): """ The base class used by the DomainCreator. """ __class_name = 'Creator' def __init__(self, model, model_context, aliases, exception_type=ExceptionType.CREATE, logger=PlatformLogger('wlsdeploy.create')): self.logger = logger self.aliases = aliases self._exception_type = exception_type 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, exception_type) self.custom_folder_helper = CustomFolderHelper(self.aliases, self.logger, self.model_context, exception_type) # Must be initialized by the subclass since only it has # the knowledge required to compute the domain name. self.archive_helper = None self.files_to_extract_from_archive = list() return def _create_named_mbeans(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified type of MBeans that support multiple instances in the specified location. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBeans :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 """ _method_name = '_create_named_mbeans' self.logger.entering(type_name, str(base_location), log_created, class_name=self.__class_name, method_name=_method_name) if model_nodes is None or len( model_nodes) == 0 or not self._is_type_valid( base_location, type_name): return location = LocationContext(base_location).append_location(type_name) self._process_flattened_folder(location) token_name = self.alias_helper.get_name_token(location) create_path = self.alias_helper.get_wlst_create_path(location) list_path = self.alias_helper.get_wlst_list_path(location) existing_folder_names = self._get_existing_folders(list_path) for model_name in model_nodes: name = self.wlst_helper.get_quoted_name_for_wlst(model_name) if token_name is not None: location.add_name_token(token_name, name) wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name( location) if wlst_name not in existing_folder_names: if log_created: self.logger.info('WLSDPLY-12100', type_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12100', type_name, name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location, create_path) else: if log_created: self.logger.info('WLSDPLY-12101', type_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12101', type_name, name, class_name=self.__class_name, method_name=_method_name) attribute_path = self.alias_helper.get_wlst_attributes_path( location) self.wlst_helper.cd(attribute_path) child_nodes = dictionary_utils.get_dictionary_element( model_nodes, name) self._process_child_nodes(location, child_nodes) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _create_mbean(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified type of MBean that support a single instance in the specified location. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBean :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 """ _method_name = '_create_mbean' self.logger.entering(type_name, str(base_location), log_created, class_name=self.__class_name, method_name=_method_name) if model_nodes is None or len( model_nodes) == 0 or not self._is_type_valid( base_location, type_name): return location = LocationContext(base_location).append_location(type_name) result, message = self.alias_helper.is_version_valid_location(location) if result == ValidationCodes.VERSION_INVALID: self.logger.warning('WLSDPLY-12123', message, class_name=self.__class_name, method_name=_method_name) return create_path = self.alias_helper.get_wlst_create_path(location) existing_folder_names = self._get_existing_folders(create_path) mbean_type, mbean_name = self.alias_helper.get_wlst_mbean_type_and_name( location) token_name = self.alias_helper.get_name_token(location) if token_name is not None: if self.alias_helper.requires_unpredictable_single_name_handling( location): existing_subfolder_names = deployer_utils.get_existing_object_list( location, self.alias_helper) if len(existing_subfolder_names) > 0: mbean_name = existing_subfolder_names[0] location.add_name_token(token_name, mbean_name) self._process_flattened_folder(location) if mbean_type not in existing_folder_names: if log_created: self.logger.info('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.create_and_cd(self.alias_helper, mbean_type, mbean_name, location, create_path) else: if log_created: self.logger.info('WLSDPLY-20013', type_name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) attribute_path = self.alias_helper.get_wlst_attributes_path( location) self.wlst_helper.cd(attribute_path) self._process_child_nodes(location, model_nodes) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _create_named_subtype_mbeans(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified type of MBeans that support multiple instances, and require an artificial subtype layer after each name. There is no default behavior for this method. Sub-classes (currently only SecurityProviderCreator) will implement specialized behavior. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBeans :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 """ return def _create_subfolders(self, location, model_nodes): """ Create the child MBean folders at the specified location. :param location: the location :param model_nodes: the model dictionary :raises: CreateException: if an error occurs """ _method_name = '_create_subfolders' self.logger.entering(location.get_folder_path(), class_name=self.__class_name, method_name=_method_name) model_subfolder_names = self.alias_helper.get_model_subfolder_names( location) for key in model_nodes: if key in model_subfolder_names: subfolder_nodes = model_nodes[key] # don't check for empty subfolder nodes here, some create methods allow them sub_location = LocationContext(location).append_location(key) if self.alias_helper.requires_artificial_type_subfolder_handling( sub_location): self.logger.finest('WLSDPLY-12116', key, str(sub_location), subfolder_nodes, class_name=self.__class_name, method_name=_method_name) self._create_named_subtype_mbeans(key, subfolder_nodes, location, True) elif self.alias_helper.supports_multiple_mbean_instances( sub_location): self.logger.finest('WLSDPLY-12109', key, str(sub_location), subfolder_nodes, class_name=self.__class_name, method_name=_method_name) self._create_named_mbeans(key, subfolder_nodes, location) elif self.alias_helper.is_artificial_type_folder(sub_location): # these should have been handled inside create_named_subtype_mbeans ex = exception_helper.create_create_exception( 'WLSDPLY-12120', str(sub_location), key, str(location)) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex else: self.logger.finest('WLSDPLY-12110', key, str(sub_location), subfolder_nodes, class_name=self.__class_name, method_name=_method_name) self._create_mbean(key, subfolder_nodes, location) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _process_child_nodes(self, location, model_nodes): """ Process the model nodes at the specified location. The default behavior is to process attributes, then sub-folders. Sub-classes may override to reverse this order, or for other special processing. :param location: the location where the nodes should be applied :param model_nodes: the model dictionary of the nodes to be applied :raises: CreateException: if an error occurs """ _method_name = '_process_child_nodes' self.logger.finest('WLSDPLY-12111', self.alias_helper.get_model_folder_path(location), self.wlst_helper.get_pwd(), class_name=self.__class_name, method_name=_method_name) self._set_attributes(location, model_nodes) self._create_subfolders(location, model_nodes) def _set_attributes(self, location, model_nodes): """ Set the attributes for the MBean at the specified location. :param location: the location :param model_nodes: the model dictionary :raises: CreateException: if an error occurs """ _method_name = '_set_attributes' model_attribute_names = self.alias_helper.get_model_attribute_names_and_types( location) password_attribute_names = self.alias_helper.get_model_password_type_attribute_names( location) set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types( location) uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names( location) model_folder_path = self.alias_helper.get_model_folder_path(location) pwd = self.wlst_helper.get_pwd() for key, value in model_nodes.iteritems(): if key in model_attribute_names: if key in set_method_map: self.logger.finest('WLSDPLY-12112', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_mbean_attribute(location, key, value, set_method_map) elif key in password_attribute_names: self.logger.finest('WLSDPLY-12113', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_attribute(location, key, value, uses_path_tokens_attribute_names, masked=True) else: self.logger.finest('WLSDPLY-12113', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_attribute(location, key, value, uses_path_tokens_attribute_names) return def _set_mbean_attribute(self, location, model_key, model_value, set_method_map): """ Set the attributes for the MBean that require an MBean value to set at the specified location. :param location: the location :param model_key: the model attribute name :param model_value: the model attribute value :param set_method_map: the set method map that maps the attribute names requiring MBean values to the attribute setter method name :raises: CreateException: if an error occurs """ _method_name = '_set_mbean_attribute' set_method_info = dictionary_utils.get_dictionary_element( set_method_map, model_key) set_method_name = dictionary_utils.get_element(set_method_info, 'set_method') if set_method_name is not None: try: self.logger.finest('WLSDPLY-12114', model_key, model_value, set_method_name, class_name=self.__class_name, method_name=_method_name) set_method = getattr(self.attribute_setter, set_method_name) set_method(location, model_key, model_value, None) except AttributeError, ae: ex = exception_helper.create_create_exception( 'WLSDPLY-12104', set_method_name, model_key, self.alias_helper.get_model_folder_path(location), error=ae) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex else:
def __init__(self, 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._coherence_cluster_elements = [CLUSTER, SERVER, SERVER_TEMPLATE]
class Discoverer(object): """ Discoverer contains the private methods used to facilitate discovery of the domain information by its subclasses. """ def __init__(self, model_context, base_location, wlst_mode, aliases=None): """ :param model_context: context about the model for this instance of discover domain :param base_location: to look for common weblogic resources. By default this is the global path or '/' """ self._model_context = model_context self._base_location = base_location self._wlst_mode = wlst_mode if aliases: self._aliases = aliases else: self._aliases = Aliases(self._model_context, wlst_mode=self._wlst_mode) self._alias_helper = AliasHelper(self._aliases, _logger, ExceptionType.DISCOVER) self._att_handler_map = OrderedDict() self._wls_version = WebLogicHelper( _logger).get_actual_weblogic_version() self._wlst_helper = WlstHelper(_logger, ExceptionType.DISCOVER) # methods for use only by the subclasses def _populate_model_parameters(self, dictionary, location): """ Populate the model dictionary with the attribute values discovered at the current location. Perform any special processing for a specific attribute before storing into the model dictionary. :param dictionary: where to store the discovered attributes :param location: context containing current location information :return: dictionary of model attribute name and wlst value """ _method_name = '_populate_model_parameters' wlst_path = self._alias_helper.get_wlst_attributes_path(location) _logger.finer('WLSDPLY-06100', wlst_path, class_name=_class_name, method_name=_method_name) if not self.wlst_cd(wlst_path, location): return wlst_params = self._get_attributes_for_current_location(location) _logger.finest('WLSDPLY-06102', self._wlst_helper.get_pwd(), wlst_params, class_name=_class_name, method_name=_method_name) wlst_get_params = self._get_required_attributes(location) _logger.finest('WLSDPLY-06103', str(location), wlst_get_params, class_name=_class_name, method_name=_method_name) attr_dict = OrderedDict() if wlst_params: for wlst_param in wlst_params: if wlst_param in wlst_get_params: _logger.finest('WLSDPLY-06104', wlst_param, class_name=_class_name, method_name=_method_name) try: wlst_value = wlst_helper.get(wlst_param) except PyWLSTException, pe: _logger.warning('WLSDPLY-06127', wlst_param, wlst_path, pe.getLocalizedMessage(), class_name=_class_name, method_name=_method_name) continue else: _logger.finer('WLSDPLY-06131', wlst_param, class_name=_class_name, method_name=_method_name) wlst_value = wlst_params[wlst_param] # if type(wlst_value) == str and len(wlst_value) == 0: # wlst_value = None _logger.finer('WLSDPLY-06105', wlst_param, wlst_value, wlst_path, class_name=_class_name, method_name=_method_name) try: model_param, model_value = self._aliases.get_model_attribute_name_and_value( location, wlst_param, wlst_value) except AliasException, de: _logger.info('WLSDPLY-06106', wlst_param, wlst_path, de.getLocalizedMessage(), class_name=_class_name, method_name=_method_name) continue attr_dict[model_param] = wlst_value model_value = self._check_attribute(model_param, model_value, location) if model_value is not None: _logger.finer('WLSDPLY-06107', model_param, model_value, class_name=_class_name, method_name=_method_name) dictionary[model_param] = model_value elif model_param is None: _logger.finest('WLSDPLY-06108', model_param, class_name=_class_name, method_name=_method_name)
class AttributeSetter(object): """ Contains the "set" methods used to set WLST values that require mbeans or other special processing. The public set_ methods in this class correspond directly to the set_method names in the alias files. The signature for each set_ method is (location, key, value), where key and value are from the model. """ # used for target search __target_type_names = [ CLUSTER, SERVER, MIGRATABLE_TARGET, ] # used for destination search __destination_type_names = [ QUEUE, TOPIC, DISTRIBUTED_QUEUE, DISTRIBUTED_TOPIC, UNIFORM_DISTRIBUTED_QUEUE, UNIFORM_DISTRIBUTED_TOPIC ] # used for SAF destination search __saf_destination_type_names = [ SAF_QUEUE, SAF_TOPIC ] # used for persistent store search __persistent_store_type_names = [ FILE_STORE, JDBC_STORE ] # used for self-tuning deployment and attribute processing. # these names are applicable as self-tuning sub-folder names, and work manager attribute names. # work manager is intentionally excluded and treated separately. __self_tuning_type_names = [ CAPACITY, CONTEXT_REQUEST_CLASS, FAIR_SHARE_REQUEST_CLASS, MAX_THREADS_CONSTRAINT, MIN_THREADS_CONSTRAINT, RESPONSE_TIME_REQUEST_CLASS ] # used for WLDF watch notification search __watch_action_types = [ HEAP_DUMP_ACTION, IMAGE_NOTIFICATION, JMS_NOTIFICATION, JMX_NOTIFICATION, LOG_ACTION, REST_NOTIFICATION, SCRIPT_ACTION, SMTP_NOTIFICATION, SNMP_NOTIFICATION, THREAD_DUMP_ACTION ] _class_name = "AttributeSetter" def __init__(self, aliases, logger, exception_type, wlst_mode=WlstModes.OFFLINE): self.__logger = logger self.__exception_type = exception_type self.__wlst_mode = wlst_mode self.__alias_helper = AliasHelper(aliases, self.__logger, exception_type) self.__wlst_helper = WlstHelper(self.__logger, exception_type) return # # public set_ methods for special attribute types, signature (self, location, key, value, wlst_value, ...) # def set_target_jms_mbeans(self, location, key, value, wlst_value): """ Set the target MBeans for targets that can include JMS resources (e.g., JMSServer). :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ self.set_target_mbeans(location, key, value, wlst_value, include_jms=True) return def set_target_mbeans(self, location, key, value, wlst_value, include_jms=False): """ Set the target MBeans. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :param include_jms: whether or not to include JMS resources :raises BundleAwareException of the specified type: if target is not found """ targets_value = self.__build_target_mbean_list(value, wlst_value, location, include_jms=include_jms) self.set_attribute(location, key, targets_value, wlst_merge_value=wlst_value, use_raw_value=True) return def set_jms_error_destination_mbean(self, location, key, value, wlst_value): """ Set the JMS Error Destination MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if destination is not found """ mbean = self.__find_jms_destination_mbean(location, value) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_jms_bridge_destination_mbean(self, location, key, value, wlst_value): """ Set the JMS Bridge Destination MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if destination is not found """ mbean = self.__find_in_resource_group_or_domain(location, JMS_BRIDGE_DESTINATION, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_persistent_store_mbean(self, location, key, value, wlst_value): """ Set the Persistent Store MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if store is not found """ mbean = self.__find_persistent_store(location, value) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_data_source_mbean(self, location, key, value, wlst_value): """ Set the DataSource MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if DataSource is not found """ mbean = self.__find_in_resource_group_or_domain(location, JDBC_SYSTEM_RESOURCE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_saf_remote_context_mbean(self, location, key, value, wlst_value): """ Set the SAF RemoteContext MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if SAF RemoteContext is not found """ resource_location = self.__get_parent_location(location, JMS_RESOURCE) mbean = self.__find_in_location(resource_location, SAF_REMOTE_CONTEXT, value) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_saf_error_destination_mbean(self, location, key, value, wlst_value): """ Set the SAF Error Destination MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if destination is not found """ mbean = self.__find_saf_destination_mbean(location, value) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_self_tuning_mbean(self, location, key, value, wlst_value): """ Set the SelfTuning MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if MBean is not found """ tuning_location = self.__get_parent_location(location, SELF_TUNING) mbean = self.__find_in_location(tuning_location, key, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_server_mbeans(self, location, key, value, wlst_value): """ Set the Server MBeans. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if a server is not found """ mbeans = self.__build_server_mbean_list(value, wlst_value) self.set_attribute(location, key, mbeans, wlst_merge_value=wlst_value, use_raw_value=True) return def set_server_mbean(self, location, key, value, wlst_value): """ Set the Server MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the server is not found """ mbean = self.__find_in_location(LocationContext(), SERVER, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_server_template_mbean(self, location, key, value, wlst_value): """ Set the Server Template MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the server template is not found """ mbean = self.__find_in_location(LocationContext(), SERVER_TEMPLATE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_cluster_mbean(self, location, key, value, wlst_value): """ Set the Cluster MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the cluster is not found """ mbean = self.__find_in_location(LocationContext(), CLUSTER, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_server_cluster_mbean(self, location, key, value, wlst_value): """ assign the Cluster MBean to a server. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the cluster is not found """ entity_type, entity_name = self.__alias_helper.get_model_type_and_name(location) self.__wlst_helper.assign(entity_type, entity_name, key, value) return def set_coherence_cluster_mbean(self, location, key, value, wlst_value): """ Set the Log Filter MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if store is not found """ mbean = self.__find_in_location(LocationContext(), COHERENCE_CLUSTER_SYSTEM_RESOURCE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_machine_mbean(self, location, key, value, wlst_value): """ Set the Machine MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the machine is not found """ mbean = self.__find_in_location(LocationContext(), MACHINE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_jms_template_mbean(self, location, key, value, wlst_value): """ Set the JMS Template MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the JMS Template is not found """ resource_location = self.__get_parent_location(location, JMS_RESOURCE) mbean = self.__find_in_location(resource_location, TEMPLATE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_wldf_action_mbeans(self, location, key, value, wlst_value): """ Set the WLDF Action/Notification MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if the WLDF Action/Notification is not found """ watch_location = self.__get_parent_location(location, WATCH_NOTIFICATION) action_names = TypeUtils.convertToType(List, value) # type: list of str action_names = self.__merge_existing_items(action_names, wlst_value) action_mbeans = [] for action_name in action_names: action_mbean = self.__find_wldf_action(watch_location, action_name) action_mbeans.append(action_mbean) if self.__wlst_mode == WlstModes.ONLINE: # for online, call the current location's add method for each action mbean location_mbean = self.__wlst_helper.cd(self.__wlst_helper.get_pwd()) for action_mbean in action_mbeans: location_mbean.addNotification(action_mbean) else: self.set_attribute(location, key, action_mbeans, wlst_merge_value=wlst_value, use_raw_value=True) return def set_log_filter_mbean(self, location, key, value, wlst_value): """ Set the Log Filter MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if store is not found """ mbean = self.__find_in_location(LocationContext(), LOG_FILTER, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_jms_server_mbean(self, location, key, value, wlst_value): """ For those entities, such as WLSReliableDeliveryPolicy, that take a single JMS Server mbean. :param location: location to look for jms server :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if jms server mbean is not found. """ mbean = self.__find_in_location(LocationContext(), JMS_SERVER, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_jms_quota_mbean(self, location, key, value, wlst_value): """ For those entities, queues, template, topics, that take a single Quota mbean. :param location: location to look for Quota mbean :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if quota mbean is not found. """ resource_location = self.__get_parent_location(location, JMS_RESOURCE) mbean = self.__find_in_location(resource_location, QUOTA, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_reliable_delivery_policy_mbean(self, location, key, value, wlst_value): """ Sets the ws soap reliable delivery policy mbean used by mbeans like Server and Server Template. :param location: location to look for reliable delivery policy :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if reliable delivery policy mbean is not found. """ mbean = self.__find_in_location(LocationContext(), WS_RELIABLE_DELIVERY_POLICY, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_xml_entity_cache_mbean(self, location, key, value, wlst_value): """ Sets the XML cache mbean used by topology entities such as Server. :param location: location to look for reliable delivery policy :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if xml entity cache mbean is not found. """ mbean = self.__find_in_location(LocationContext(), XML_ENTITY_CACHE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_xml_registry_mbean(self, location, key, value, wlst_value): """ Sets the XML registry mbean used by topology entities such as Server. :param location: location to look for reliable delivery policy :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if xml registry mbean is not found. """ mbean = self.__find_in_location(LocationContext(), XML_REGISTRY, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_mt_target_mbeans(self, location, key, value, wlst_value): """ Set the virtual target MBeans. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ targets_value = self.__build_virtual_target_mbean_list(value, wlst_value) self.set_attribute(location, key, targets_value, wlst_merge_value=wlst_value, use_raw_value=True) return def set_partition_security_realm(self, location, key, value, wlst_value): """ Set the security realm MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ security_location = self.__get_domain_location(location).append_location(SECURITY_CONFIGURATION) mbean = self.__find_in_location(security_location, REALM, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_resource_group_template_mbean(self, location, key, value, wlst_value): """ Set the resource group template MBean. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ domain_location = self.__get_domain_location(location) mbean = self.__find_in_location(domain_location, RESOURCE_GROUP_TEMPLATE, value, required=True) self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_partition_work_manager_mbean(self, location, key, value, wlst_value): """ Set the partition work manager MBean. Search in the same partition, then at the domain level. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ method_name = 'set_partition_work_manager_mbean' partition_location = self.__get_parent_location(location, PARTITION) mbean = self.__find_in_location(partition_location, PARTITION_WORK_MANAGER, value) if mbean is None: domain_location = self.__get_domain_location(location) mbean = self.__find_in_location(domain_location, PARTITION_WORK_MANAGER, value) if mbean is None: _type, partition_name = self.__alias_helper.get_model_type_and_name(location) ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19206', value, partition_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return def set_resource_manager_mbean(self, location, key, value, wlst_value): """ Set the resource manager MBean. Search in the same partition, then at the domain level. :param location: the location :param key: the attribute name :param value: the string value :param wlst_value: the existing value of the attribute from WLST :raises BundleAwareException of the specified type: if target is not found """ method_name = 'set_resource_manager_mbean' partition_location = self.__get_parent_location(location, PARTITION) mbean = self.__find_in_location(partition_location, RESOURCE_MANAGER, value) if mbean is None: management_location = self.__get_domain_location(location).append_location(RESOURCE_MANAGEMENT) mbean = self.__find_in_location(management_location, RESOURCE_MANAGER, value) if mbean is None: _type, manager_name = self.__alias_helper.get_model_type_and_name(location) ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19207', value, manager_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex self.set_attribute(location, key, mbean, wlst_merge_value=wlst_value, use_raw_value=True) return # # public set_attribute convenience methods # def set_attribute(self, location, model_key, model_value, wlst_merge_value=None, use_raw_value=False): """ Convenience method for setting the attribute. :param location: location :param model_key: attribute name :param model_value: attribute value :param wlst_merge_value: value from WLST to merge :param use_raw_value: whether or not to the use the model value, default is to use the WLST value :raises BundleAwareException of the specified type: if an error occurs """ _method_name = 'set_attribute' if use_raw_value: wlst_param = self.__alias_helper.get_wlst_attribute_name(location, model_key) wlst_value = model_value else: wlst_param, wlst_value = \ self.__alias_helper.get_wlst_attribute_name_and_value(location, model_key, model_value, existing_wlst_value=wlst_merge_value) if wlst_param is None: self.__logger.info('WLSDPLY-20011', model_key, class_name=self._class_name, method_name=_method_name) elif wlst_value is None: self.__logger.info('WLSDPLY-20012', model_key, str(model_value), class_name=self._class_name, method_name=_method_name) else: self.__wlst_helper.set(wlst_param, wlst_value) return def set_attribute_with_cmo(self, location, key, value, wlst_value=None, masked=False): _method_name = 'set_attribute_with_cmo' wlst_attr_name, wlst_attr_value = \ self.__alias_helper.get_wlst_attribute_name_and_value(location, key, value, existing_wlst_value=wlst_value) if wlst_attr_name is None: self.__logger.info('WLSDPLY-20011', key, class_name=self._class_name, method_name=_method_name) elif wlst_attr_value is None: log_value = str(value) if masked: log_value = '<masked>' self.__logger.info('WLSDPLY-20012', key, log_value, class_name=self._class_name, method_name=_method_name) else: self.__wlst_helper.set_with_cmo(wlst_attr_name, wlst_attr_value, masked=masked) return # # internal lookup methods # def __build_target_mbean_list(self, target_value, wlst_value, location, include_jms=False): """ Construct the target MBean list. :param target_value: the target value :param wlst_value: the existing value from WLST :param include_jms: whether or not to include JMS targets, the default is False :return: the Java array of MBeans ObjectNames :raises BundleAwareException of the specified type: if an error occurs """ target_names = TypeUtils.convertToType(List, target_value) # type: list of str target_names = self.__merge_existing_items(target_names, wlst_value) name_list = [] for target_name in target_names: target_mbean = self.__find_target(target_name, location, include_jms=include_jms) name_list.append(target_mbean.getObjectName()) return jarray.array(name_list, ObjectName) def __build_server_mbean_list(self, value, wlst_value): """ Construct the server MBean list. :param value: the value :param wlst_value: the existing value from WLST :return: the Java array of MBeans ObjectNames :raises BundleAwareException of the specified type: if an error occurs """ server_names = TypeUtils.convertToType(List, value) # type: list of str server_names = self.__merge_existing_items(server_names, wlst_value) name_list = [] for server_name in server_names: mbean = self.__find_in_location(LocationContext(), SERVER, server_name, required=True) name_list.append(mbean.getObjectName()) return jarray.array(name_list, ObjectName) def __build_virtual_target_mbean_list(self, target_value, wlst_value): """ Construct the virtual target MBean list. :param target_value: the target value :param wlst_value: the existing value from WLST :return: for offline, a list of MBeans; for online, a jarray of MBean ObjectNames :raises BundleAwareException of the specified type: if an error occurs """ target_names = TypeUtils.convertToType(List, target_value) # type: list of str target_names = self.__merge_existing_items(target_names, wlst_value) if self.__wlst_mode == WlstModes.ONLINE: name_list = [] for target_name in target_names: target_mbean = self.__find_in_location(LocationContext(), VIRTUAL_TARGET, target_name, required=True) name_list.append(target_mbean.getObjectName()) return jarray.array(name_list, ObjectName) else: mbean_list = [] for target_name in target_names: target_mbean = self.__find_in_location(LocationContext(), VIRTUAL_TARGET, target_name, required=True) mbean_list.append(target_mbean) return mbean_list def __find_target(self, target_name, location, include_jms=False): """ Find a target by name. :param target_name: the target name :param include_jms: whether or not to include JMS in the search, the default is False :return: the MBean for the target :raises BundleAwareException of the specified type: if an error occurs """ method_name = '__find_target' domain_location = self.__get_domain_location(location) for type_name in self.__target_type_names: mbean = self.__find_in_location(domain_location, type_name, target_name) if mbean is not None: return mbean if include_jms: mbean = self.__find_in_resource_group_or_domain(location, JMS_SERVER, target_name) if mbean is not None: return mbean ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19200', target_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex def __find_jms_destination_mbean(self, location, destination_name): """ Find the destination with the specified name and return its WLST mbean. :param location: the WLST location of the attribute :param destination_name: the name of the destination to find :return: the mbean for the destination :raises BundleAwareException of the specified type: if destination is not found """ method_name = '__find_jms_destination_mbean' resource_location = self.__get_parent_location(location, JMS_RESOURCE) for type_name in self.__destination_type_names: mbean = self.__find_in_location(resource_location, type_name, destination_name) if mbean is not None: return mbean _resource_type, resource_name = self.__alias_helper.get_model_type_and_name(resource_location) ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19201', destination_name, resource_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex def __find_persistent_store(self, location, store_name): """ Find the persistent store with the specified name and return its WLST mbean. :param location: the WLST location of the attribute :param store_name: the name of the store to find :return: the mbean for the store :raises BundleAwareException of the specified type: if store is not found """ method_name = '__find_persistent_store' for type_name in self.__persistent_store_type_names: mbean = self.__find_in_resource_group_or_domain(location, type_name, store_name) if mbean is not None: return mbean ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19202', PERSISTENT_STORE, store_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex def __find_saf_destination_mbean(self, location, destination_name): """ Find the SAF destination with the specified name and return its WLST mbean. :param location: the WLST location of the attribute :param destination_name: the name of the SAF destination to find :return: the mbean for the SAF destination :raises BundleAwareException of the specified type: if SAF destination is not found """ method_name = '__find_saf_destination_mbean' resource_location = self.__get_parent_location(location, JMS_RESOURCE) destination_location = LocationContext(resource_location).append_location(SAF_IMPORTED_DESTINATION) existing_sets = self.__get_existing_object_list(destination_location) token_name = self.__alias_helper.get_name_token(destination_location) for set_name in existing_sets: if token_name is not None: destination_location.add_name_token(token_name, set_name) for type_name in self.__saf_destination_type_names: mbean = self.__find_in_location(destination_location, type_name, destination_name) if mbean is not None: return mbean _resource_type, resource_name = self.__alias_helper.get_model_type_and_name(resource_location) ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19203', destination_name, resource_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex def __find_wldf_action(self, watch_location, action_name): """ Find the WLDF action with the specified name and return its WLST mbean. :param watch_location: the WLST location of the watch notification :param action_name: the name of the action to find :return: the mbean for the action :raises BundleAwareException of the specified type: if action is not found """ method_name = '__find_wldf_action' for type_name in self.__watch_action_types: mbean = self.__find_in_location(watch_location, type_name, action_name) if mbean is not None: return mbean ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19202', WATCH_NOTIFICATION, action_name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex def __find_in_resource_group_or_domain(self, location, element_type, name, required=False): """ Find the element with the specified name and type and return its WLST mbean. If the specified location is in a resource group, search only that resource group. :param location: the WLST location of the attribute :param name: the name of the element to find :param required: indicates exception should be thrown if not found :return: the mbean for the destination :raises BundleAwareException of the specified type: if element is not found, and required is True """ method_name = '__find_in_resource_group_or_domain' in_resource_group = RESOURCE_GROUP in location.get_model_folders() if in_resource_group: resource_group_location = self.__get_parent_location(location, RESOURCE_GROUP) mbean = self.__find_in_location(resource_group_location, element_type, name) if mbean is None: template_id = self.__wlst_helper.get("ResourceGroupTemplate") domain_location = self.__get_domain_location(location) mbean = self.__find_in_location(domain_location, RESOURCE_GROUP_TEMPLATE, template_id) else: location = self.__get_domain_location(location) mbean = self.__find_in_location(location, element_type, name) if required and (mbean is None): ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19202', element_type, name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex return mbean def __find_in_location(self, location, element_type, name, required=False): """ Find the element with the specified name and type and return its WLST mbean. :param location: the WLST location of the attribute :param element_type: the thype of the element to be found :param name: the name of the element to find :param required: indicates exception should be thrown if not found :return: the mbean for the destination :raises BundleAwareException of the specified type: if element is not found, and required is True """ method_name = '__find_in_location' location = LocationContext(location).append_location(element_type) if self.__alias_helper.get_wlst_mbean_type(location) is not None: existing_names = self.__get_existing_object_list(location) if name in existing_names: location_type, location_name = self.__alias_helper.get_model_type_and_name(location) self.__logger.fine('WLSDPLY-19204', element_type, name, location_type, location_name, class_name=self._class_name, method_name=method_name) token = self.__alias_helper.get_name_token(location) location.add_name_token(token, name) path = self.__alias_helper.get_wlst_attributes_path(location) return self.__wlst_helper.get_mbean_for_wlst_path(path) if required: ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19202', element_type, name) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex return None def __get_domain_location(self, location): """ Returns a copy of the specified location with all folders removed, but tokens intact. :param location: the location to be examined :return: the domain location """ _method_name = '__get_domain_location' self.__logger.entering(str(location), class_name=self._class_name, method_name=_method_name) location = LocationContext(location) while len(location.get_model_folders()) > 0: location.pop_location() return location def __get_parent_location(self, location, folder_name): """ Searches the specified location for the specified folder name, and returns the corresponding location. :param location: the location to be examined :param folder_name: the folder name to find :return: the parent location :raises BundleAwareException of the specified type: if the folder is not found in the location folders list """ method_name = '__get_parent_location' try: location = LocationContext(location) resource_index = location.get_model_folders().index(folder_name) while len(location.get_model_folders()) > resource_index + 1: location.pop_location() except: # index throws a ValueError if the item is not in the list... ex = exception_helper.create_exception(self.__exception_type, 'WLSDPLY-19205', folder_name, str(location)) self.__logger.throwing(class_name=self._class_name, method_name=method_name, error=ex) raise ex return location def __get_existing_object_list(self, location): """ Convenience method to get the existing object list by location's list path :param location: the location :return: the list of existing names :raises BundleAwareException of the specified type: if an error occurs """ _method_name = '__get_existing_object_list' self.__logger.entering(str(location), class_name=self._class_name, method_name=_method_name) list_path = self.__alias_helper.get_wlst_list_path(location) existing_names = self.__wlst_helper.get_existing_object_list(list_path) self.__logger.exiting(class_name=self._class_name, method_name=_method_name, result=existing_names) return existing_names # # methods for merging existing values # def __merge_existing_items(self, items, existing_value): """ Merge the specified items with the items represented by existing value, and return the result. :param items: the attribute name :param existing_value: the value representing the existing items (may be a string or list) :return: the merged list of items :raises BundleAwareException of the specified type: if the WLDF Action/Notification is not found """ _method_name = '__merge_existing_items' self.__logger.entering(str(items), str(existing_value), class_name=self._class_name, method_name=_method_name) existing_items = TypeUtils.convertToType(List, existing_value) # type: list of str no_existing_items = (existing_items is None) or (len(existing_items) == 0) if no_existing_items: result = items else: result = list(Set(items).union(Set(existing_items))) return result
class Deployer(object): """ The base class for deployers. Maintains model, model context, WLST mode, etc. Has common methods for deployers. """ _class_name = "Deployer" _mbean_interface = Class.forName('weblogic.management.configuration.ConfigurationMBean') _object_name_class = Class.forName('javax.management.ObjectName') _list_interface = Class.forName('java.util.List') def __init__(self, model, model_context, aliases, wlst_mode=WlstModes.OFFLINE): self.name = self._class_name self.model = model self.wlst_mode = wlst_mode self.model_context = model_context self.aliases = aliases self.logger = PlatformLogger('wlsdeploy.deploy') self.alias_helper = AliasHelper(aliases, self.logger, ExceptionType.DEPLOY) self.wls_helper = WebLogicHelper(self.logger) self.wlst_helper = WlstHelper(self.logger, ExceptionType.DEPLOY) self.attribute_setter = AttributeSetter(self.aliases, self.logger, ExceptionType.DEPLOY, wlst_mode=wlst_mode) self.archive_helper = None 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.model_context.get_domain_home(), self.logger, exception_helper.ExceptionType.DEPLOY) return def _add_named_elements(self, type_name, model_nodes, location): """ Add each named element from the specified nodes in WLST and set its attributes. Sub-folders are processed in a generic manner if present. It is assumed that there are no attributes or sub-folders with special processing. :param type_name: the type name of the child nodes :param model_nodes: the child nodes of a model element :param location: the location where elements should be added """ _method_name = '_add_named_elements' if len(model_nodes) == 0: return parent_type, parent_name = self.get_location_type_and_name(location) location = LocationContext(location).append_location(type_name) if not self._check_location(location): return deployer_utils.check_flattened_folder(location, self.alias_helper) existing_names = deployer_utils.get_existing_object_list(location, self.alias_helper) token = self.alias_helper.get_name_token(location) for name in model_nodes: is_add = name not in existing_names log_helper.log_updating_named_folder(type_name, name, parent_type, parent_name, is_add, self._class_name, _method_name) if token is not None: location.add_name_token(token, name) deployer_utils.create_and_cd(location, existing_names, self.alias_helper) child_nodes = dictionary_utils.get_dictionary_element(model_nodes, name) self._set_attributes_and_add_subfolders(location, child_nodes) return def _add_subfolders(self, model_nodes, location, excludes=None): """ Add each model sub-folder from the specified nodes and set its attributes. :param model_nodes: the child nodes of a model element :param location: the location where sub-folders should be added :param excludes: optional list of sub-folder names to be excluded from processing """ location = LocationContext(location) model_subfolder_names = self.alias_helper.get_model_subfolder_names(location) for subfolder in model_nodes: key_excluded = (excludes is not None) and (subfolder in excludes) if subfolder in model_subfolder_names and not key_excluded: subfolder_nodes = model_nodes[subfolder] if len(subfolder_nodes) != 0: sub_location = LocationContext(location).append_location(subfolder) if self.alias_helper.supports_multiple_mbean_instances(sub_location): self._add_named_elements(subfolder, subfolder_nodes, location) else: self._add_model_elements(subfolder, subfolder_nodes, location) return def _add_model_elements(self, type_name, model_nodes, location): """ Add each model element from the specified nodes at the specified location and set its attributes. :param model_nodes: the child nodes of a model element :param location: the location where sub-folders should be added :param type_name: the name of the model folder to add """ _method_name = '_add_model_elements' parent_type, parent_name = self.get_location_type_and_name(location) location = LocationContext(location).append_location(type_name) if not self._check_location(location): return deployer_utils.check_flattened_folder(location, self.alias_helper) existing_subfolder_names = deployer_utils.get_existing_object_list(location, self.alias_helper) mbean_name = deployer_utils.get_mbean_name(location, existing_subfolder_names, self.alias_helper) is_add = mbean_name not in existing_subfolder_names log_helper.log_updating_folder(type_name, parent_type, parent_name, is_add, self._class_name, _method_name) deployer_utils.create_and_cd(location, existing_subfolder_names, self.alias_helper) self._set_attributes_and_add_subfolders(location, model_nodes) return def _set_attributes_and_add_subfolders(self, location, model_nodes): """ Set the attributes and add sub-folders for the specified location. This method can be overridden for finer control of the ordering :param location: the location of the attributes and sub-folders :param model_nodes: a map of model nodes including attributes and sub-folders :raise: DeployException: if an error condition is encountered """ self.set_attributes(location, model_nodes) self._add_subfolders(model_nodes, location) return def set_attributes(self, location, model_nodes, excludes=None): """ Set all the attributes in the model_nodes list. Exclude items that are sub-folders. :param location: the location of the attributes to be set :param model_nodes: a map of model nodes with attributes to be set :param excludes: a list of items that should not be set :raise: DeployException: if an error condition is encountered """ _method_name = 'set_attributes' attribute_names = self.alias_helper.get_model_attribute_names(location) uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names(location) restart_attribute_names = self.alias_helper.get_model_restart_required_attribute_names(location) merge_attribute_names = self.alias_helper.get_model_merge_required_attribute_names(location) lsa_required_attribute_names = self.aliases.get_model_lsa_required_attribute_names(location) set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types(location) for key in model_nodes: key_excluded = (excludes is not None) and (key in excludes) if key in attribute_names and not key_excluded: value = model_nodes[key] if key in uses_path_tokens_attribute_names: self._extract_from_archive_if_needed(location, key, value) wlst_merge_value = None if key in merge_attribute_names: wlst_merge_value = self._get_existing_wlst_value(location, key, lsa_required_attribute_names) if not self._skip_setting_attribute(key, value, wlst_merge_value, restart_attribute_names) and \ (not self.set_special_attribute(location, key, value, wlst_merge_value, set_method_map)): try: self.attribute_setter.set_attribute(location, key, value, wlst_merge_value) except PyWLSTException, pwe: loc_type, loc_name = self.get_location_type_and_name(location) ex = exception_helper.create_deploy_exception('WLSDPLY-09200', key, loc_type, loc_name, pwe.getLocalizedMessage(), error=pwe) self.logger.throwing(ex, class_name=self._class_name, method_name=_method_name) raise ex return
class PrepareModel: """ This is the main driver for the caller. It compares two model files whether they are json or yaml format. """ def __init__(self, model_files, model_context, logger, output_dir=None): self.model_files = model_files self.output_dir = output_dir self.model_context = model_context self._aliases = Aliases(model_context=model_context, wlst_mode=WlstModes.OFFLINE) self._alias_helper = AliasHelper(self._aliases, logger, ExceptionType.COMPARE) self._logger = logger self._name_tokens_location = LocationContext() self._name_tokens_location.add_name_token('DOMAIN', "testdomain") self.current_dict = None self.cache = OrderedDict() self.secrets_to_generate = sets.Set() def __walk_model_section(self, model_section_key, model_dict, valid_section_folders): _method_name = '__validate_model_section' if model_section_key not in model_dict.keys(): return # only specific top-level sections have attributes attribute_location = self._alias_helper.get_model_section_attribute_location(model_section_key) valid_attr_infos = [] path_tokens_attr_keys = [] if attribute_location is not None: valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(attribute_location) path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(attribute_location) model_section_dict = model_dict[model_section_key] for section_dict_key, section_dict_value in model_section_dict.iteritems(): # section_dict_key is either the name of a folder in the # section, or the name of an attribute in the section. validation_location = LocationContext() model_folder_path = model_section_key + ":/" if section_dict_key in valid_attr_infos: # section_dict_key is the name of an attribute in the section self.__walk_attribute(section_dict_key, section_dict_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, attribute_location) elif section_dict_key in valid_section_folders: # section_dict_key is a folder under the model section # Append section_dict_key to location context validation_location.append_location(section_dict_key) # Call self.__validate_section_folder() passing in section_dict_value as the model_node to process self.__walk_section_folder(section_dict_value, validation_location) def __walk_section_folder(self, model_node, validation_location): _method_name = '__validate_section_folder' model_folder_path = self._alias_helper.get_model_folder_path(validation_location) if self._alias_helper.supports_multiple_mbean_instances(validation_location): for name in model_node: expanded_name = name new_location = LocationContext(validation_location) name_token = self._alias_helper.get_name_token(new_location) if name_token is not None: new_location.add_name_token(name_token, expanded_name) value_dict = model_node[name] self.__walk_model_node(value_dict, new_location) elif self._alias_helper.requires_artificial_type_subfolder_handling(validation_location): for name in model_node: expanded_name = name new_location = LocationContext(validation_location) name_token = self._alias_helper.get_name_token(new_location) if name_token is not None: new_location.add_name_token(name_token, expanded_name) value_dict = model_node[name] self.__walk_model_node(value_dict, new_location) else: name_token = self._alias_helper.get_name_token(validation_location) if name_token is not None: name = self._name_tokens_location.get_name_for_token(name_token) if name is None: name = '%s-0' % name_token validation_location.add_name_token(name_token, name) self.__walk_model_node(model_node, validation_location) def __walk_model_node(self, model_node, validation_location): _method_name = '__process_model_node' valid_folder_keys = self._alias_helper.get_model_subfolder_names(validation_location) valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(validation_location) model_folder_path = self._alias_helper.get_model_folder_path(validation_location) for key, value in model_node.iteritems(): if key in valid_folder_keys: new_location = LocationContext(validation_location).append_location(key) if self._alias_helper.is_artificial_type_folder(new_location): # key is an ARTIFICIAL_TYPE folder valid_attr_infos = self._alias_helper.get_model_attribute_names_and_types(new_location) self.__walk_attributes(value, valid_attr_infos, new_location) else: self.__walk_section_folder(value, new_location) elif key in valid_attr_infos: # aliases.get_model_attribute_names_and_types(location) filters out # attributes that ARE NOT valid in the wlst_version being used, so if # we're in this section of code we know key is a bonafide "valid" attribute valid_data_type = valid_attr_infos[key] if valid_data_type in ['properties']: valid_prop_infos = {} properties = validation_utils.get_properties(value) self.__walk_properties(properties, valid_prop_infos, validation_location) else: path_tokens_attr_keys = \ self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location) self.__walk_attribute(key, value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location) def __walk_attributes(self, attributes_dict, valid_attr_infos, validation_location): _method_name = '__validate_attributes' path_tokens_attr_keys = self._alias_helper.get_model_uses_path_tokens_attribute_names(validation_location) model_folder_path = self._alias_helper.get_model_folder_path(validation_location) for attribute_name, attribute_value in attributes_dict.iteritems(): self.__walk_attribute(attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location) def __walk_attribute(self, attribute_name, attribute_value, valid_attr_infos, path_tokens_attr_keys, model_folder_path, validation_location): _method_name = '__validate_attribute' if attribute_name in valid_attr_infos: expected_data_type = valid_attr_infos[attribute_name] if expected_data_type == 'password': self.__substitute_password_with_token(model_folder_path, attribute_name, validation_location) self._logger.exiting(class_name=_class_name, method_name=_method_name) def __walk_properties(self, properties_dict, valid_prop_infos, validation_location): _method_name = '__walk_properties' for property_name, property_value in properties_dict.iteritems(): valid_prop_infos[property_name] = validation_utils.get_python_data_type(property_value) self.__walk_property(property_name, property_value, valid_prop_infos, validation_location) def __walk_property(self, property_name, property_value, valid_prop_infos, model_folder_path, validation_location): _method_name = '__walk_property' self._logger.entering(property_name, property_value, str(valid_prop_infos), model_folder_path, class_name=_class_name, method_name=_method_name) if property_name in valid_prop_infos: expected_data_type = valid_prop_infos[property_name] if expected_data_type == 'password': self.__substitute_password_with_token(model_folder_path, property_name, validation_location) def __format_variable_name(self, location, attribute): _method_name = '__format_variable_name' def __traverse_location(iterate_location, name_list, last_folder=None, last_folder_short=None): current_folder = iterate_location.get_current_model_folder() if current_folder == model_constants.DOMAIN: if last_folder is not None: # If a short name is not defined for the top level folder, use the full name if len(last_folder_short) == 0: last_folder_short = last_folder name_list.insert(0, last_folder_short) else: current_folder = iterate_location.get_current_model_folder() short_folder = self._aliases.get_folder_short_name(iterate_location) if last_folder_short is not None: name_list.insert(0, last_folder_short) try: if not self._aliases.is_artificial_type_folder(location) and \ (self._aliases.supports_multiple_mbean_instances(iterate_location) or self._aliases.is_custom_folder_allowed(iterate_location)): name_token = self._aliases.get_name_token(iterate_location) name = iterate_location.get_name_for_token(name_token) name_list.insert(0, name) iterate_location.remove_name_token(name_token) iterate_location.pop_location() except AliasException, ae: self._logger.warning('WLSDPLY-19531', str(location), attribute, ae.getLocalizedMessage(), class_name=_class_name, method_name=_method_name) __traverse_location(iterate_location, name_list, current_folder, short_folder) return name_list short_list = __traverse_location(LocationContext(location), list()) short_name = '' for node in short_list: if node is not None and len(node) > 0: short_name += node + '.' short_name += attribute _fake_name_replacement = re.compile('.fakename') _white_space_replacement = re.compile('\s') short_name = short_name.replace('/', '.') short_name = _white_space_replacement.sub('-', short_name) short_name = _fake_name_replacement.sub('', short_name) return short_name
class Creator(object): """ The base class used by the DomainCreator. """ __class_name = 'Creator' 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, 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, exception_type) # Must be initialized by the subclass since only it has # the knowledge required to compute the domain name. self.archive_helper = None self.files_to_extract_from_archive = list() return def _create_named_mbeans(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified type of MBeans that support multiple instances in the specified location. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBeans :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 """ _method_name = '_create_named_mbeans' self.logger.entering(type_name, str(base_location), log_created, class_name=self.__class_name, method_name=_method_name) if model_nodes is None or len( model_nodes) == 0 or not self._is_type_valid( base_location, type_name): return location = LocationContext(base_location).append_location(type_name) self._process_flattened_folder(location) token_name = self.alias_helper.get_name_token(location) create_path = self.alias_helper.get_wlst_create_path(location) list_path = self.alias_helper.get_wlst_list_path(location) existing_folder_names = self._get_existing_folders(list_path) for model_name in model_nodes: name = self.wlst_helper.get_quoted_name_for_wlst(model_name) if token_name is not None: location.add_name_token(token_name, name) wlst_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name( location) if wlst_name not in existing_folder_names: if log_created: self.logger.info('WLSDPLY-12100', type_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12100', type_name, name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.create_and_cd(self.alias_helper, wlst_type, wlst_name, location, create_path) else: if log_created: self.logger.info('WLSDPLY-12101', type_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12101', type_name, name, class_name=self.__class_name, method_name=_method_name) attribute_path = self.alias_helper.get_wlst_attributes_path( location) self.wlst_helper.cd(attribute_path) child_nodes = dictionary_utils.get_dictionary_element( model_nodes, name) self.logger.finest( 'WLSDPLY-12111', self.alias_helper.get_model_folder_path(location), self.wlst_helper.get_pwd(), class_name=self.__class_name, method_name=_method_name) self._set_attributes(location, child_nodes) self._create_subfolders(location, child_nodes) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _create_mbean(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified type of MBean that support a single instance in the specified location. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBean :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 """ _method_name = '_create_mbean' self.logger.entering(type_name, str(base_location), log_created, class_name=self.__class_name, method_name=_method_name) if model_nodes is None or len( model_nodes) == 0 or not self._is_type_valid( base_location, type_name): return location = LocationContext(base_location).append_location(type_name) result, message = self.alias_helper.is_version_valid_location(location) if result == ValidationCodes.VERSION_INVALID: self.logger.warning('WLSDPLY-12123', message, class_name=self.__class_name, method_name=_method_name) return create_path = self.alias_helper.get_wlst_create_path(location) existing_folder_names = self._get_existing_folders(create_path) mbean_type, mbean_name = self.alias_helper.get_wlst_mbean_type_and_name( location) token_name = self.alias_helper.get_name_token(location) if token_name is not None: location.add_name_token(token_name, mbean_name) self._process_flattened_folder(location) if mbean_type not in existing_folder_names: if log_created: self.logger.info('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.create_and_cd(self.alias_helper, mbean_type, mbean_name, location, create_path) else: if log_created: self.logger.info('WLSDPLY-20013', type_name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12102', type_name, class_name=self.__class_name, method_name=_method_name) attribute_path = self.alias_helper.get_wlst_attributes_path( location) self.wlst_helper.cd(attribute_path) self.logger.finest('WLSDPLY-12111', self.alias_helper.get_model_folder_path(location), self.wlst_helper.get_pwd(), class_name=self.__class_name, method_name=_method_name) self._set_attributes(location, model_nodes) self._create_subfolders(location, model_nodes) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _create_security_provider_mbeans(self, type_name, model_nodes, base_location, log_created=False): """ Create the specified security provider MBean types that support multiple instances but use an artificial type subfolder in the specified location. :param type_name: the model folder type :param model_nodes: the model dictionary of the specified model folder type :param base_location: the base location object to use to create the MBeans :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 """ _method_name = '_create_security_provider_mbeans' self.logger.entering(type_name, str(base_location), log_created, class_name=self.__class_name, method_name=_method_name) if model_nodes is None or len( model_nodes) == 0 or not self._is_type_valid( base_location, type_name): return location = LocationContext(base_location).append_location(type_name) self._process_flattened_folder(location) token_name = self.alias_helper.get_name_token(location) create_path = self.alias_helper.get_wlst_create_path(location) list_path = self.alias_helper.get_wlst_list_path(location) existing_folder_names = self._get_existing_folders(list_path) for model_name in model_nodes: prov_location = LocationContext(location) name = self.wlst_helper.get_quoted_name_for_wlst(model_name) if token_name is not None: prov_location.add_name_token(token_name, name) wlst_base_provider_type, wlst_name = self.alias_helper.get_wlst_mbean_type_and_name( prov_location) model_node = model_nodes[model_name] if model_node is not None: if len(model_node) == 1: model_type_subfolder_name = list(model_node.keys())[0] prov_location.append_location(model_type_subfolder_name) wlst_type = self.alias_helper.get_wlst_mbean_type( prov_location) else: ex = exception_helper.create_create_exception( 'WLSDPLY-12117', type_name, model_name, len(model_node)) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex else: # The node is empty so nothing to do...move to the next named node. continue if wlst_name not in existing_folder_names: if log_created: self.logger.info('WLSDPLY-12118', type_name, model_type_subfolder_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12118', type_name, model_type_subfolder_name, name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.cd(create_path) self.wlst_helper.create(wlst_name, wlst_type, wlst_base_provider_type) else: if log_created: self.logger.info('WLSDPLY-12119', type_name, model_type_subfolder_name, name, class_name=self.__class_name, method_name=_method_name) else: self.logger.fine('WLSDPLY-12119', type_name, model_type_subfolder_name, name, class_name=self.__class_name, method_name=_method_name) attribute_path = self.alias_helper.get_wlst_attributes_path( prov_location) self.wlst_helper.cd(attribute_path) child_nodes = dictionary_utils.get_dictionary_element( model_node, model_type_subfolder_name) self.logger.finest( 'WLSDPLY-12111', self.alias_helper.get_model_folder_path(prov_location), self.wlst_helper.get_pwd(), class_name=self.__class_name, method_name=_method_name) self._set_attributes(prov_location, child_nodes) self._create_subfolders(prov_location, child_nodes) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _set_attributes(self, location, model_nodes): """ Set the attributes for the MBean at the specified location. :param location: the location :param model_nodes: the model dictionary :raises: CreateException: if an error occurs """ _method_name = '_set_attributes' model_attribute_names = self.alias_helper.get_model_attribute_names_and_types( location) password_attribute_names = self.alias_helper.get_model_password_type_attribute_names( location) set_method_map = self.alias_helper.get_model_mbean_set_method_attribute_names_and_types( location) uses_path_tokens_attribute_names = self.alias_helper.get_model_uses_path_tokens_attribute_names( location) model_folder_path = self.alias_helper.get_model_folder_path(location) pwd = self.wlst_helper.get_pwd() for key, value in model_nodes.iteritems(): if key in model_attribute_names: if key in set_method_map: self.logger.finest('WLSDPLY-12112', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_mbean_attribute(location, key, value, set_method_map) elif key in password_attribute_names: self.logger.finest('WLSDPLY-12113', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_attribute(location, key, value, uses_path_tokens_attribute_names, masked=True) else: self.logger.finest('WLSDPLY-12113', key, pwd, model_folder_path, class_name=self.__class_name, method_name=_method_name) self._set_attribute(location, key, value, uses_path_tokens_attribute_names) return def _set_mbean_attribute(self, location, model_key, model_value, set_method_map): """ Set the attributes for the MBean that require an MBean value to set at the specified location. :param location: the location :param model_key: the model attribute name :param model_value: the model attribute value :param set_method_map: the set method map that maps the attribute names requiring MBean values to the attribute setter method name :raises: CreateException: if an error occurs """ _method_name = '_set_mbean_attribute' set_method_info = dictionary_utils.get_dictionary_element( set_method_map, model_key) set_method_name = dictionary_utils.get_element(set_method_info, 'set_method') if set_method_name is not None: try: self.logger.finest('WLSDPLY-12114', model_key, model_value, set_method_name, class_name=self.__class_name, method_name=_method_name) set_method = getattr(self.attribute_setter, set_method_name) set_method(location, model_key, model_value, None) except AttributeError, ae: ex = exception_helper.create_create_exception( 'WLSDPLY-12104', set_method_name, model_key, self.alias_helper.get_model_folder_path(location), error=ae) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex else:
class OdlDeployer(object): """ Handle the ODL validation and configuration. """ __class_name = 'OdlHelper' def __init__(self, model, model_context, aliases, wlst_mode): self.model = model self.model_context = model_context self.logger = PlatformLogger('wlsdeploy.deploy') self.alias_helper = AliasHelper(aliases, self.logger, ExceptionType.DEPLOY) self.wlst_mode = wlst_mode def configure_odl(self, parent_dict, parent_location): """ Apply the ODL configuration section of the model, if present. :param parent_dict: the model dictionary that may contains ODL configuration :param parent_location: the alias location of the parent dictionary (used for logging paths) """ _method_name = 'configure_odl' self.logger.entering(class_name=self.__class_name, method_name=_method_name) odl_info = dictionary_utils.get_dictionary_element(parent_dict, ODL_CONFIGURATION) if len(odl_info): typedef = self.model_context.get_domain_typedef() if not (typedef.is_jrf_domain_type() or typedef.is_restricted_jrf_domain_type()): self.logger.info('WLSDPLY-19709', class_name=self.__class_name, method_name=_method_name) elif self.wlst_mode == WlstModes.ONLINE: self.logger.info('WLSDPLY-19700', class_name=self.__class_name, method_name=_method_name) else: for config in odl_info: self._update_config(config, odl_info[config], parent_location) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _update_config(self, config_name, config_dictionary, parent_location): _method_name = '_update_config' config_location = LocationContext(parent_location).append_location(ODL_CONFIGURATION) token = self.alias_helper.get_name_token(config_location) config_location.add_name_token(token, config_name) servers = dictionary_utils.get_element(config_dictionary, _SERVERS) if servers is not None: servers_list = alias_utils.convert_to_type('list', servers, delimiter=MODEL_LIST_DELIMITER) for server in servers_list: self.logger.info('WLSDPLY-19708', ODL_CONFIGURATION, config_name, server, class_name=self.__class_name, method_name=_method_name) self._update_server(server, config_dictionary, config_location) def _update_server(self, name, dictionary, config_location): _method_name = '_update_server' # these imports are local, since they are only present in JRF environments. # this method is only called after that check has been made. from oracle.core.ojdl.weblogic.ODLConfiguration import CONFIG_DIR from oracle.core.ojdl.weblogic.ODLConfiguration import CONFIG_FILE from oracle.core.ojdl.logging.config import LoggingConfigurationDocument config_dir = File(self.model_context.get_domain_home(), CONFIG_DIR) server_dir = File(config_dir, name) config_file = File(server_dir, CONFIG_FILE) try: FileUtils.validateWritableFile(config_file.getPath()) document = LoggingConfigurationDocument(FileInputStream(config_file)) # configure AddJvmNumber add_jvm_number = dictionary_utils.get_element(dictionary, _ADD_JVM_NUMBER) if add_jvm_number is not None: document.setAddJvmNumber(alias_utils.convert_boolean(add_jvm_number)) # configure HandlerDefaults handler_defaults = dictionary_utils.get_dictionary_element(dictionary, _HANDLER_DEFAULTS) if handler_defaults is not None: for key in handler_defaults: value = handler_defaults[key] document.setHandlerDefault(key, _get_property_text(value)) # configure Handlers # do these before loggers, in case new handlers are assigned to loggers existing_handler_names = document.getHandlerNames() handlers = dictionary_utils.get_dictionary_element(dictionary, _HANDLER) if handlers is not None: for handler_name in handlers: handler = handlers[handler_name] self._configure_handler(handler_name, handler, document, existing_handler_names, config_location) # configure Loggers existing_logger_names = document.getLoggerNames() loggers = dictionary_utils.get_dictionary_element(dictionary, _LOGGER) if loggers is not None: for logger_name in loggers: logger = loggers[logger_name] self._configure_logger(logger_name, logger, document, existing_logger_names, config_location) document.writeDocument(FileOutputStream(config_file)) except (ParserConfigurationException, SAXException, IOException, IllegalArgumentException), ex: self.logger.severe('WLSDPLY-19707', name, ex.getLocalizedMessage(), class_name=self.__class_name, method_name=_method_name) return
class TopologyHelper(object): """ Shared code for topology section of model. Domain create and update use this code. """ __class_name = 'TopologyHelper' def __init__(self, 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._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)
class UsagePrinter(object): """ Class for printing the recognized metadata for a model file, to STDOUT. This output is referred to as the usage. """ ControlOptions = Enum(['RECURSIVE', 'FOLDERS_ONLY', 'ATTRIBUTES_ONLY']) def __init__(self, aliases, logger): """ :param aliases: A reference to an Aliases class instance :param logger: A reference to the platform logger to write to, if a log entry needs to be made """ self._logger = logger self._aliases = aliases self._alias_helper = AliasHelper(self._aliases, self._logger, ExceptionType.VALIDATE) def print_model_path_usage(self, model_path, control_option): """ Prints out the usage information for a given '''model_path'''. '''model_path''' needs to be specified using the following pattern: <model_section>[:/<section_folder>[/<section_subfolder>|...]] Examples: 'domainInfo', 'domainInfo:' or 'domainInfo:/' (all 3 are rquivalent) 'topology:/Server' 'resources:/JDBCSystemResource/JdbcResource/JDBCDriverParams' 'appDeployments:/Application' :param model_path: A forward-slash delimited string contain the model path to print usage for :param control_option: A command-line switch that controls what is output to STDOUT :return: :raises ValidationException: if an AliasException is raised during an invocation of an aliases API call. """ model_path_tokens = self.__create_model_path_tokens(model_path) top_level_key = model_path_tokens[0] if control_option == self.ControlOptions.RECURSIVE: print validation_utils.format_message('WLSDPLY-05100') elif control_option == self.ControlOptions.FOLDERS_ONLY: print validation_utils.format_message('WLSDPLY-05101') elif control_option == self.ControlOptions.ATTRIBUTES_ONLY: print validation_utils.format_message('WLSDPLY-05102') validation_utils.print_blank_lines() section_name = model_path_tokens[0] valid_section_folder_keys = self._aliases.get_model_section_top_level_folder_names( section_name) if len(model_path_tokens) == 1: self.__print_top_level_usage(top_level_key, valid_section_folder_keys, control_option) else: self.__print_model_section_usage(model_path_tokens, valid_section_folder_keys, control_option) return def __print_top_level_usage(self, top_level_key, valid_section_folder_keys, control_option): """ Prints out the usage for a section of a model, when just the section_name[:[/}} is provided :param top_level_key: The name of one of the model sections :param valid_section_folder_keys: Python list of the valid model section names :param control_option: A command-line switch that controls what is output to STDOUT :return: """ _method_name = '__print_top_level_usage' self._logger.finest('1 top_level_key={0}', top_level_key, class_name=_class_name, method_name=_method_name) location_path = '%s:' % top_level_key self._logger.finest('1 location_path={0}', location_path, class_name=_class_name, method_name=_method_name) model_section = validation_utils.format_message( 'WLSDPLY-05104', location_path) # Print 'Section: <model_section>' label and field validation_utils.print_indent(model_section, 0) validation_utils.print_blank_lines() validation_location = LocationContext() attributes_location = self._alias_helper.get_model_section_attribute_location( top_level_key) if attributes_location is not None: self.__print_attributes_usage(attributes_location, 1) if control_option == self.ControlOptions.FOLDERS_ONLY: validation_utils.print_indent( validation_utils.format_message('WLSDPLY-05105'), 1) valid_section_folder_keys.sort() for section_folder_key in valid_section_folder_keys: if control_option == self.ControlOptions.FOLDERS_ONLY: validation_utils.print_indent(section_folder_key, 2) elif control_option == self.ControlOptions.RECURSIVE: validation_location.append_location(section_folder_key) name_token = self._alias_helper.get_name_token( validation_location) if name_token is not None: validation_location.add_name_token( name_token, '%s-0' % section_folder_key) self._logger.finest('1 validation_location={0}', validation_location, class_name=_class_name, method_name=_method_name) location_path = '%s:%s' % ( top_level_key, validation_location.get_folder_path()) model_path = validation_utils.format_message( 'WLSDPLY-05103', location_path) validation_utils.print_blank_lines() validation_utils.print_indent(model_path, 0) validation_utils.print_blank_lines() self.__print_folders_usage(validation_location, control_option, 1) validation_location.pop_location() return def __print_model_section_usage(self, model_path_tokens, valid_section_folder_keys, control_option): """ Prints out the usage for a section of a model, when more than just the section_name[:[/}} is provided :param model_path_tokens: A Python list of path elements built from model path :param valid_section_folder_keys: A list of valid folder names for the model section the usage is being printed for :param control_option: A command-line switch that controls what is output to STDOUT :return: """ _method_name = '__print_model_section_usage' self._logger.finest('1 model_path_tokens={0}, control_option={1}', str(model_path_tokens), self.ControlOptions.from_value(control_option), class_name=_class_name, method_name=_method_name) self._logger.finest('1 valid_section_folder_keys={0}', str(valid_section_folder_keys), class_name=_class_name, method_name=_method_name) self.__validate_section_folder_path(model_path_tokens, valid_section_folder_keys) validation_location = LocationContext() model_path = validation_utils.format_message( 'WLSDPLY-05103', '%s:/%s' % (model_path_tokens[0], '/'.join(model_path_tokens[1:]))) # Print 'Path: <model_section>' header validation_utils.print_indent(model_path, 0) validation_utils.print_blank_lines() # Populate the location context using model_path_tokens[1:] for folder_key in model_path_tokens[1:]: validation_location.append_location(folder_key) name_token = self._alias_helper.get_name_token(validation_location) if name_token is not None: validation_location.add_name_token(name_token, '%s-0' % folder_key) self._logger.finest('2 validation_location={0}', validation_location, class_name=_class_name, method_name=_method_name) # Print the attributes associated with location context self.__print_attributes_usage(validation_location, 1) if control_option != self.ControlOptions.ATTRIBUTES_ONLY: # Print the folders associated with location context self.__print_folders_usage(validation_location, control_option, 1) self._logger.exiting(class_name=_class_name, method_name=_method_name) return def __print_folders_usage(self, validation_location, control_option, indent_level): """ Prints out the usage for the folders in a model location :param validation_location: An object containing data about the model location being worked on :param control_option: A command-line switch that controls what is output to STDOUT :param indent_level: The level to indent by, before printing output :return: """ _method_name = '__print_folders_usage' valid_subfolder_keys = self._alias_helper.get_model_subfolder_names( validation_location) self._logger.finest( '3 aliases.get_model_subfolder_names(validation_location) returned: {0}', str(valid_subfolder_keys), class_name=_class_name, method_name=_method_name) if not valid_subfolder_keys: return validation_utils.print_indent( validation_utils.format_message('WLSDPLY-05105'), indent_level) valid_subfolder_keys.sort() for key in valid_subfolder_keys: validation_location.append_location(key) name_token = self._alias_helper.get_name_token(validation_location) if name_token is not None: validation_location.add_name_token(name_token, '%s-0' % key) self._logger.finest('3 validation_location={0}', validation_location, class_name=_class_name, method_name=_method_name) validation_utils.print_indent(key, indent_level + 1) if control_option != self.ControlOptions.FOLDERS_ONLY: self.__print_attributes_usage(validation_location, indent_level + 2) if control_option == self.ControlOptions.RECURSIVE: # Call this __print_folders_usage() function recursively self.__print_folders_usage(validation_location, control_option, indent_level + 2) validation_location.pop_location() return def __print_attributes_usage(self, validation_location, indent_level): """ Prints out the usage for the attributes in a model location :param validation_location: An object containing data about the model location being worked on :param indent_level: The level to indent by, before printing output :return: """ _method_name = '__print_attributes_usage' attr_infos = self._alias_helper.get_model_attribute_names_and_types( validation_location) self._logger.finer('WLSDPLY-05012', str(validation_location), str(attr_infos), class_name=_class_name, method_name=_method_name) _print_attr_infos(attr_infos, indent_level) return def __create_model_path_tokens(self, model_path=''): """ Creates a Python list from the elements in the specified model_path. :param model_path: A forward-slash delimited string contain the model path to print usage for :return: """ _method_name = '__create_model_path_tokens' self._logger.entering(model_path, class_name=_class_name, method_name=_method_name) if model_path[-1:] != ':': m = MODEL_PATH_PATTERN.match(model_path) if m is None: ex = exception_helper.create_validate_exception( 'WLSDPLY-05106', model_path) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex self._logger.finest('m.group(1)={0}, m.group(3)={1}', str(m.group(1)), str(m.group(3)), class_name=_class_name, method_name=_method_name) # Replace any ':' in model_path with '', then split it on '/' into a list model_path_tokens = model_path.replace(':', '').split('/') # Remove any blank list items caused by the user entering # extraneous '/' characters. while '' in model_path_tokens: del model_path_tokens[model_path_tokens.index('')] recognized_top_level_keys = model.get_model_top_level_keys() self._logger.finest('recognized_top_level_keys={0}', str(recognized_top_level_keys), class_name=_class_name, method_name=_method_name) top_level_key = model_path_tokens[0] if top_level_key not in recognized_top_level_keys: ex = exception_helper.create_validate_exception( 'WLSDPLY-05107', top_level_key, '%s' % ', '.join(recognized_top_level_keys)) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex return model_path_tokens def __validate_section_folder_path(self, model_path_tokens, valid_section_folder_keys): """ Verifies that a model path element is in the specified valid_section_folder_keys list. :param model_path_tokens: A Python list of path elements built from model path :param valid_section_folder_keys: A Python list of folder names :return: """ _method_name = '__validate_section_folder_path' if model_path_tokens[1] not in valid_section_folder_keys: ex = exception_helper.create_validate_exception( 'WLSDPLY-05108', '%s:/' % model_path_tokens[0], '%s' % '/'.join(model_path_tokens[1:]), '%s' % ', '.join(valid_section_folder_keys)) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex return
class DomainResourceExtractor: """ Create a domain resource file for use with Kubernetes deployment. """ _class_name = "DomainResourceExtractor" # the name field keys corresponding to named model elements NAME_KEY_MAP = {CHANNELS: 'channelName', CLUSTERS: CLUSTER_NAME} def __init__(self, model, model_context, aliases, logger): self._model = model self._model_context = model_context self._aliases = AliasHelper(aliases, logger, ExceptionType.DEPLOY) self._logger = logger return def extract(self): """ Deploy resource model elements at the domain level, including multi-tenant elements. """ _method_name = 'extract' resource_file = self._model_context.get_domain_resource_file() self._logger.info("WLSDPLY-10000", resource_file, method_name=_method_name, class_name=self._class_name) # create the target file directory, if needed resource_dir = File(resource_file).getParentFile() if (not resource_dir.isDirectory()) and (not resource_dir.mkdirs()): mkdir_ex = exception_helper.create_deploy_exception( 'WLSDPLY-10001', resource_dir) raise mkdir_ex # build the resource file structure from the kubernetes section of the model resource_dict = self._create_domain_resource_dictionary() # revise the resource file structure with values from command line, and elsewhere in model self._update_resource_dictionary(resource_dict) # write the resource file structure to the output file writer = PythonToFile(resource_dict) writer.write_to_file(resource_file) return def _create_domain_resource_dictionary(self): """ Build the resource file structure from the kubernetes section of the model. :return: the resource file structure """ kubernetes_map = self._model.get_model_kubernetes() resource_dict = PyOrderedDict() attribute_location = self._aliases.get_model_section_attribute_location( KUBERNETES) top_attributes_map = self._aliases.get_model_attribute_names_and_types( attribute_location) top_folders = self._aliases.get_model_section_top_level_folder_names( KUBERNETES) self._process_fields(kubernetes_map, top_folders, top_attributes_map, LocationContext(), resource_dict) return resource_dict def _process_fields(self, model_dict, folder_names, attributes_map, location, target_dict): """ Transfer folders and attributes from the model dictionary to the target domain resource dictionary. For the top level, the folders and attributes are not derived directly from the location. :param model_dict: the source model dictionary :param folder_names: the names of the folders at this location :param attributes_map: the map of attribute names to types for this location :param location: the location used for alias processing :param target_dict: the target dictionary for the domain resource file. """ for key, model_value in model_dict.items(): if key in attributes_map.keys(): type_name = attributes_map[key] target_dict[key] = _get_target_value(model_value, type_name) elif key in folder_names: child_location = LocationContext(location).append_location(key) if self._aliases.supports_multiple_mbean_instances( child_location): target_dict[key] = self._build_dictionary_list( key, model_value, child_location) else: if key not in target_dict: target_dict[key] = PyOrderedDict() target_child_dict = target_dict[key] self._process_location_fields(model_value, child_location, target_child_dict) return def _process_location_fields(self, model_dict, location, target_dict): """ Transfer folders and attributes from the model dictionary to the target domain resource dictionary. Below the top level, the folders and attributes can be derived from the location. :param model_dict: the source model dictionary :param location: the location used for alias processing :param target_dict: the target dictionary for the domain resource file. """ attributes_map = self._aliases.get_model_attribute_names_and_types( location) folder_names = self._aliases.get_model_subfolder_names(location) self._process_fields(model_dict, folder_names, attributes_map, location, target_dict) return def _build_dictionary_list(self, model_key, name_dictionary, location): """ Build a dictionary list object based on the name dictionary and location. :param name_dictionary: a dictionary containing named levels :param location: the location used for alias resolution :return: """ child_list = DictionaryList() for name in name_dictionary: model_named_dict = name_dictionary[name] name_key = self._get_name_key(model_key) target_list_dict = PyOrderedDict() target_list_dict[name_key] = name self._process_location_fields(model_named_dict, location, target_list_dict) child_list.append(target_list_dict) return child_list def _get_name_key(self, key): """ Return the key to be used for the name in a dictionary list element. :param key: the folder key in the model :return: the name key """ key = dictionary_utils.get_element(self.NAME_KEY_MAP, key) if key is not None: return key return 'name' def _update_resource_dictionary(self, resource_dict): """ Revise the resource file structure with values from defaults, command line, and elsewhere in model :param resource_dict: the resource file dictionary """ _method_name = '_update_resource_dictionary' # add API version if not present if API_VERSION not in resource_dict: resource_dict[API_VERSION] = DEFAULT_API_VERSION # add kind if not present if KIND not in resource_dict: resource_dict[KIND] = DEFAULT_KIND # add a metadata section if not present, since we'll at least add name if METADATA not in resource_dict: resource_dict[METADATA] = PyOrderedDict() metadata_section = resource_dict[METADATA] # if metadata name not present, use the domain name from the model, or default if K_NAME not in metadata_section: domain_name = dictionary_utils.get_element( self._model.get_model_topology(), NAME) if domain_name is None: domain_name = DEFAULT_WLS_DOMAIN_NAME metadata_section[K_NAME] = domain_name # add a spec section if not present, since we'll at least add domain home if SPEC not in resource_dict: resource_dict[SPEC] = PyOrderedDict() spec_section = resource_dict[SPEC] # only set domain home if it is not present in spec section if DOMAIN_HOME not in spec_section: spec_section[DOMAIN_HOME] = self._model_context.get_domain_home() # only set image if it is not present in spec section if IMAGE not in spec_section: spec_section[IMAGE] = DEFAULT_IMAGE # imagePullSecrets is required unless imagePullPolicy is Never pull_secrets_required = True if IMAGE_PULL_POLICY in spec_section: policy = str(spec_section[IMAGE_PULL_POLICY]) pull_secrets_required = (policy != NEVER) # if imagePullSecrets required and not present, add a list with one FIX ME value if pull_secrets_required and (IMAGE_PULL_SECRETS not in spec_section): secrets_list = DictionaryList() secrets_list.append({'name': DEFAULT_IMAGE_PULL_SECRETS}) spec_section[IMAGE_PULL_SECRETS] = secrets_list # if webLogicCredentialsSecret not present, add it using the FIX ME value if WEBLOGIC_CREDENTIALS_SECRET not in spec_section: spec_section[ WEBLOGIC_CREDENTIALS_SECRET] = DEFAULT_WEBLOGIC_CREDENTIALS_SECRET # only update clusters if section is not present in spec section if CLUSTERS not in spec_section: topology = self._model.get_model_topology() model_clusters = dictionary_utils.get_dictionary_element( topology, CLUSTER) if len(model_clusters) > 0: cluster_list = DictionaryList() spec_section[CLUSTERS] = cluster_list for cluster_name, cluster_values in model_clusters.items(): server_count = self._get_server_count( cluster_name, cluster_values) cluster_dict = PyOrderedDict() cluster_dict[CLUSTER_NAME] = cluster_name cluster_dict[REPLICAS] = server_count self._logger.info("WLSDPLY-10002", cluster_name, server_count, method_name=_method_name, class_name=self._class_name) cluster_list.append(cluster_dict) return def _get_server_count(self, cluster_name, cluster_values): """ Determine the number of servers associated with a cluster. :param cluster_name: the name of the cluster :param cluster_values: a map of values for the cluster :return: the number of servers """ if DYNAMIC_SERVERS in cluster_values: # for dynamic clusters, return the value of DynamicClusterSize dynamic_servers_dict = cluster_values[DYNAMIC_SERVERS] cluster_size_value = dictionary_utils.get_element( dynamic_servers_dict, DYNAMIC_CLUSTER_SIZE) if cluster_size_value is not None: return alias_utils.convert_to_type('integer', cluster_size_value) else: # for other clusters, return the number of servers assigned to this cluster count = 0 servers = dictionary_utils.get_dictionary_element( self._model.get_model_topology(), SERVER) for server_name, server_value in servers.items(): server_cluster = dictionary_utils.get_element( server_value, CLUSTER) if str(server_cluster) == cluster_name: count = count + 1 return count return 0
variables = None if variable_file is not None: try: variables = variable_helper.load_variables(variable_file) except VariableException, ve: __logger.severe('WLSDPLY-04207', _program_name, variable_file, ve.getLocalizedMessage(), error=ve, class_name=_class_name, method_name=_method_name) return CommandLineArgUtil.PROG_ERROR_EXIT_CODE aliases = Aliases(model_context, wlst_mode=WlstModes.OFFLINE) alias_helper = AliasHelper(aliases, __logger, ExceptionType.ENCRYPTION) try: passphrase = model_context.get_encryption_passphrase() model_change_count, variable_change_count = \ encryption_utils.encrypt_model_dictionary(passphrase, model, alias_helper, variables) except EncryptionException, ee: __logger.severe('WLSDPLY-04208', _program_name, ee.getLocalizedMessage(), error=ee, class_name=_class_name, method_name=_method_name) return CommandLineArgUtil.PROG_ERROR_EXIT_CODE if variable_change_count > 0:
def __init__(self, model, model_context, aliases, logger): self._model = model self._model_context = model_context self._aliases = AliasHelper(aliases, logger, ExceptionType.DEPLOY) self._logger = logger return
class ModelHelpPrinter(object): """ Class for printing the recognized model metadata to STDOUT. """ def __init__(self, aliases, logger): """ :param aliases: A reference to an Aliases class instance :param logger: A reference to the platform logger to write to, if a log entry needs to be made """ self._logger = logger self._alias_helper = AliasHelper(aliases, self._logger, ExceptionType.CLA) def print_model_help(self, model_path, control_option, as_sample=False): """ Prints out the help information for a given '''model_path'''. '''model_path''' needs to be specified using the following pattern: <model_section>[:/<section_folder>[/<section_subfolder>|...]] Examples: 'domainInfo', 'domainInfo:' or 'domainInfo:/' (all 3 are equivalent) 'topology:/Server' 'resources:/JDBCSystemResource/JdbcResource/JDBCDriverParams' 'appDeployments:/Application' :param model_path: a formatted string containing the model path :param control_option: a command-line switch that controls what is output :param as_sample: specifies that a model sample should be output :raises CLAException: if a problem is encountered """ # print filter information, if not NORMAL if control_option == ControlOptions.RECURSIVE: print print _format_message('WLSDPLY-10102') elif control_option == ControlOptions.FOLDERS_ONLY: print print _format_message('WLSDPLY-10103') elif control_option == ControlOptions.ATTRIBUTES_ONLY: print print _format_message('WLSDPLY-10104') model_path_tokens = self._parse_model_path(model_path) section_name = model_path_tokens[0] valid_section_folder_keys = self._alias_helper.get_model_section_top_level_folder_names( section_name) if as_sample: sample_printer = ModelSamplePrinter(self._alias_helper, self._logger) sample_printer.print_model_sample(model_path_tokens, control_option) else: if model_path_tokens[0] == 'top': self._print_model_top_level_help() elif len(model_path_tokens) == 1: self._print_model_section_help(section_name, valid_section_folder_keys, control_option) else: self._print_model_folder_help(model_path_tokens, valid_section_folder_keys, control_option) def _parse_model_path(self, model_path): """ Parse the specified model_path into a Python list of elements. The first element will be the section name. If not specified, the section name will be derived from the first path element. :param model_path: a string contain the model path to parse :return: a python list containing the section name, then each folder element :raises: CLAException if the path cannot be parsed, or the section name is invalid """ _method_name = '_parse_model_path' self._logger.entering(model_path, class_name=_class_name, method_name=_method_name) match = MODEL_PATH_PATTERN.match(model_path) if match is None: ex = exception_helper.create_cla_exception('WLSDPLY-10108', model_path) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex self._logger.finest('match.group(1)={0}, match.group(2)={1}', str(match.group(1)), str(match.group(2)), class_name=_class_name, method_name=_method_name) section = match.group(1) path = match.group(2) folders = [] if path is not None: for folder in path.split('/'): # trailing or duplicate slashes may cause empty folder name if len(folder) > 0: folders.append(folder) if section is None: section = self._get_section_for_folder_list(folders) section = section.replace(':', '') top_level_keys = model.get_model_top_level_keys() # 'top' is a special case for listing the sections all_section_keys = ['top'] all_section_keys.extend(top_level_keys) if section not in all_section_keys: ex = exception_helper.create_cla_exception( 'WLSDPLY-10109', section, str(', '.join(top_level_keys))) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex model_path_tokens = [section] model_path_tokens.extend(folders) return model_path_tokens def _get_section_for_folder_list(self, folder_list): """ Derive the section name from the first folder in the specified list. :param folder_list: the list of folders in the model path :return: the section name :raises: CLAException if the section name cannot be determined """ _method_name = '_get_section_for_folder_list' top_folder = folder_list[0] for section in KNOWN_TOPLEVEL_MODEL_SECTIONS: folder_keys = self._alias_helper.get_model_section_top_level_folder_names( section) if top_folder in folder_keys: return section ex = exception_helper.create_cla_exception('WLSDPLY-10101', top_folder) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex def _print_model_top_level_help(self): """ Prints out all the valid section names for a model. The -recursive flag is disregarded for this case. """ _method_name = '_print_model_top_level_help' self._logger.finest('sections={0}', KNOWN_TOPLEVEL_MODEL_SECTIONS, class_name=_class_name, method_name=_method_name) title = _format_message('WLSDPLY-10113') # Print 'All Sections:' header print _print_indent(title, 0) print for section in KNOWN_TOPLEVEL_MODEL_SECTIONS: _print_indent(section, 1) def _print_model_section_help(self, section_name, valid_section_folder_keys, control_option): """ Prints the help for a section of a model, when just the section_name[:] is provided :param section_name: the name of the model section :param valid_section_folder_keys: list of the valid top folders in the specified section :param control_option: A command-line switch that controls what is output to STDOUT """ _method_name = '_print_model_section_help' self._logger.finest('1 section_name={0}', section_name, class_name=_class_name, method_name=_method_name) location_path = '%s:' % section_name self._logger.finest('1 location_path={0}', location_path, class_name=_class_name, method_name=_method_name) model_section = _format_message('WLSDPLY-10106', location_path) # Print 'Section: <model_section>' label and field print _print_indent(model_section, 0) if model_help_utils.show_attributes(control_option): attributes_location = self._alias_helper.get_model_section_attribute_location( section_name) if attributes_location is not None: self._print_attributes_help(attributes_location, 1) if model_help_utils.show_folders(control_option): print _print_indent(_format_message('WLSDPLY-10107'), 1) valid_section_folder_keys.sort() for section_folder_key in valid_section_folder_keys: _print_indent(section_folder_key, 2) if control_option == ControlOptions.RECURSIVE: model_location = LocationContext().append_location( section_folder_key) self._print_subfolders_help(model_location, control_option, 2) def _print_model_folder_help(self, model_path_tokens, valid_section_folder_keys, control_option): """ Prints the help for a folder in a model, when more than just the section_name[:] is provided. The section name in the first token was already validated. :param model_path_tokens: a Python list of path elements built from model path :param valid_section_folder_keys: A list of valid folder names for the model section in the path :param control_option: A command-line switch that controls what is output to STDOUT """ _method_name = '_print_model_folder_help' self._logger.finest( '1 model_path_tokens={0}, control_option={1}, valid_section_folder_keys={0}', str(model_path_tokens), ControlOptions.from_value(control_option), str(valid_section_folder_keys), class_name=_class_name, method_name=_method_name) section_name = model_path_tokens[0] top_folder = model_path_tokens[1] if top_folder not in valid_section_folder_keys: ex = exception_helper.create_cla_exception( 'WLSDPLY-10110', section_name + ':', top_folder, ', '.join(valid_section_folder_keys)) self._logger.throwing(ex, class_name=_class_name, method_name=_method_name) raise ex # Populate the location context using model_path_tokens[1:] model_location = LocationContext() for folder_key in model_path_tokens[1:]: model_location.append_location(folder_key) name_token = self._alias_helper.get_name_token(model_location) if name_token is not None: model_location.add_name_token(name_token, '%s-0' % folder_key) self._logger.finest('2 model_location={0}', model_location, class_name=_class_name, method_name=_method_name) folder_path = '/'.join(model_path_tokens[1:]) model_path = _format_message('WLSDPLY-10105', '%s:/%s' % (section_name, folder_path)) type_name = self._get_folder_type_name(model_location) if type_name is not None: model_path += " (" + type_name + ")" # Print 'Path: <model_section>' header print _print_indent(model_path, 0) if model_help_utils.show_attributes(control_option): # Print the attributes associated with location context self._print_attributes_help(model_location, 1) if model_help_utils.show_folders(control_option): # Print the folders associated with location context print _print_indent(_format_message('WLSDPLY-10107'), 1) self._print_subfolders_help(model_location, control_option, 1) self._logger.exiting(class_name=_class_name, method_name=_method_name) return def _print_subfolders_help(self, model_location, control_option, indent_level): """ Prints the help for the folders in a model location, without header or leading space. :param model_location: the model location being worked on :param control_option: a command-line switch that controls what is output to STDOUT :param indent_level: the level to indent by, before printing output """ _method_name = '_print_subfolders_help' valid_subfolder_keys = self._alias_helper.get_model_subfolder_names( model_location) self._logger.finest( '3 aliases.get_model_subfolder_names(model_location) returned: {0}', str(valid_subfolder_keys), class_name=_class_name, method_name=_method_name) if not valid_subfolder_keys: return valid_subfolder_keys.sort() for key in valid_subfolder_keys: model_location.append_location(key) name_token = self._alias_helper.get_name_token(model_location) if name_token is not None: model_location.add_name_token(name_token, '%s-0' % key) self._logger.finest('3 model_location={0}', model_location, class_name=_class_name, method_name=_method_name) text = key type_name = self._get_folder_type_name(model_location) if type_name is not None: text += " (" + type_name + ")" _print_indent(text, indent_level + 1) if control_option == ControlOptions.RECURSIVE: # Call this method recursively self._print_subfolders_help(model_location, control_option, indent_level + 1) model_location.pop_location() def _print_attributes_help(self, model_location, indent_level): """ Prints out the help for the attributes in a model location :param model_location: An object containing data about the model location being worked on :param indent_level: The level to indent by, before printing output """ _method_name = '_print_attributes_help' attr_infos = self._alias_helper.get_model_attribute_names_and_types( model_location) self._logger.finer('WLSDPLY-05012', str(model_location), str(attr_infos), class_name=_class_name, method_name=_method_name) # Print 'Valid Attributes:' area label print _print_indent(_format_message('WLSDPLY-10111'), indent_level) if attr_infos: maxlen = 0 for key in attr_infos: if len(key) > maxlen: maxlen = len(key) formatted_string = '%-' + str(maxlen) + 's\t%s' attr_list = attr_infos.keys() attr_list.sort() for attr_name in attr_list: msg = formatted_string % (attr_name, attr_infos[attr_name]) _print_indent(msg, indent_level + 1) def _get_folder_type_name(self, location): """ Return text indicating the type of a folder, such as "multiple". :param location: the location to be checked :return: name of the folder type to be displayed, or None """ if self._alias_helper.is_artificial_type_folder(location): return None if self._alias_helper.supports_multiple_mbean_instances(location): return "multiple" return None
class TopologyHelper(object): """ Shared code for topology section of model. Domain create and update use this code. """ __class_name = 'TopologyHelper' def __init__(self, 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._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.keys(): 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_servers_in_cluster(self, topology): """ Create a placeholder for servers that are in a cluster, as these are migratable entities that can reference other servers in the cluster. :param topology: The topology model nodes containing the full set of Servers to add for the create / update """ _method_name = 'create_placeholder_servers_in_cluster' self.logger.entering(class_name=self.__class_name, method_name=_method_name) self.create_placeholder_named_elements(LocationContext(), SERVER, topology) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) 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 """ self.create_placeholder_named_elements(LocationContext(), SERVER_TEMPLATE, topology) def create_placeholder_jdbc_resources(self, resources): """ Create a placeholder JDBC resource for each name in the resources section. This is necessary because cluster attributes may reference JDBC resources. :param resources: the resource model nodes """ self.create_placeholder_named_elements(LocationContext(), JDBC_SYSTEM_RESOURCE, resources) def create_placeholder_named_elements(self, location, model_type, model_nodes): """ Create a placeholder entry for each element in the specified named element nodes. This is necessary when there can be circular references with other elements. :param location: the location for the nodes to be added :param model_type: the type of the specified model nodes :param model_nodes: the model nodes """ _method_name = 'create_placeholder_named_elements' original_location = self.wlst_helper.get_pwd() resource_location = LocationContext(location).append_location( model_type) if self.alias_helper.get_wlst_mbean_type( resource_location) is not None: existing_names = deployer_utils.get_existing_object_list( resource_location, self.alias_helper) name_nodes = dictionary_utils.get_dictionary_element( model_nodes, model_type) for name in name_nodes.keys(): if model_helper.is_delete_name(name): # don't create placeholder for delete names continue if name not in existing_names: self.logger.info('WLSDPLY-19403', model_type, name, class_name=self.__class_name, method_name=_method_name) token = self.alias_helper.get_name_token(resource_location) resource_location.add_name_token(token, name) deployer_utils.create_and_cd(resource_location, existing_names, self.alias_helper) self.wlst_helper.cd(original_location) def qualify_nm_properties(self, type_name, model_nodes, base_location, model_context, attribute_setter): """ For the NM properties MBean, update the keystore file path to be fully qualified with the domain directory. :param type_name: the type name of the MBean to be checked :param model_nodes: the model nodes of the MBean to be checked :param base_location: the parent location of the MBean :param model_context: the model context of the tool :param attribute_setter: the attribute setter to be used for update """ if type_name == NM_PROPERTIES: location = LocationContext(base_location).append_location( type_name) keystore_file = dictionary_utils.get_element( model_nodes, CUSTOM_IDENTITY_KEYSTORE_FILE) if keystore_file and WLSDeployArchive.isPathIntoArchive( keystore_file): value = model_context.get_domain_home() + "/" + keystore_file attribute_setter.set_attribute(location, CUSTOM_IDENTITY_KEYSTORE_FILE, value) def is_clustered_server(self, server_name, servers_dictionary): """ Return true if the server's Cluster attribute is set. :param server_name: name of the server in the dictionary :param servers_dictionary: model topology section of servers :return: True if a clustered server """ server_dictionary = dictionary_utils.get_dictionary_element( servers_dictionary, server_name) if dictionary_utils.is_empty_dictionary_element( server_dictionary, CLUSTER): return False return True
class CustomFolderHelper(object): """ Shared code for custom (user-defined) folders in the model. These require special handling, since they do not have alias definitions. """ __class_name = 'CustomFolderHelper' __cipher_text_prefixes = ["{AES}", "{AES-256}"] def __init__(self, aliases, logger, model_context, exception_type): self.logger = logger self.model_context = model_context self.exception_type = exception_type self.alias_helper = AliasHelper(aliases, self.logger, self.exception_type) self.weblogic_helper = WebLogicHelper(self.logger) self.wlst_helper = WlstHelper(self.logger, self.exception_type) def update_security_folder(self, location, model_type, model_subtype, model_name, model_nodes): """ Update the specified security model nodes in WLST. :param location: the location for the provider :param model_type: the type of the provider to be updated, such as AuthenticationProvider :param model_subtype: the subtype of the provider to be updated, such as 'custom.my.CustomIdentityAsserter' :param model_name: the name of the provider to be updated, such as 'My custom IdentityAsserter' :param model_nodes: a child model nodes of the provider to be updated :raises: BundleAwareException of the specified type: if an error occurs """ _method_name = 'update_security_folder' location_path = self.alias_helper.get_model_folder_path(location) self.logger.entering(location_path, model_subtype, model_name, class_name=self.__class_name, method_name=_method_name) self.logger.info('WLSDPLY-12124', model_type, model_name, model_subtype, location_path, class_name=self.__class_name, method_name=_method_name) create_path = self.alias_helper.get_wlst_subfolders_path(location) self.wlst_helper.cd(create_path) # create the MBean using the model type, name, and subtype type_location = LocationContext(location).append_location(model_type) token = self.alias_helper.get_name_token(type_location) type_location.add_name_token(token, model_name) mbean_type = self.alias_helper.get_wlst_mbean_type(type_location) self.wlst_helper.create(model_name, model_subtype, mbean_type) provider_path = self.alias_helper.get_wlst_attributes_path( type_location) provider_mbean = self.wlst_helper.cd(provider_path) interface_name = model_subtype + 'MBean' bean_info = self.weblogic_helper.get_bean_info_for_interface( interface_name) if bean_info is None: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12125', interface_name) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex property_map = dict() for property_descriptor in bean_info.getPropertyDescriptors(): self.logger.finer('WLSDPLY-12126', str(property_descriptor), class_name=self.__class_name, method_name=_method_name) property_map[property_descriptor.getName()] = property_descriptor for model_key in model_nodes: model_value = model_nodes[model_key] property_descriptor = property_map.get(model_key) if not property_descriptor: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12128', model_key) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex # find the setter method for the attribute method = property_descriptor.writeMethod if not method: # this must be a read-only attribute, just log it and continue with next attribute self.logger.info('WLSDPLY-12129', str(model_key), class_name=self.__class_name, method_name=_method_name) continue self.logger.finer('WLSDPLY-12127', str(model_key), str(model_value), class_name=self.__class_name, method_name=_method_name) # determine the data type from the set method parameter_types = method.getParameterTypes() parameter_count = len(parameter_types) if parameter_count != 1: ex = exception_helper.create_exception(self.exception_type, 'WLSDPLY-12130', model_key, parameter_count) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex # if the property requires encryption, and the value is not encrypted, # encrypt the value with domain encryption. requires_encrypted = property_descriptor.getValue('encrypted') if requires_encrypted and not self.is_encrypted( model_value) and isinstance(model_value, str): model_value = self.weblogic_helper.encrypt( model_value, self.model_context.get_domain_home()) property_type = parameter_types[0] # convert the model value to the target type and call the setter with the target value. # these are done together in Java to avoid automatic Jython type conversions. try: CustomBeanUtils.callMethod(provider_mbean, method, property_type, model_value) # failure converting value or calling method except (IllegalAccessException, IllegalArgumentException, InvocationTargetException), ex: ex = exception_helper.create_exception( self.exception_type, 'WLSDPLY-12131', method, str(model_value), ex.getLocalizedMessage(), error=ex) self.logger.throwing(ex, class_name=self.__class_name, method_name=_method_name) raise ex
if model_context.get_variable_file(): variable_map = variables.load_variables( model_context.get_variable_file()) variables.substitute(model, variable_map, model_context) except VariableException, ex: __logger.severe('WLSDPLY-20004', _program_name, ex.getLocalizedMessage(), error=ex, class_name=_class_name, method_name=_method_name) cla_helper.clean_up_temp_files() tool_exit.end(model_context, CommandLineArgUtil.PROG_ERROR_EXIT_CODE) aliases = Aliases(model_context, wlst_mode=__wlst_mode) alias_helper = AliasHelper(aliases, __logger, ExceptionType.CREATE) validate_model(model, model_context, aliases) if filter_helper.apply_filters(model, "create"): # if any filters were applied, re-validate the model validate_model(model, model_context, aliases) try: has_atp = validateRCUArgsAndModel(model_context, model, alias_helper) # check if there is an atpwallet and extract in the domain dir # it is to support non JRF domain but user wants to use ATP database archive_file_name = model_context.get_archive_file_name() if not has_atp and archive_file_name and os.path.exists( archive_file_name): archive_file = WLSDeployArchive(archive_file_name) if archive_file:
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
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) self.exception_type = 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_jrf_groups_to_clusters_servers(self, should_update=True): """ Call applyJRF to for those versions of wlst that cannot target servers to server groups. This assigns the JRF resources to all managed servers. If the managed server is in a cluster, this method assigns the JRF resources are assigned to the cluster. Else, if the managed server is stand-alone, the resources are assigned to the managed server. :param should_update: Control how the applyJRF applies the changes. By default, allow the applyJRF to automatically update the values """ _method_name = 'target_jrf_groups_to_clusters_servers' self.logger.entering(should_update, class_name=self.__class_name, method_name=_method_name) location = LocationContext() root_path = self.alias_helper.get_wlst_attributes_path(location) self.wlst_helper.cd(root_path) admin_server_name = self.wlst_helper.get(ADMIN_SERVER_NAME) # 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() if admin_server_name in server_names: server_names.remove(admin_server_name) # Get the clusters and and their members cluster_map = self._get_clusters_and_members_map() self.wlst_helper.save_and_close(self.model_context) # Get the clusters and and their members for cluster_name, cluster_servers in cluster_map.iteritems(): self.logger.info('WLSDPLY-12233', 'Cluster', cluster_name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.apply_jrf(cluster_name, self.model_context, should_update=should_update) for member in cluster_servers: if member in server_names: server_names.remove(member) for ms_name in server_names: self.logger.info('WLSDPLY-12233', 'Managed Server', ms_name, class_name=self.__class_name, method_name=_method_name) self.wlst_helper.apply_jrf(ms_name, self.model_context, should_update=should_update) self.wlst_helper.reopen(self.model_context) 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: 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 list(), list() 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() dynamic_cluster_names = list() for cluster_name in cluster_map: if DYNAMIC_SERVERS in cluster_map[cluster_name]: dynamic_cluster_names.append(cluster_name) # 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) self.logger.finer('WLSDPLY-12240', str(server_group_targeting_limits), class_name=self.__class_name, method_name=_method_name) # 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, dynamic_cluster_names, server_groups_to_target, server_group_targeting_limits) # type: dict self.logger.finer('WLSDPLY-12242', str(server_to_server_groups_map), class_name=self.__class_name, method_name=_method_name) final_assignment_map = dict() dynamic_cluster_assigns = dict() # Target servers and dynamic clusters to the server group resources if len(server_names) > 0 or len(dynamic_cluster_names) > 0: for server, server_groups in server_to_server_groups_map.iteritems(): if len(server_groups) > 0: if server in server_names: final_assignment_map[server] = server_groups elif server in dynamic_cluster_names: dynamic_cluster_assigns[server] = server_groups # # Domain has not targeted the server groups to managed servers (configured), or the # domain has no managed servers (configured) but has user server groups. The resources for the # user server groups must be targeted before the write/update domain or the write/update will fail. # Thus assign the user server groups to the admin server. # # Because of the interaction of the working context in the different wlst helpers, the dynamic # clusters will be applied to the resources separately and after the write/update domain. # # (From original blurb) # 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... # # (New comment) # As we have added the intricacies of the dynamic clusters, if the targeting is to dynamic # clusters only, the set server groups with the admin server will get through the write/update domain # and the applyJRF with the dynamic cluster should theoretically unset the AdminServer on the user server # groups. It works with JRF type domains. if len(server_groups_to_target) > 0: if len(final_assignment_map) == 0: # This is a quickie to fix the issue where server groups are not targeted because no configured # managed servers exist in the domain final_assignment_map[server_names[0]] = server_groups_to_target else: # If a server group or groups is not targeted in the assignments, log it to stdout no_targets = [server_target for server_target in server_groups_to_target if server_target not in [server_target for row in final_assignment_map.itervalues() for server_target in server_groups_to_target if server_target in row]] if len(no_targets) > 0: self.logger.info('WLSDPLY-12248', no_targets, class_name=self.__class_name, method_name=_method_name) self.logger.exiting(result=str(dynamic_cluster_assigns), class_name=self.__class_name, method_name=_method_name) return final_assignment_map, dynamic_cluster_assigns def target_server_groups(self, server_assigns): """ Perform the targeting of the server groups to server from the list of assignments made in the target helper assignment step. This is separate from creating the list of assignments in order to control the state of the domain when the target is done. :param server_assigns: map of server to server group """ _method_name = 'target_server_groups' self.logger.entering(str(server_assigns), class_name=self.__class_name, method_name=_method_name) for server, server_groups in server_assigns.iteritems(): 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) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) def target_server_groups_to_dynamic_clusters(self, dynamic_cluster_assigns): """ Dynamic clusters need special handling to assign the server group resources to the dynamic cluster. You cannot assign servergroups to a server template. So must search each templates that contain the server group for resources and specifically add the dynamic target to the resource target. If JRF or RestrictedJRF skip the check and do the applyJRF function to automatically target to the cluster. :param dynamic_cluster_assigns: The assignments from domainInfo targeting limits applied to dynamic lusters """ _method_name = 'target_server_group_resources_to_dyanamic_cluster' self.logger.entering(str(dynamic_cluster_assigns), class_name=self.__class_name, method_name=_method_name) domain_typedef = self.model_context.get_domain_typedef() if len(dynamic_cluster_assigns) > 0: self.logger.info('WLSDPLY-12247', class_name=self.__class_name, method_name=_method_name) # TBD assign server group resources to cluster. The JRF resources could still be applied separately # using this technique - or remove this technique and replace with the resource targeting if domain_typedef.has_jrf_resources(): self._target_jrf_resources(dynamic_cluster_assigns) else: self.logger.warning('WLSDPLY-12238', domain_typedef.get_domain_type(), class_name=self.__class_name, method_name=_method_name) self.logger.exiting(class_name=self.__class_name, method_name=_method_name) return def _target_jrf_resources(self, dynamic_cluster_assigns): # Target the JRF resources directly using the applyJRF method. _method_name = '_target_jrf_resources' names_only = list() for name in dynamic_cluster_assigns: names_only.append(name) if self.model_context.is_wlst_online() and \ self.model_context.get_domain_typedef().is_restricted_jrf_domain_type(): self.logger.warning('WLSDPLY-12244', str(names_only), class_name=self.__class_name, _method_name=_method_name) else: self.logger.info('WLSDPLY-12236', str(names_only), class_name=self.__class_name, method_name=_method_name) self.wlst_helper.apply_jrf_control_updates(names_only, self.model_context) 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) clusters_location = LocationContext().append_location(CLUSTER) cluster_list_path = self.alias_helper.get_wlst_list_path(clusters_location) cluster_names = self.wlst_helper.get_existing_object_list(cluster_list_path) cluster_token = self.alias_helper.get_name_token(clusters_location) # Add the cluster with dynamic servers, if not already in the cluster member list. # A cluster may contain both dynamic and configured servers (referred to as mixed cluster). # Add a token marking DYNAMIC SERVERS in the member list. for cluster_name in cluster_names: cluster_location = LocationContext(clusters_location) cluster_location.add_name_token(cluster_token, cluster_name) cluster_attributes_path = self.alias_helper.get_wlst_attributes_path(cluster_location) self.wlst_helper.cd(cluster_attributes_path) cluster_location.append_location(DYNAMIC_SERVERS) wlst_subfolder_name = self.alias_helper.get_wlst_mbean_type(cluster_location) if self.wlst_helper.subfolder_exists(wlst_subfolder_name): if cluster_name not in cluster_map: cluster_map[cluster_name] = list() cluster_map[cluster_name].append(DYNAMIC_SERVERS) self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=cluster_map) return cluster_map 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_existing_cluster_names(self): """ Get the list of cluster names from WLST. :return: the list of cluster names :raises: BundleAwareException of the specified type: is an error occurs reading from the aliases or WLST """ _method_name = 'get_existing_cluster_names' self.logger.entering(class_name=self.__class_name, method_name=_method_name) cluster_location = LocationContext().append_location(CLUSTER) cluster_list_path = self.alias_helper.get_wlst_list_path(cluster_location) result = self.wlst_helper.get_existing_object_list(cluster_list_path) self.logger.exiting(class_name=self.__class_name, method_name=_method_name, result=result) return result 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) if DYNAMIC_SERVERS in cluster_members: # This will need special handling to target server group resources cluster_members.remove(DYNAMIC_SERVERS) cluster_members.append(target_name) new_list.extend(cluster_members) else: # Assume it is a server name and add it to the new list # Stand-alone Managed Servers were not added to the cluster: server_name_list map # which was built from the existing servers and clusters. 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, dynamic_cluster_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() revised_server_groups = self._revised_list_server_groups(server_groups, sg_targeting_limits) for server_name in server_names: server_groups_for_server = self.__get_server_groups_for_entity(server_name, sg_targeting_limits) if len(server_groups_for_server) > 0: 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(revised_server_groups) else: result[admin_server_name] = list() for cluster_name in dynamic_cluster_names: server_groups_for_cluster = \ self.__get_server_groups_for_entity(cluster_name, sg_targeting_limits) if len(server_groups_for_cluster) > 0: result[cluster_name] = server_groups_for_cluster else: result[cluster_name] = list(revised_server_groups) self.logger.finer('WLSDPLY-12239', result[cluster_name], cluster_name, class_name=self.__class_name, method_name=_method_name) 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 _revised_list_server_groups(self, server_groups, sg_targeting_limits): """ Remove all server groups that are explicitly targeted to a cluster, server set or stand-alone managed server. :param server_groups: list of server groups applied by the extension templates :param sg_targeting_limits: list of targeting from the domainInfo section :return: server group list with the specific targeted server groups removed """ _method_name = '_revised_list_server_groups' self.logger.entering(sg_targeting_limits, class_name=self.__class_name, method_name=_method_name) result = list() targeted_server_groups = sg_targeting_limits.keys() for server_group in server_groups: if server_group not in targeted_server_groups: result.append(server_group) return result def __get_server_groups_for_entity(self, entity_name, sg_targeting_limits): """ Get the servers groups to target for a given server or dynamic cluster name. :param entity_name: the server or dynamic_cluster name :param sg_targeting_limits: the targeting limits :return: the list of server groups to target to the specified entity name, or None if the entity name does not appear in the targeting limits """ _method_name = '__get_server_groups_for_entity' result = list() for server_group, entity_names_list in sg_targeting_limits.iteritems(): if entity_name in entity_names_list: result.append(server_group) if len(result) > 0: self.logger.fine('WLSDPLY-12243', entity_name, result, class_name=self.__class_name, method_name=_method_name) return result
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