Exemplo n.º 1
0
def test_retrocl_exclude_attr_add(topology_st):
    """ Test exclude attribute feature of the retrocl plugin for add operation

    :id: 3481650f-2070-45ef-9600-2500cfc51559

    :setup: Standalone instance

    :steps:
        1. Enable dynamic plugins
        2. Confige retro changelog plugin
        3. Add an entry
        4. Ensure entry attrs are in the changelog
        5. Exclude an attr
        6. Add another entry
        7. Ensure excluded attr is not in the changelog

    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
    """

    st = topology_st.standalone

    log.info('Configure retrocl plugin')
    rcl = RetroChangelogPlugin(st)
    rcl.disable()
    rcl.enable()
    rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    users = UserAccounts(st, DEFAULT_SUFFIX)

    log.info('Adding user1')
    try:
        users.create(
            properties={
                'sn': '1',
                'cn': 'user 1',
                'uid': 'user1',
                'uidNumber': '11',
                'gidNumber': '111',
                'givenname': 'user1',
                'homePhone': '0861234567',
                'carLicense': '131D16674',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user1',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        pass
    except ldap.LDAPError as e:
        log.error("Failed to add user1: " + str(e))

    log.info(
        'Verify homePhone and carLicense attrs are in the changelog changestring'
    )
    try:
        retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
    assert len(cllist) > 0
    if cllist[0].present('changes'):
        clstr = str(cllist[0].get_attr_vals_utf8('changes'))
        assert ATTR_HOMEPHONE in clstr
        assert ATTR_CARLICENSE in clstr

    log.info('Excluding attribute ' + ATTR_HOMEPHONE)
    args = FakeArgs()
    args.connections = [
        st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM
    ]
    args.instance = 'standalone1'
    args.basedn = None
    args.binddn = None
    args.starttls = False
    args.pwdfile = None
    args.bindpw = None
    args.prompt = False
    args.exclude_attrs = ATTR_HOMEPHONE
    args.func = retrochangelog_add
    dsrc_inst = dsrc_arg_concat(args, None)
    inst = connect_instance(dsrc_inst, False, args)
    result = args.func(inst, None, log, args)
    disconnect_instance(inst)
    assert result is None

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    log.info('Adding user2')
    try:
        users.create(
            properties={
                'sn': '2',
                'cn': 'user 2',
                'uid': 'user2',
                'uidNumber': '22',
                'gidNumber': '222',
                'givenname': 'user2',
                'homePhone': '0879088363',
                'carLicense': '04WX11038',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user2',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        pass
    except ldap.LDAPError as e:
        log.error("Failed to add user2: " + str(e))

    log.info('Verify homePhone attr is not in the changelog changestring')
    try:
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER2_DN})')
        assert len(cllist) > 0
        if cllist[0].present('changes'):
            clstr = str(cllist[0].get_attr_vals_utf8('changes'))
            assert ATTR_HOMEPHONE not in clstr
            assert ATTR_CARLICENSE in clstr
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
Exemplo n.º 2
0
def test_dsconf_replication_monitor(topology_m2, set_log_file):
    """Test replication monitor that was ported from legacy tools

    :id: ce48020d-7c30-41b7-8f68-144c9cd757f6
    :setup: 2 MM topology
    :steps:
         1. Create DS instance
         2. Run replication monitor with connections option
         3. Run replication monitor with aliases option
         4. Run replication monitor with --json option
         5. Run replication monitor with .dsrc file created
         6. Run replication monitor with connections option as if using dsconf CLI
    :expectedresults:
         1. Success
         2. Success
         3. Success
         4. Success
         5. Success
         6. Success
    """

    m1 = topology_m2.ms["master1"]
    m2 = topology_m2.ms["master2"]

    # Enable ldapi if not already done.
    for inst in [topology_m2.ms["master1"], topology_m2.ms["master2"]]:
        if not inst.can_autobind():
            # Update ns-slapd instance
            inst.config.set('nsslapd-ldapilisten', 'on')
            inst.config.set('nsslapd-ldapiautobind', 'on')
            inst.restart()
    # Ensure that updates have been sent both ways.
    replicas = Replicas(m1)
    replica = replicas.get(DEFAULT_SUFFIX)
    replica.test_replication([m2])
    replicas = Replicas(m2)
    replica = replicas.get(DEFAULT_SUFFIX)
    replica.test_replication([m1])

    alias_content = [
        'Supplier: M1 (' + m1.host + ':' + str(m1.port) + ')',
        'Supplier: M2 (' + m2.host + ':' + str(m2.port) + ')'
    ]

    connection_content = 'Supplier: ' + m1.host + ':' + str(m1.port)
    content_list = [
        'Replica Root: dc=example,dc=com', 'Replica ID: 1',
        'Replica Status: Available', 'Max CSN',
        'Status For Agreement: "002" (' + m2.host + ':' + str(m2.port) + ')',
        'Replica Enabled: on', 'Update In Progress: FALSE',
        'Last Update Start:', 'Last Update End:', 'Number Of Changes Sent:',
        'Number Of Changes Skipped: None',
        'Last Update Status: Error (0) Replica acquired successfully: Incremental update succeeded',
        'Last Init Start:', 'Last Init End:', 'Last Init Status:',
        'Reap Active: 0', 'Replication Status: In Synchronization',
        'Replication Lag Time:', 'Supplier: ', m2.host + ':' + str(m2.port),
        'Replica Root: dc=example,dc=com', 'Replica ID: 2',
        'Status For Agreement: "001" (' + m1.host + ':' + str(m1.port) + ')'
    ]

    error_list = [
        'consumer (Unavailable)',
        'Failed to retrieve database RUV entry from consumer'
    ]

    json_list = [
        'type', 'list', 'items', 'name', m1.host + ':' + str(m1.port), 'data',
        '"replica_id": "1"', '"replica_root": "dc=example,dc=com"',
        '"replica_status": "Available"', 'maxcsn', 'agmts_status', 'agmt-name',
        '002', 'replica', m2.host + ':' + str(m2.port), 'replica-enabled',
        'update-in-progress', 'last-update-start', 'last-update-end',
        'number-changes-sent', 'number-changes-skipped', 'last-update-status',
        'Error (0) Replica acquired successfully: Incremental update succeeded',
        'last-init-start', 'last-init-end', 'last-init-status', 'reap-active',
        'replication-status', 'In Synchronization', 'replication-lag-time',
        '"replica_id": "2"', '001', m1.host + ':' + str(m1.port)
    ]

    connections = [
        m1.host + ':' + str(m1.port) + ':' + DN_DM + ':' + PW_DM,
        m2.host + ':' + str(m2.port) + ':' + DN_DM + ':' + PW_DM
    ]

    args = FakeArgs()
    args.connections = connections
    args.aliases = None
    args.json = False

    log.info('Run replication monitor with connections option')
    get_repl_monitor_info(m1, DEFAULT_SUFFIX, log, args)
    (host_m1, host_m2) = get_hostnames_from_log(m1.port, m2.port)
    check_value_in_log_and_reset(content_list,
                                 connection_content,
                                 error_list=error_list)

    # Prepare the data for next tests
    aliases = [
        'M1=' + host_m1 + ':' + str(m1.port),
        'M2=' + host_m2 + ':' + str(m2.port)
    ]

    alias_content = [
        'Supplier: M1 (' + host_m1 + ':' + str(m1.port) + ')',
        'Supplier: M2 (' + host_m2 + ':' + str(m2.port) + ')'
    ]

    dsrc_content = '[repl-monitor-connections]\n' \
                   'connection1 = ' + m1.host + ':' + str(m1.port) + ':' + DN_DM + ':' + PW_DM + '\n' \
                   'connection2 = ' + m2.host + ':' + str(m2.port) + ':' + DN_DM + ':' + PW_DM + '\n' \
                   '\n' \
                   '[repl-monitor-aliases]\n' \
                   'M1 = ' + host_m1 + ':' + str(m1.port) + '\n' \
                   'M2 = ' + host_m2 + ':' + str(m2.port)

    log.info('Run replication monitor with aliases option')
    args.aliases = aliases
    get_repl_monitor_info(m1, DEFAULT_SUFFIX, log, args)
    check_value_in_log_and_reset(content_list, alias_content)

    log.info('Run replication monitor with --json option')
    args.aliases = None
    args.json = True
    get_repl_monitor_info(m1, DEFAULT_SUFFIX, log, args)
    check_value_in_log_and_reset(json_list)

    with open(os.path.expanduser(DSRC_HOME), 'w+') as f:
        f.write(dsrc_content)

    args.connections = None
    args.aliases = None
    args.json = False

    log.info('Run replication monitor when .dsrc file is present with content')
    get_repl_monitor_info(m1, DEFAULT_SUFFIX, log, args)
    check_value_in_log_and_reset(content_list, alias_content)
    os.remove(os.path.expanduser(DSRC_HOME))

    log.info(
        'Run replication monitor with connections option as if using dsconf CLI'
    )
    # Perform same test than steps 2 test but without using directly the topology instance.
    # but with an instance similar to those than dsconf cli generates:
    # step 2 args
    args.connections = connections
    args.aliases = None
    args.json = False
    # args needed to generate an instance with dsrc_arg_concat
    args.instance = 'master1'
    args.basedn = None
    args.binddn = None
    args.bindpw = None
    args.pwdfile = None
    args.prompt = False
    args.starttls = False
    dsrc_inst = dsrc_arg_concat(args, None)
    inst = connect_instance(dsrc_inst, True, args)
    get_repl_monitor_info(inst, DEFAULT_SUFFIX, log, args)
    check_value_in_log_and_reset(content_list,
                                 connection_content,
                                 error_list=error_list)
Exemplo n.º 3
0
def test_retrocl_exclude_attr_mod(topology_st):
    """ Test exclude attribute feature of the retrocl plugin for mod operation

    :id: f6bef689-685b-4f86-a98d-f7e6b1fcada3

    :setup: Standalone instance

    :steps:
        1. Enable dynamic plugins
        2. Confige retro changelog plugin
        3. Add user1 entry
        4. Ensure entry attrs are in the changelog
        5. Exclude an attr
        6. Modify user1 entry
        7. Ensure excluded attr is not in the changelog

    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
    """

    st = topology_st.standalone

    log.info('Configure retrocl plugin')
    rcl = RetroChangelogPlugin(st)
    rcl.disable()
    rcl.enable()
    rcl.replace('nsslapd-attribute', 'nsuniqueid:targetUniqueId')

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    users = UserAccounts(st, DEFAULT_SUFFIX)

    log.info('Adding user1')
    try:
        user1 = users.create(
            properties={
                'sn': '1',
                'cn': 'user 1',
                'uid': 'user1',
                'uidNumber': '11',
                'gidNumber': '111',
                'givenname': 'user1',
                'homePhone': '0861234567',
                'carLicense': '131D16674',
                'mail': '*****@*****.**',
                'homeDirectory': '/home/user1',
                'userpassword': USER_PW
            })
    except ldap.ALREADY_EXISTS:
        user1 = UserAccount(st, dn=USER1_DN)
    except ldap.LDAPError as e:
        log.error("Failed to add user1: " + str(e))

    log.info(
        'Verify homePhone and carLicense attrs are in the changelog changestring'
    )
    try:
        retro_changelog_suffix = DSLdapObjects(st, basedn=RETROCL_SUFFIX)
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
    assert len(cllist) > 0
    if cllist[0].present('changes'):
        clstr = str(cllist[0].get_attr_vals_utf8('changes'))
        assert ATTR_HOMEPHONE in clstr
        assert ATTR_CARLICENSE in clstr

    log.info('Excluding attribute ' + ATTR_CARLICENSE)
    args = FakeArgs()
    args.connections = [
        st.host + ':' + str(st.port) + ':' + DN_DM + ':' + PW_DM
    ]
    args.instance = 'standalone1'
    args.basedn = None
    args.binddn = None
    args.starttls = False
    args.pwdfile = None
    args.bindpw = None
    args.prompt = False
    args.exclude_attrs = ATTR_CARLICENSE
    args.func = retrochangelog_add
    dsrc_inst = dsrc_arg_concat(args, None)
    inst = connect_instance(dsrc_inst, False, args)
    result = args.func(inst, None, log, args)
    disconnect_instance(inst)
    assert result is None

    log.info('Restarting instance')
    try:
        st.restart()
    except ldap.LDAPError as e:
        ldap.error('Failed to restart instance ' + e.args[0]['desc'])
        assert False

    log.info('Modify user1 carLicense attribute')
    try:
        user1.replace(ATTR_CARLICENSE, "123WX321")
    except ldap.LDAPError as e:
        log.fatal(
            'test_retrocl_exclude_attr_mod: Failed to update user1 attribute: error '
            + e.message['desc'])
        assert False

    log.info('Verify carLicense attr is not in the changelog changestring')
    try:
        cllist = retro_changelog_suffix.filter(f'(targetDn={USER1_DN})')
        assert len(cllist) > 0
        # There will be 2 entries in the changelog for this user, we are only
        #interested in the second one, the modify operation.
        if cllist[1].present('changes'):
            clstr = str(cllist[1].get_attr_vals_utf8('changes'))
            assert ATTR_CARLICENSE not in clstr
    except ldap.LDAPError as e:
        log.fatal("Changelog search failed, error: " + str(e))
        assert False
Exemplo n.º 4
0
def test_dsrc(topo, setup):
    """Test "dsctl dsrc" command

    :id: 0610de6c-e167-4761-bdab-3e677b2d44bb
    :setup: Standalone Instance
    :steps:
        1. Test creation works
        2. Test creating duplicate section
        3. Test adding an additional inst config works
        4. Test removing an instance works
        5. Test modify works
        6. Test delete works
        7. Test display fails when no file is present

    :expectedresults:
        1. Success
        2. Success
        3. Success
        4. Success
        5. Success
        6. Success
        7. Success
    """

    inst = topo.standalone
    serverid = inst.serverid
    second_inst_name = "Second"
    second_inst_basedn = "o=second"
    different_suffix = "o=different"

    # Setup our args
    args = FakeArgs()
    args.basedn = DEFAULT_SUFFIX
    args.binddn = DN_DM
    args.json = None
    args.uri = None
    args.saslmech = None
    args.tls_cacertdir = None
    args.tls_cert = None
    args.tls_key = None
    args.tls_reqcert = None
    args.starttls = None
    args.cancel_starttls = None
    args.pwdfile = None
    args.do_it = True

    # Create a dsrc configuration entry
    create_dsrc(inst, log, args)
    display_dsrc(inst, topo.logcap.log, args)
    assert topo.logcap.contains("basedn = " + args.basedn)
    assert topo.logcap.contains("binddn = " + args.binddn)
    assert topo.logcap.contains("[" + serverid + "]")
    topo.logcap.flush()

    # Attempt to add duplicate instance section
    with pytest.raises(ValueError):
        create_dsrc(inst, log, args)

    # Test adding a second instance works correctly
    inst.serverid = second_inst_name
    args.basedn = second_inst_basedn
    create_dsrc(inst, log, args)
    display_dsrc(inst, topo.logcap.log, args)
    assert topo.logcap.contains("basedn = " + args.basedn)
    assert topo.logcap.contains("[" + second_inst_name + "]")
    topo.logcap.flush()

    # Delete second instance
    delete_dsrc(inst, log, args)
    inst.serverid = serverid  # Restore original instance name
    display_dsrc(inst, topo.logcap.log, args)
    assert not topo.logcap.contains("[" + second_inst_name + "]")
    assert not topo.logcap.contains("basedn = " + args.basedn)
    # Make sure first instance config is still present
    assert topo.logcap.contains("[" + serverid + "]")
    assert topo.logcap.contains("binddn = " + args.binddn)
    topo.logcap.flush()

    # Modify the config
    args.basedn = different_suffix
    modify_dsrc(inst, log, args)
    display_dsrc(inst, topo.logcap.log, args)
    assert topo.logcap.contains(different_suffix)
    topo.logcap.flush()

    # Remove an arg from the config
    args.basedn = ""
    modify_dsrc(inst, log, args)
    display_dsrc(inst, topo.logcap.log, args)
    assert not topo.logcap.contains(different_suffix)
    topo.logcap.flush()

    # Remove the last entry, which should delete the file
    delete_dsrc(inst, log, args)
    dsrc_file = f'{expanduser("~")}/.dsrc'
    assert not os.path.exists(dsrc_file)

    # Make sure display fails
    with pytest.raises(ValueError):
        display_dsrc(inst, log, args)