def _find_dictionary_merge_key(dictionary, new_key, variable_map): """ Find the key corresponding to new_key in the specified dictionary. Determine if the new_key should completely replace the value in the dictionary. If no direct match is found, and a variable map is specified, perform check with variable substitution. If keys have the same name, but one has delete notation (!server), that is a match, and replace is true. :param dictionary: the dictionary to be searched :param new_key: the key being checked :param variable_map: variables to be used for name resolution, or None :return: tuple - the corresponding key from the dictionary, True if dictionary key should be replaced """ if new_key in dictionary: return new_key, False new_is_delete = model_helper.is_delete_name(new_key) match_new_key = _get_merge_match_key(new_key, variable_map) for dictionary_key in dictionary.keys(): dictionary_is_delete = model_helper.is_delete_name(dictionary_key) match_dictionary_key = _get_merge_match_key(dictionary_key, variable_map) if match_dictionary_key == match_new_key: replace_key = new_is_delete != dictionary_is_delete return dictionary_key, replace_key return None, False
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 _merge_dictionaries(dictionary, new_dictionary, variable_map): """ Merge the values from the new dictionary to the existing one. Use variables to resolve keys. :param dictionary: the existing dictionary :param new_dictionary: the new dictionary to be merged :param variable_map: variables to be used for name resolution, or None """ for new_key in new_dictionary: new_value = new_dictionary[new_key] dictionary_key, replace_key = _find_dictionary_merge_key(dictionary, new_key, variable_map) # the key is not in the original dictionary, just add it if dictionary_key is None: dictionary[new_key] = new_value # the new key should replace the existing one - delete the existing key and add the new one elif replace_key: del dictionary[dictionary_key] if not model_helper.is_delete_name(new_key): dictionary[new_key] = new_value # the key is in both dictionaries - merge if the values are dictionaries, otherwise replace the value else: value = dictionary[dictionary_key] if isinstance(value, dict) and isinstance(new_value, dict): _merge_dictionaries(value, new_value, variable_map) else: dictionary[new_key] = new_value
def _add_group_params(self, group_name_nodes, location): """ Add each group param entry from group name nodes and set its attributes. A two-pass approach is required since the new folder's name does not always match the group name. Special processing for error destination attributes (build mbean) :param group_name_nodes: the nodes containing group parameter names :param location: the WLST location where the parameters should be added """ _method_name = '_add_group_params' if len(group_name_nodes) == 0: return # use a copy of the dictionary to remove items as they are deleted remaining_name_nodes = group_name_nodes.copy() parent_type, parent_name = self.get_location_type_and_name(location) template_path = self.alias_helper.get_wlst_subfolders_path(location) groups_location = LocationContext(location) groups_location.append_location(GROUP_PARAMS) groups_token = self.alias_helper.get_name_token(groups_location) name_attribute = self.alias_helper.get_wlst_attribute_name(groups_location, SUB_DEPLOYMENT_NAME) mbean_type = self.alias_helper.get_wlst_mbean_type(groups_location) for group_name in group_name_nodes: if model_helper.is_delete_name(group_name): group_nodes = group_name_nodes[group_name] name = model_helper.get_delete_item_name(group_name) sub_name = self._get_subdeployment_name(group_nodes, name) self._delete_mapped_mbean(groups_location, groups_token, mbean_type, name_attribute, sub_name) del remaining_name_nodes[group_name] # loop once to create and name any missing folders. folder_map = self._build_folder_map(groups_location, groups_token, name_attribute) for group_name in remaining_name_nodes: group_nodes = remaining_name_nodes[group_name] sub_deployment_name = self._get_subdeployment_name(group_nodes, group_name) folder_name = dictionary_utils.get_element(folder_map, sub_deployment_name) if folder_name is None: self.wlst_helper.cd(template_path) group = self.wlst_helper.create(sub_deployment_name, mbean_type) group.setSubDeploymentName(sub_deployment_name) # loop a second time to set attributes new_folder_map = self._build_folder_map(groups_location, groups_token, name_attribute) for group_name in remaining_name_nodes: group_nodes = remaining_name_nodes[group_name] sub_deployment_name = self._get_subdeployment_name(group_nodes, group_name) is_add = sub_deployment_name not in folder_map log_helper.log_updating_named_folder(GROUP_PARAMS, group_name, parent_type, parent_name, is_add, self._class_name, _method_name) folder_name = dictionary_utils.get_element(new_folder_map, sub_deployment_name) groups_location.add_name_token(groups_token, folder_name) self.wlst_helper.cd(self.alias_helper.get_wlst_attributes_path(groups_location)) self.set_attributes(groups_location, group_nodes)
def _add_jndi_properties(self, property_name_nodes, location): """ Add each property entry from property nodes and set its attributes. A two-pass approach is required since the new folder's name does not always match the property name. :param property_name_nodes: the nodes containing property names :param location: the WLST location where the properties should be added """ _method_name = '_add_jndi_properties' if len(property_name_nodes) == 0: return # use a copy of the dictionary to remove items as they are deleted remaining_name_nodes = property_name_nodes.copy() parent_type, parent_name = self.get_location_type_and_name(location) is_online = self.wlst_mode == WlstModes.ONLINE if is_online and deployer_utils.is_in_resource_group_or_template(location): self.logger.info('WLSDPLY-09501', JNDI_PROPERTY, parent_type, parent_name, class_name=self._class_name, method_name=_method_name) return foreign_server_path = self.alias_helper.get_wlst_subfolders_path(location) properties_location = LocationContext(location).append_location(JNDI_PROPERTY) properties_token = self.alias_helper.get_name_token(properties_location) name_attribute = self.alias_helper.get_wlst_attribute_name(properties_location, KEY) mbean_type = self.alias_helper.get_wlst_mbean_type(properties_location) for property_name in property_name_nodes: if model_helper.is_delete_name(property_name): name = model_helper.get_delete_item_name(property_name) self._delete_mapped_mbean(properties_location, properties_token, mbean_type, name_attribute, name) del remaining_name_nodes[property_name] # loop once to create and name any missing folders. folder_map = self._build_folder_map(properties_location, properties_token, name_attribute) for property_name in remaining_name_nodes: folder_name = dictionary_utils.get_element(folder_map, property_name) if folder_name is None: self.wlst_helper.cd(foreign_server_path) new_property = self.wlst_helper.create(property_name, mbean_type) new_property.setKey(property_name) # loop a second time to set attributes new_folder_map = self._build_folder_map(properties_location, properties_token, name_attribute) for property_name in remaining_name_nodes: is_add = property_name not in folder_map log_helper.log_updating_named_folder(JNDI_PROPERTY, property_name, parent_type, parent_name, is_add, self._class_name, _method_name) folder_name = dictionary_utils.get_element(new_folder_map, property_name) properties_location.add_name_token(properties_token, folder_name) self.wlst_helper.cd(self.alias_helper.get_wlst_attributes_path(properties_location)) property_nodes = remaining_name_nodes[property_name] self.set_attributes(properties_location, property_nodes)
def _add_named_elements(self, type_name, model_nodes, location, delete_now=True): """ Add each named element from the specified nodes in WLST and set its attributes. Sub-folders are processed in a generic manner if present. It is assumed that there are no attributes or sub-folders with special processing. :param type_name: the type name of the child nodes :param model_nodes: the child nodes of a model element :param location: the location where elements should be added :param delete_now: Flag to determine whether to delay delete of element """ _method_name = '_add_named_elements' if len(model_nodes) == 0: return parent_type, parent_name = self.get_location_type_and_name(location) location = LocationContext(location).append_location(type_name) if not self._check_location(location): return deployer_utils.check_flattened_folder(location, self.aliases) existing_names = deployer_utils.get_existing_object_list( location, self.aliases) token = self.aliases.get_name_token(location) for name in model_nodes: if model_helper.is_delete_name(name): if delete_now: deployer_utils.delete_named_element( location, name, existing_names, self.aliases) continue is_add = name not in existing_names log_helper.log_updating_named_folder(type_name, name, parent_type, parent_name, is_add, self._class_name, _method_name) if token is not None: location.add_name_token(token, name) deployer_utils.create_and_cd(location, existing_names, self.aliases) child_nodes = dictionary_utils.get_dictionary_element( model_nodes, name) self._set_attributes_and_add_subfolders(location, child_nodes) return
def _get_merge_match_key(key, variable_map): """ Get the key name to use for matching in model merge. This includes resolving any variables, and removing delete notation if present. :param key: the key to be examined :param variable_map: variable map to use for substitutions :return: the key to use for matching """ match_key = variables.substitute_key(key, variable_map) if model_helper.is_delete_name(match_key): match_key = model_helper.get_delete_item_name(match_key) return match_key
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 merge_model_and_existing_lists(model_list, existing_list, location_path="(unknown)", attribute_name="(unknown)"): """ Merge the two lists so that the resulting list contains all of the elements in both lists one time. :param model_list: the list to merge, possibly a string or None :param existing_list: the existing list, possibly a string or None :param location_path: optional, the path of the attribute location, for logging :param attribute_name: optional, the attribute name, for logging :return: the merged list as a list or a string, depending on the type of the model_list :raises: DeployException: if either list is not either a string or a list """ _method_name = 'merge_model_and_existing_lists' _logger.entering(model_list, existing_list, location_path, attribute_name, class_name=_class_name, method_name=_method_name) if model_list is None: result_is_string = isinstance(existing_list, basestring) else: result_is_string = isinstance(model_list, basestring) result = create_list(existing_list, 'WLSDPLY-08001') model_iterator = create_list(model_list, 'WLSDPLY-08000') for item in model_iterator: if model_helper.is_delete_name(item): item_name = model_helper.get_delete_item_name(item) if item_name in result: result.remove(item_name) else: _logger.warning('WLSDPLY-08022', item_name, attribute_name, location_path, class_name=_class_name, method_name=_method_name) elif item not in result: result.append(item) if result_is_string: result = MODEL_LIST_DELIMITER.join(result) _logger.exiting(class_name=_class_name, method_name=_method_name, result=result) return result
def __delete_online_targets(app_deployments, model_type, aliases): """ For online deploy and update, remove any deleted targets from existing objects of the specified type. Objects may be applications or libraries. :param app_deployments: the APP_DEPLOYMENTS dictionary from the model :param model_type: map of library targets to be deleted :param aliases: the parent location of the apps and libraries """ _method_name = '__delete_online_targets' location = LocationContext().append_location(model_type) wlst_path = aliases.get_wlst_list_path(location) wlst_names = _wlst_helper.get_existing_object_list(wlst_path) name_token = aliases.get_name_token(location) deploy_dict = dictionary_utils.get_dictionary_element(app_deployments, model_type) for deploy_name in deploy_dict.keys(): if deploy_name in wlst_names: value_dict = deploy_dict[deploy_name] delete_names = [] model_targets = dictionary_utils.get_element(value_dict, TARGET) targets = alias_utils.create_list(model_targets, 'WLSDPLY-08000') for target in targets: if model_helper.is_delete_name(target): delete_names.append(model_helper.get_delete_item_name(target)) location.add_name_token(name_token, deploy_name) mbean_path = aliases.get_wlst_attributes_path(location) mbean = _wlst_helper.get_mbean_for_wlst_path(mbean_path) mbean_targets = mbean.getTargets() for mbean_target in mbean_targets: mbean_name = mbean_target.getName() if mbean_name in delete_names: _logger.info('WLSDPLY-09114', mbean_name, model_type, deploy_name, class_name=_class_name, method_name=_method_name) mbean.removeTarget(mbean_target)
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