Esempio n. 1
0
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 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 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
Esempio n. 4
0
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.wlst_helper = WlstHelper(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,
                             delete_now=True):
        """
        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.aliases.get_name_token(location)
        create_path = self.aliases.get_wlst_create_path(location)
        list_path = self.aliases.get_wlst_list_path(location)
        existing_folder_names = self._get_existing_folders(list_path)
        for model_name in model_nodes.keys():
            name = self.wlst_helper.get_quoted_name_for_wlst(model_name)
            if model_helper.is_delete_name(name):
                if delete_now:
                    deployer_utils.delete_named_element(
                        location, name, existing_folder_names, self.aliases)
                continue

            if token_name is not None:
                location.add_name_token(token_name, name)

            wlst_type, wlst_name = self.aliases.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.aliases, 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.aliases.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.aliases.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.aliases.get_wlst_create_path(location)
        existing_folder_names = self._get_existing_folders(create_path)

        mbean_type, mbean_name = self.aliases.get_wlst_mbean_type_and_name(
            location)

        token_name = self.aliases.get_name_token(location)
        if token_name is not None:
            if self.aliases.requires_unpredictable_single_name_handling(
                    location):
                existing_subfolder_names = deployer_utils.get_existing_object_list(
                    location, self.aliases)
                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.aliases, 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.aliases.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.aliases.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.aliases.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.aliases.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.aliases.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.aliases.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.aliases.get_model_attribute_names_and_types(
            location)
        password_attribute_names = self.aliases.get_model_password_type_attribute_names(
            location)
        set_method_map = self.aliases.get_model_mbean_set_method_attribute_names_and_types(
            location)
        uses_path_tokens_attribute_names = self.aliases.get_model_uses_path_tokens_attribute_names(
            location)
        model_folder_path = self.aliases.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.aliases.get_model_folder_path(location),
                    error=ae)
                self.logger.throwing(ex,
                                     class_name=self.__class_name,
                                     method_name=_method_name)
                raise ex
        else:
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
Esempio n. 6
0
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:
Esempio n. 7
0
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 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.aliases = aliases
        self.wlst_helper = WlstHelper(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.aliases)

        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.aliases.get_name_token(cluster_location)
            cluster_location.add_name_token(cluster_token, cluster_name)
            deployer_utils.create_and_cd(cluster_location, existing_names, self.aliases)

        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
        :return: a list of names of created placeholders
        """
        return 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
        :return: a list of names of created placeholders
        """
        _method_name = 'create_placeholder_named_elements'
        holder_names = []
        original_location = self.wlst_helper.get_pwd()
        resource_location = LocationContext(location).append_location(model_type)

        if self.aliases.get_wlst_mbean_type(resource_location) is not None:
            existing_names = deployer_utils.get_existing_object_list(resource_location, self.aliases)

            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.aliases.get_name_token(resource_location)
                    resource_location.add_name_token(token, name)
                    deployer_utils.create_and_cd(resource_location, existing_names, self.aliases)
                    self._update_placeholder(model_type, name, resource_location)
                    holder_names.append(name)

        self.wlst_helper.cd(original_location)
        return holder_names

    def _update_placeholder(self, type_name, name, location):
        """
        Make any required updates to a newly-created placeholder.
        :param type_name: the type name of the placeholder
        :param name: the name of the placeholder MBean
        :param location: the location of the placeholder
        """
        if type_name == JDBC_SYSTEM_RESOURCE:
            # for online update, Name must be assigned to each JDBCSystemResource / JdbcResource MBean.
            # (see datasource_deployer.set_attributes())
            child_location = LocationContext(location).append_location(JDBC_RESOURCE)
            deployer_utils.set_single_folder_token(child_location, self.aliases)
            wlst_path = self.aliases.get_wlst_attributes_path(child_location)
            if self.wlst_helper.path_exists(wlst_path):
                original_location = self.wlst_helper.get_pwd()
                self.wlst_helper.cd(wlst_path)
                existing_name = self.wlst_helper.get('Name')
                if existing_name is None:
                    self.wlst_helper.set('Name', name)
                self.wlst_helper.cd(original_location)

    def clear_jdbc_placeholder_targeting(self, jdbc_names):
        """
        Remove any targets for the JDBC resources in the specified list of names.
        Targets may have been inadvertently assigned when clusters were added after JDBC placeholders.
        :param jdbc_names: names of placeholders to clear
        """
        _method_name = 'clear_jdbc_placeholder_targeting'
        resource_location = LocationContext().append_location(JDBC_SYSTEM_RESOURCE)
        token = self.aliases.get_name_token(resource_location)

        for name in jdbc_names:
            self.logger.info('WLSDPLY-19404', JDBC_SYSTEM_RESOURCE, name, class_name=self.__class_name,
                             method_name=_method_name)

            resource_location.add_name_token(token, name)
            wlst_path = self.aliases.get_wlst_attributes_path(resource_location)
            if self.wlst_helper.path_exists(wlst_path):
                mbean = self.wlst_helper.get_mbean_for_wlst_path(wlst_path)
                mbean.setTargets(None)

    def remove_deleted_clusters_and_servers(self, domain_location, model_topology):
        """
        Remove clusters, servers, server templates, and migratable targets that were flagged for deletion
        in the model. The deletions are intentionally skipped when these elements are first created.
        :param domain_location: the location for the root of the domain
        :param model_topology: the topology folder from the model
        """
        _method_name = 'remove_deleted_clusters_and_servers'
        self.logger.entering(str(domain_location), class_name=self.__class_name, method_name=_method_name)

        for folder_name in [CLUSTER, SERVER_TEMPLATE, SERVER, MIGRATABLE_TARGET]:
            location = LocationContext(domain_location).append_location(folder_name)
            existing_names = deployer_utils.get_existing_object_list(location, self.aliases)
            folder_nodes = dictionary_utils.get_dictionary_element(model_topology, folder_name)

            for mbean_name in folder_nodes:
                if model_helper.is_delete_name(mbean_name):
                    deployer_utils.delete_named_element(location, mbean_name, existing_names, self.aliases)

        self.logger.exiting(class_name=self.__class_name, method_name=_method_name)

    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 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, credential_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 '/'
        :param wlst_mode: offline or online
        :param aliases: optional, aliases object to use
        :param credential_injector: optional, injector to collect credentials
        """
        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,
                                    exception_type=ExceptionType.DISCOVER)
        self._credential_injector = credential_injector
        self._att_handler_map = OrderedDict()
        self._custom_folder = CustomFolderHelper(self._aliases, _logger, self._model_context, ExceptionType.DISCOVER,
                                                 self._credential_injector)
        self._weblogic_helper = WebLogicHelper(_logger)
        self._wlst_helper = WlstHelper(ExceptionType.DISCOVER)
        self._mbean_utils = MBeanUtils(self._model_context, self._aliases, ExceptionType.DISCOVER)
        self._wls_version = self._weblogic_helper.get_actual_weblogic_version()

    def discover_domain_mbean(self, model_top_folder_name):
        """
        Discover the domain specific MBean and its configuration attributes.
        :return: model name for domain MBean:dictionary containing the discovered Domain MBean attributes
        """
        _method_name = 'discover_domain_mbean'
        _logger.entering(model_top_folder_name, class_name=_class_name, method_name=_method_name)
        result = OrderedDict()
        location = LocationContext(self._base_location)
        location.append_location(model_top_folder_name)
        name = self._find_singleton_name_in_folder(location)
        if name is not None:
            _logger.info('WLSDPLY-06644', model_top_folder_name, class_name=_class_name, method_name=_method_name)
            location.add_name_token(self._aliases.get_name_token(location), name)
            self._populate_model_parameters(result, location)
            # if any subfolders exist, discover
            self._discover_subfolders(result, location)
        _logger.exiting(class_name=_class_name, method_name=_method_name)
        return model_top_folder_name, result

    # 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._aliases.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]

                # if attribute was never set (online only), don't add to the model
                if not self._wlst_helper.is_set(wlst_lsa_param):
                    _logger.finest('WLSDPLY-06157', wlst_lsa_param, str(location), class_name=_class_name,
                                   method_name=_method_name)
                    continue

                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