Esempio n. 1
0
def _append_container(bundle_element, container_type, container_options):
    # Do not add options with empty values. When updating, an empty value means
    # remove the option.
    update_attributes_remove_empty(
        etree.SubElement(bundle_element, container_type),
        container_options,
    )
Esempio n. 2
0
def append_new(parent_element, id_provider, bundle_id, container_type,
               container_options, network_options, port_map, storage_map):
    """
    Create new bundle and add it to the CIB

    etree parent_element -- the bundle will be appended to this element
    IdProvider id_provider -- elements' ids generator
    string bundle_id -- id of the bundle
    string container_type -- bundle container type
    dict container_options -- container options
    dict network_options -- network options
    list of dict port_map -- list of port mapping options
    list of dict storage_map -- list of storage mapping options
    """
    bundle_element = etree.SubElement(parent_element, TAG, {"id": bundle_id})
    # TODO create the proper element once more container_types are supported
    # by pacemaker
    docker_element = etree.SubElement(bundle_element, "docker")
    # Do not add options with empty values. When updating, an empty value means
    # remove the option.
    update_attributes_remove_empty(docker_element, container_options)
    if network_options or port_map:
        network_element = etree.SubElement(bundle_element, "network")
        # Do not add options with empty values. When updating, an empty value
        # means remove the option.
        update_attributes_remove_empty(network_element, network_options)
    for port_map_options in port_map:
        _append_port_map(network_element, id_provider, bundle_id,
                         port_map_options)
    if storage_map:
        storage_element = etree.SubElement(bundle_element, "storage")
    for storage_map_options in storage_map:
        _append_storage_map(storage_element, id_provider, bundle_id,
                            storage_map_options)
    return bundle_element
Esempio n. 3
0
 def test_more(self):
     lib.update_attributes_remove_empty(self.el, {
         "a": "X",
         "b": "",
         "c": "C",
         "d": "",
     })
     self.assert_xml_equal('<test_element a="X" c="C" />')
Esempio n. 4
0
 def test_more(self):
     lib.update_attributes_remove_empty(self.el, {
         "a": "X",
         "b": "",
         "c": "C",
         "d": "",
     })
     self.assert_xml_equal('<test_element a="X" c="C" />')
Esempio n. 5
0
def _append_network(bundle_element, id_provider, id_base, network_options,
                    port_map):
    network_element = etree.SubElement(bundle_element, "network")
    # Do not add options with empty values. When updating, an empty value means
    # remove the option.
    update_attributes_remove_empty(network_element, network_options)
    for port_map_options in port_map:
        _append_port_map(network_element, id_provider, id_base,
                         port_map_options)
Esempio n. 6
0
def _append_storage_map(parent_element, id_provider, id_base,
                        storage_map_options):
    if "id" not in storage_map_options:
        storage_map_options["id"] = id_provider.allocate_id(
            # use just numbers to keep the ids reasonably short
            "{0}-storage-map".format(id_base))
    storage_map_element = etree.SubElement(parent_element, "storage-mapping")
    # Do not add options with empty values. When updating, an empty value means
    # remove the option.
    update_attributes_remove_empty(storage_map_element, storage_map_options)
    return storage_map_element
Esempio n. 7
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):
    """
    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
    """
    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")
    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)
    for port_map_options in port_map_add:
        _append_port_map(network_element, id_provider, bundle_id,
                         port_map_options)

    storage_element = get_sub_element(bundle_el, "storage")
    # 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)
    for storage_map_options in storage_map_add:
        _append_storage_map(storage_element, id_provider, bundle_id,
                            storage_map_options)

    if meta_attributes:
        arrange_first_meta_attributes(bundle_el, meta_attributes)

    # remove empty elements with no attributes
    # meta attributes are handled in their own function
    remove_when_pointless(network_element)
    remove_when_pointless(storage_element)
Esempio n. 8
0
def _append_port_map(parent_element, id_provider, id_base, port_map_options):
    if "id" not in port_map_options:
        id_suffix = None
        if "port" in port_map_options:
            id_suffix = port_map_options["port"]
        elif "range" in port_map_options:
            id_suffix = port_map_options["range"]
        if id_suffix:
            port_map_options["id"] = id_provider.allocate_id(
                sanitize_id("{0}-port-map-{1}".format(id_base, id_suffix)))
    port_map_element = etree.SubElement(parent_element, "port-mapping")
    # Do not add options with empty values. When updating, an empty value means
    # remove the option.
    update_attributes_remove_empty(port_map_element, port_map_options)
    return port_map_element
Esempio n. 9
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)