Esempio n. 1
0
 def test_different_parent_not_useful(self):
     element = self.tree.find(".//element-B2")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 2
0
def arrange_first_nvset(
    tag_name, context_element, nvpair_dict, id_provider, new_id=None
):
    """
    Put nvpairs to the first tag_name nvset in the context_element.

    If the nvset does not exist, it will be created.

    WARNING: does not solve multiple nvsets (with the same tag_name) in the
    context_element! Consider carefully if this is your use case. Probably not.
    There could be more than one nvset.
    This function is DEPRECATED. Try to use update_nvset etc.

    string tag_name -- tag name of nvset element
    etree context_element -- parent element of nvset
    dict nvpair_dict -- dictionary of nvpairs
    IdProvider id_provider -- elements' ids generator
    """
    if not nvpair_dict:
        return

    nvset_element = get_sub_element(
        context_element,
        tag_name,
        new_id=(
            new_id
            if new_id
            else create_subelement_id(context_element, tag_name, id_provider)
        ),
        append_if_missing=False,
    )
    update_nvset(nvset_element, nvpair_dict, id_provider)
    append_when_useful(context_element, nvset_element, index=0)
Esempio n. 3
0
def append_new_nvset(tag_name,
                     context_element,
                     nvpair_dict,
                     id_provider,
                     enforce_append=False):
    """
    Append new nvset_element comprising nvpairs children (corresponding
    nvpair_dict) to the context_element

    string tag_name should be "instance_attributes" or "meta_attributes"
    etree.Element context_element is element where new nvset will be appended
    dict nvpair_dict contains source for nvpair children
    IdProvider id_provider -- elements' ids generator
    bool enforce_append -- append element wo usefulness check if flag is True
    """
    nvset_element = etree.Element(
        tag_name,
        {"id": create_subelement_id(context_element, tag_name, id_provider)},
    )
    for name, value in sorted(nvpair_dict.items()):
        _append_new_nvpair(nvset_element, name, value, id_provider)
    if enforce_append:
        context_element.append(nvset_element)
    else:
        append_when_useful(context_element, nvset_element)
Esempio n. 4
0
 def test_not_useful(self):
     element = etree.Element("new")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 5
0
def arrange_first_nvset(
    tag_name, context_element, nvpair_dict, id_provider, new_id=None
):
    """
    Put nvpairs to the first tag_name nvset in the context_element.

    If the nvset does not exist, it will be created.

    WARNING: does not solve multiple nvsets (with the same tag_name) in the
    context_element! Consider carefully if this is your use case. Probably not.
    There could be more than one nvset.
    This function is DEPRECATED. Try to use update_nvset etc.

    string tag_name -- tag name of nvset element
    etree context_element -- parent element of nvset
    dict nvpair_dict -- dictionary of nvpairs
    IdProvider id_provider -- elements' ids generator
    """
    if not nvpair_dict:
        return

    nvset_element = get_sub_element(
        context_element,
        tag_name,
        new_id=(new_id if new_id else create_subelement_id(
            context_element, tag_name, id_provider
        )),
        append_if_missing=False
    )
    update_nvset(nvset_element, nvpair_dict, id_provider)
    append_when_useful(context_element, nvset_element, index=0)
Esempio n. 6
0
def append_new_nvset(
        tag_name, context_element, nvpair_dict, id_provider,
        enforce_append=False
    ):
    """
    Append new nvset_element comprising nvpairs children (corresponding
    nvpair_dict) to the context_element

    string tag_name should be "instance_attributes" or "meta_attributes"
    etree.Element context_element is element where new nvset will be appended
    dict nvpair_dict contains source for nvpair children
    IdProvider id_provider -- elements' ids generator
    bool enforce_append -- append element wo usefulness check if flag is True
    """
    nvset_element = etree.Element(
        tag_name,
        {
            "id": create_subelement_id(context_element, tag_name, id_provider)
        }
    )
    for name, value in sorted(nvpair_dict.items()):
        _append_new_nvpair(nvset_element, name, value, id_provider)
    if enforce_append:
        context_element.append(nvset_element)
    else:
        append_when_useful(context_element, nvset_element)
Esempio n. 7
0
 def test_already_appended(self):
     element = self.tree.find(".//element-A2")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 8
0
 def test_not_useful_with_attributes(self):
     element = etree.Element("new", attr="test")
     lib.append_when_useful(self.parent, element, attribs_important=False)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 9
0
 def test_already_appended(self):
     element = self.tree.find(".//element-A2")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 10
0
 def test_not_useful_with_attributes(self):
     element = etree.Element("new", attr="test")
     lib.append_when_useful(self.parent, element, attribs_important=False)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 11
0
 def test_not_useful(self):
     element = etree.Element("new")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 12
0
 def test_different_parent_not_useful(self):
     element = self.tree.find(".//element-B2")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         self.tree_str,
         etree_to_str(self.tree)
     )
Esempio n. 13
0
 def test_different_parent_useful(self):
     element = self.tree.find(".//element-B1")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         """
             <root>
                 <parent-A>
                     <element-A1 />
                     <element-A2 attr="test" />
                     <element-B1 attr="test"/>
                 </parent-A>
                 <parent-B>
                     <element-B2 />
                 </parent-B>
             </root>
         """, etree_to_str(self.tree))
Esempio n. 14
0
 def test_index(self):
     element = etree.Element("new", attr="test")
     lib.append_when_useful(self.parent, element, index=1)
     assert_xml_equal(
         """
             <root>
                 <parent-A>
                     <element-A1 />
                     <new attr="test" />
                     <element-A2 attr="test" />
                 </parent-A>
                 <parent-B>
                     <element-B1 attr="test"/>
                     <element-B2 />
                 </parent-B>
             </root>
         """, etree_to_str(self.tree))
Esempio n. 15
0
 def test_different_parent_useful(self):
     element = self.tree.find(".//element-B1")
     lib.append_when_useful(self.parent, element)
     assert_xml_equal(
         """
             <root>
                 <parent-A>
                     <element-A1 />
                     <element-A2 attr="test" />
                     <element-B1 attr="test"/>
                 </parent-A>
                 <parent-B>
                     <element-B2 />
                 </parent-B>
             </root>
         """,
         etree_to_str(self.tree)
     )
Esempio n. 16
0
 def test_index(self):
     element = etree.Element("new", attr="test")
     lib.append_when_useful(self.parent, element, index=1)
     assert_xml_equal(
         """
             <root>
                 <parent-A>
                     <element-A1 />
                     <new attr="test" />
                     <element-A2 attr="test" />
                 </parent-A>
                 <parent-B>
                     <element-B1 attr="test"/>
                     <element-B2 />
                 </parent-B>
             </root>
         """,
         etree_to_str(self.tree)
     )
Esempio n. 17
0
def update_node_instance_attrs(cib,
                               id_provider,
                               node_name,
                               attrs,
                               state_nodes=None):
    """
    Update nvpairs in instance_attributes for a node specified by its name.

    Automatically creates instance_attributes element if needed. If the node has
    more than one instance_attributes element, the first one is modified. If the
    node is missing in the CIB, it is automatically created if its state is
    provided in state_nodes.

    etree cib -- cib
    IdProvider id_provider -- elements' ids generator
    string node_name -- name of the node to be updated
    dict attrs -- attrs to update, e.g. {'A': 'a', 'B': ''}
    iterable state_nodes -- optional list of node state objects
    """
    # Do not ever remove the nvset element or the node element, even if they
    # are empty. There may be ACLs set in pacemaker which allow "write" for
    # nvpairs (adding, changing and removing) but not nvsets. In such a case,
    # removing the nvset would cause the whole change to be rejected by
    # pacemaker with a "permission denied" message.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1642514

    if not attrs:
        return

    cib_nodes = get_nodes(cib)
    node_el = _ensure_node_exists(cib_nodes, node_name, state_nodes)
    # If no instance_attributes id is specified, crm_attribute modifies the
    # first one found. So we just mimic this behavior here.
    attrs_el = node_el.find("./instance_attributes")
    if attrs_el is None:
        attrs_el = etree.Element(
            "instance_attributes",
            id=id_provider.allocate_id("nodes-{0}".format(node_el.get("id"))),
        )
    update_nvset(attrs_el, attrs, id_provider)
    append_when_useful(node_el, attrs_el)
    append_when_useful(cib_nodes, node_el)
Esempio n. 18
0
def update_node_instance_attrs(
    cib, id_provider, node_name, attrs, state_nodes=None
):
    """
    Update nvpairs in instance_attributes for a node specified by its name.

    Automatically creates instance_attributes element if needed. If the node has
    more than one instance_attributes element, the first one is modified. If the
    node is missing in the CIB, it is automatically created if its state is
    provided in state_nodes.

    etree cib -- cib
    IdProvider id_provider -- elements' ids generator
    string node_name -- name of the node to be updated
    dict attrs -- attrs to update, e.g. {'A': 'a', 'B': ''}
    iterable state_nodes -- optional list of node state objects
    """
    # Do not ever remove the nvset element or the node element, even if they
    # are empty. There may be ACLs set in pacemaker which allow "write" for
    # nvpairs (adding, changing and removing) but not nvsets. In such a case,
    # removing the nvset would cause the whole change to be rejected by
    # pacemaker with a "permission denied" message.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1642514

    if not attrs:
        return

    cib_nodes = get_nodes(cib)
    node_el = _ensure_node_exists(cib_nodes, node_name, state_nodes)
    # If no instance_attributes id is specified, crm_attribute modifies the
    # first one found. So we just mimic this behavior here.
    attrs_el = node_el.find("./instance_attributes")
    if attrs_el is None:
        attrs_el = etree.Element(
            "instance_attributes",
            id=id_provider.allocate_id("nodes-{0}".format(node_el.get("id"))),
        )
    update_nvset(attrs_el, attrs, id_provider)
    append_when_useful(node_el, attrs_el)
    append_when_useful(cib_nodes, node_el)
Esempio n. 19
0
def update(
    id_provider,
    bundle_el,
    container_options,
    network_options,
    port_map_add,
    port_map_remove,
    storage_map_add,
    storage_map_remove,
    meta_attributes,
):
    # pylint: disable=too-many-arguments, too-many-locals
    """
    Modify an existing bundle (does not touch encapsulated resources)

    IdProvider id_provider -- elements' ids generator and uniqueness checker
    etree bundle_el -- the bundle to be updated
    dict container_options -- container options to modify
    dict network_options -- network options to modify
    list of dict port_map_add -- list of port mapping options to add
    list of string port_map_remove -- list of port mapping ids to remove
    list of dict storage_map_add -- list of storage mapping options to add
    list of string storage_map_remove -- list of storage mapping ids to remove
    dict meta_attributes -- meta attributes to update
    """
    # Do not ever remove meta_attributes, network and storage elements, even if
    # they are empty. There may be ACLs set in pacemaker which allow "write"
    # for their children (adding, changing and removing) but not themselves. In
    # such a case, removing those elements would cause the whole change to be
    # rejected by pacemaker with a "permission denied" message.
    # https://bugzilla.redhat.com/show_bug.cgi?id=1642514

    bundle_id = bundle_el.get("id")
    update_attributes_remove_empty(_get_container_element(bundle_el),
                                   container_options)

    network_element = get_sub_element(bundle_el,
                                      "network",
                                      append_if_missing=False)
    if network_options:
        update_attributes_remove_empty(network_element, network_options)
    # It's crucial to remove port maps prior to appending new ones: If we are
    # adding a port map which in any way conflicts with another one and that
    # another one is being removed in the very same command, the removal must
    # be done first, otherwise the conflict would manifest itself (and then
    # possibly the old mapping would be removed)
    if port_map_remove:
        _remove_map_elements(network_element.findall("port-mapping"),
                             port_map_remove)
    if port_map_add:
        for port_map_options in port_map_add:
            _append_port_map(network_element, id_provider, bundle_id,
                             port_map_options)
    append_when_useful(bundle_el, network_element)

    storage_element = get_sub_element(bundle_el,
                                      "storage",
                                      append_if_missing=False)
    # See the comment above about removing port maps prior to adding new ones.
    if storage_map_remove:
        _remove_map_elements(storage_element.findall("storage-mapping"),
                             storage_map_remove)
    if storage_map_add:
        for storage_map_options in storage_map_add:
            _append_storage_map(storage_element, id_provider, bundle_id,
                                storage_map_options)
    append_when_useful(bundle_el, storage_element)

    if meta_attributes:
        arrange_first_meta_attributes(bundle_el, meta_attributes, id_provider)