2 # -*- coding: utf-8 -*-
4 # Tests various schema replication scenarios
6 # Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2011
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # export DC1=dc1_dns_name
25 # export DC2=dc2_dns_name
26 # export SUBUNITRUN=$samba4srcdir/scripting/bin/subunitrun
27 # PYTHONPATH="$PYTHONPATH:$samba4srcdir/torture/drs/python" $SUBUNITRUN replica_sync -U"$DOMAIN/$DC_USERNAME"%"$DC_PASSWORD"
36 class DrsReplicaSyncTestCase(drs_base
.DrsBaseTestCase
):
37 """Intended as a black box test case for DsReplicaSync
38 implementation. It should test the behavior of this
39 case in cases when inbound replication is disabled"""
42 super(DrsReplicaSyncTestCase
, self
).setUp()
45 # re-enable replication
46 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
47 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
48 super(DrsReplicaSyncTestCase
, self
).tearDown()
50 def test_ReplEnabled(self
):
51 """Tests we can replicate when replication is enabled"""
52 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
53 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=False)
55 def test_ReplDisabled(self
):
56 """Tests we cann't replicate when replication is disabled"""
57 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
59 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=False)
60 except samba
.tests
.BlackboxProcessError
, e
:
61 self
.assertTrue('WERR_DS_DRA_SINK_DISABLED' in e
.stderr
)
63 self
.fail("'drs replicate' command should have failed!")
65 def test_ReplDisabledForced(self
):
66 """Tests we can force replicate when replication is disabled"""
67 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
68 out
= self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True)
70 def test_ReplLocal(self
):
71 """Tests we can replicate direct to the local db"""
72 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
73 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=False, local
=True, full_sync
=True)
75 def _create_ou(self
, samdb
, name
):
78 objectClass: organizationalUnit
79 """ % (name
, self
.domain_dn
)
81 res
= samdb
.search(base
="%s,%s" % (name
, self
.domain_dn
),
82 scope
=SCOPE_BASE
, attrs
=["objectGUID"])
83 return self
._GUID
_string
(res
[0]["objectGUID"][0])
85 def _check_deleted(self
, sam_ldb
, guid
):
86 # search the user by guid as it may be deleted
87 expression
= "(objectGUID=%s)" % guid
88 res
= sam_ldb
.search(base
=self
.domain_dn
,
89 expression
=expression
,
90 controls
=["show_deleted:1"],
91 attrs
=["isDeleted", "objectCategory", "ou"])
92 self
.assertEquals(len(res
), 1)
94 # Deleted Object base DN
95 dodn
= self
._deleted
_objects
_dn
(sam_ldb
)
96 # now check properties of the user
97 name_cur
= ou_cur
["ou"][0]
98 self
.assertEquals(ou_cur
["isDeleted"][0],"TRUE")
99 self
.assertTrue(not("objectCategory" in ou_cur
))
100 self
.assertTrue(dodn
in str(ou_cur
["dn"]),
101 "OU %s is deleted but it is not located under %s!" % (name_cur
, dodn
))
103 def test_ReplConflictsFullSync(self
):
104 """Tests that objects created in conflict become conflict DNs (honour full sync override)"""
105 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
106 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
108 # Create conflicting objects on DC1 and DC2, with DC1 object created first
109 ou1
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Full Sync")
110 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Full Sync")
112 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
113 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, local
=True, forced
=True, full_sync
=True)
114 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
116 # Check that DC2 got the DC1 object, and one or other object was make into conflict
117 res1
= self
.ldb_dc2
.search(base
="<GUID=%s>" % ou1
,
118 scope
=SCOPE_BASE
, attrs
=["name"])
119 res2
= self
.ldb_dc2
.search(base
="<GUID=%s>" % ou2
,
120 scope
=SCOPE_BASE
, attrs
=["name"])
121 print res1
[0]["name"][0]
122 print res2
[0]["name"][0]
123 self
.assertTrue('CNF:%s' % ou1
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2
in str(res2
[0]["name"][0]))
124 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc2
, self
.domain_dn
) not in str(res1
[0].dn
))
125 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc2
, self
.domain_dn
) not in str(res2
[0].dn
))
127 # Delete both objects by GUID on DC1
129 self
.ldb_dc2
.delete('<GUID=%s>' % ou1
)
130 self
.ldb_dc2
.delete('<GUID=%s>' % ou2
)
132 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
133 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
134 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=True)
136 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
137 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
138 # Check deleted on DC2
139 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
140 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
142 def test_ReplConflictsRemoteWin(self
):
143 """Tests that objects created in conflict become conflict DNs"""
144 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
145 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
147 # Create conflicting objects on DC1 and DC2, with DC1 object created first
148 ou1
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Remote Conflict")
149 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Remote Conflict")
151 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
152 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
153 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
155 # Check that DC2 got the DC1 object, and one or other object was make into conflict
156 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1
,
157 scope
=SCOPE_BASE
, attrs
=["name"])
158 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2
,
159 scope
=SCOPE_BASE
, attrs
=["name"])
160 print res1
[0]["name"][0]
161 print res2
[0]["name"][0]
162 self
.assertTrue('CNF:%s' % ou1
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2
in str(res2
[0]["name"][0]))
163 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res1
[0].dn
))
164 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res2
[0].dn
))
166 # Delete both objects by GUID on DC1
168 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
169 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
171 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
172 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
173 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
175 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
176 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
177 # Check deleted on DC2
178 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
179 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
181 def test_ReplConflictsLocalWin(self
):
182 """Tests that objects created in conflict become conflict DNs"""
183 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
184 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
186 # Create conflicting objects on DC1 and DC2, with DC2 object created first
187 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Local Conflict")
188 ou1
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Local Conflict")
190 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
191 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
192 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
194 # Check that DC2 got the DC1 object, and one or other object was make into conflict
195 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1
,
196 scope
=SCOPE_BASE
, attrs
=["name"])
197 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2
,
198 scope
=SCOPE_BASE
, attrs
=["name"])
199 print res1
[0]["name"][0]
200 print res2
[0]["name"][0]
201 self
.assertTrue('CNF:%s' % ou1
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2
in str(res2
[0]["name"][0]))
202 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res1
[0].dn
))
203 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res2
[0].dn
))
205 # Delete both objects by GUID on DC1
207 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
208 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
210 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
211 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
212 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
214 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
215 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
216 # Check deleted on DC2
217 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
218 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
220 def test_ReplConflictsRenameRemoteWin(self
):
221 """Tests that objects created in conflict become conflict DNs"""
222 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
223 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
225 # Create conflicting objects on DC1 and DC2, with DC1 object created first
226 ou1
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Remote Rename Conflict")
227 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Remote Rename Conflict 2")
229 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
230 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
231 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
233 self
.ldb_dc1
.rename("<GUID=%s>" % ou1
, "OU=Test Remote Rename Conflict 3,%s" % self
.domain_dn
)
234 self
.ldb_dc2
.rename("<GUID=%s>" % ou2
, "OU=Test Remote Rename Conflict 3,%s" % self
.domain_dn
)
236 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
237 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
238 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
240 # Check that DC2 got the DC1 object, and one or other object was make into conflict
241 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1
,
242 scope
=SCOPE_BASE
, attrs
=["name"])
243 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2
,
244 scope
=SCOPE_BASE
, attrs
=["name"])
245 print res1
[0]["name"][0]
246 print res2
[0]["name"][0]
247 self
.assertTrue('CNF:%s' % ou1
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2
in str(res2
[0]["name"][0]))
248 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res1
[0].dn
))
249 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res2
[0].dn
))
251 # Delete both objects by GUID on DC1
253 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
254 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
256 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
257 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
258 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
260 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
261 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
262 # Check deleted on DC2
263 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
264 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
266 def test_ReplConflictsRenameLocalWin(self
):
267 """Tests that objects created in conflict become conflict DNs"""
268 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
269 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
271 # Create conflicting objects on DC1 and DC2, with DC1 object created first
272 ou1
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Rename Local Conflict")
273 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Rename Local Conflict 2")
275 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
276 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
277 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
279 self
.ldb_dc2
.rename("<GUID=%s>" % ou2
, "OU=Test Rename Local Conflict 3,%s" % self
.domain_dn
)
280 self
.ldb_dc1
.rename("<GUID=%s>" % ou1
, "OU=Test Rename Local Conflict 3,%s" % self
.domain_dn
)
282 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
283 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
284 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
286 # Check that DC2 got the DC1 object, and one or other object was make into conflict
287 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1
,
288 scope
=SCOPE_BASE
, attrs
=["name"])
289 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2
,
290 scope
=SCOPE_BASE
, attrs
=["name"])
291 print res1
[0]["name"][0]
292 print res2
[0]["name"][0]
293 self
.assertTrue('CNF:%s' % ou1
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2
in str(res2
[0]["name"][0]))
294 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res1
[0].dn
))
295 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) not in str(res2
[0].dn
))
297 # Delete both objects by GUID on DC1
299 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
300 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
302 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
303 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
304 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
306 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
307 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
308 # Check deleted on DC2
309 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
310 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
312 def test_ReplLostAndFound(self
):
313 """Tests that objects created under a OU deleted eleswhere end up in lostAndFound"""
314 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
315 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
317 # Create two OUs on DC2
318 ou1
= self
._create
_ou
(self
.ldb_dc2
, "OU=Deleted parent")
319 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Deleted parent 2")
321 # replicate them from DC2 to DC1
322 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
323 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
324 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
326 # Delete both objects by GUID on DC1
328 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
329 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
331 # Create children on DC2
332 ou1_child
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Child,OU=Deleted parent")
333 ou2_child
= self
._create
_ou
(self
.ldb_dc2
, "OU=Test Child,OU=Deleted parent 2")
336 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
337 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
338 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
340 # Check the sub-OUs are now in lostAndFound and the first one is a conflict DN
342 # Check that DC2 got the DC1 object, and one or other object was make into conflict
343 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1_child
,
344 scope
=SCOPE_BASE
, attrs
=["name"])
345 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2_child
,
346 scope
=SCOPE_BASE
, attrs
=["name"])
347 print res1
[0]["name"][0]
348 print res2
[0]["name"][0]
349 self
.assertTrue('CNF:%s' % ou1_child
in str(res1
[0]["name"][0]) or 'CNF:%s' % ou2_child
in str(res2
[0]["name"][0]))
350 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) in str(res1
[0].dn
))
351 self
.assertTrue(self
._lost
_and
_found
_dn
(self
.ldb_dc1
, self
.domain_dn
) in str(res2
[0].dn
))
353 # Delete all objects by GUID on DC1
355 self
.ldb_dc1
.delete('<GUID=%s>' % ou1_child
)
356 self
.ldb_dc1
.delete('<GUID=%s>' % ou2_child
)
358 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
359 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
360 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
363 # Check all deleted on DC1
364 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
365 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
366 self
._check
_deleted
(self
.ldb_dc1
, ou1_child
)
367 self
._check
_deleted
(self
.ldb_dc1
, ou2_child
)
368 # Check all deleted on DC2
369 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
370 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
371 self
._check
_deleted
(self
.ldb_dc2
, ou1_child
)
372 self
._check
_deleted
(self
.ldb_dc2
, ou2_child
)
374 def test_ReplRenames(self
):
375 """Tests that objects created under a OU deleted eleswhere end up in lostAndFound"""
376 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
377 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
379 # Create two OUs on DC2
380 ou1
= self
._create
_ou
(self
.ldb_dc2
, "OU=Original parent")
381 ou2
= self
._create
_ou
(self
.ldb_dc2
, "OU=Original parent 2")
383 # replicate them from DC2 to DC1
384 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
385 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
386 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
388 # Create children on DC1
389 ou1_child
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Child,OU=Original parent")
390 ou2_child
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Child 2,OU=Original parent")
391 ou3_child
= self
._create
_ou
(self
.ldb_dc1
, "OU=Test Case Child,OU=Original parent")
393 # replicate them from DC1 to DC2
394 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
395 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
396 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
398 self
.ldb_dc1
.rename("<GUID=%s>" % ou2_child
, "OU=Test Child 3,OU=Original parent 2,%s" % self
.domain_dn
)
399 self
.ldb_dc1
.rename("<GUID=%s>" % ou1_child
, "OU=Test Child 2,OU=Original parent 2,%s" % self
.domain_dn
)
400 self
.ldb_dc1
.rename("<GUID=%s>" % ou2_child
, "OU=Test Child,OU=Original parent 2,%s" % self
.domain_dn
)
401 self
.ldb_dc1
.rename("<GUID=%s>" % ou3_child
, "OU=Test CASE Child,OU=Original parent,%s" % self
.domain_dn
)
402 self
.ldb_dc2
.rename("<GUID=%s>" % ou2
, "OU=Original parent 3,%s" % self
.domain_dn
)
403 self
.ldb_dc2
.rename("<GUID=%s>" % ou1
, "OU=Original parent 2,%s" % self
.domain_dn
)
405 # replicate them from DC1 to DC2
406 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
407 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
408 self
._disable
_inbound
_repl
(self
.dnsname_dc2
)
410 # Check the sub-OUs are now under Original Parent 3 (original
411 # parent 2 for Test CASE Child), and both have the right names
413 # Check that DC2 got the DC1 object, and the renames are all correct
414 res1
= self
.ldb_dc2
.search(base
="<GUID=%s>" % ou1_child
,
415 scope
=SCOPE_BASE
, attrs
=["name"])
416 res2
= self
.ldb_dc2
.search(base
="<GUID=%s>" % ou2_child
,
417 scope
=SCOPE_BASE
, attrs
=["name"])
418 res3
= self
.ldb_dc2
.search(base
="<GUID=%s>" % ou3_child
,
419 scope
=SCOPE_BASE
, attrs
=["name"])
423 self
.assertEqual('Test Child 2', res1
[0]["name"][0])
424 self
.assertEqual('Test Child', res2
[0]["name"][0])
425 self
.assertEqual('Test CASE Child', res3
[0]["name"][0])
426 self
.assertEqual(str(res1
[0].dn
), "OU=Test Child 2,OU=Original parent 3,%s" % self
.domain_dn
)
427 self
.assertEqual(str(res2
[0].dn
), "OU=Test Child,OU=Original parent 3,%s" % self
.domain_dn
)
428 self
.assertEqual(str(res3
[0].dn
), "OU=Test CASE Child,OU=Original parent 2,%s" % self
.domain_dn
)
430 # replicate them from DC2 to DC1
431 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
432 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc1
, fromDC
=self
.dnsname_dc2
, forced
=True, full_sync
=False)
433 self
._disable
_inbound
_repl
(self
.dnsname_dc1
)
435 # Check that DC1 got the DC2 object, and the renames are all correct
436 res1
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou1_child
,
437 scope
=SCOPE_BASE
, attrs
=["name"])
438 res2
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou2_child
,
439 scope
=SCOPE_BASE
, attrs
=["name"])
440 res3
= self
.ldb_dc1
.search(base
="<GUID=%s>" % ou3_child
,
441 scope
=SCOPE_BASE
, attrs
=["name"])
445 self
.assertEqual('Test Child 2', res1
[0]["name"][0])
446 self
.assertEqual('Test Child', res2
[0]["name"][0])
447 self
.assertEqual('Test CASE Child', res3
[0]["name"][0])
448 self
.assertEqual(str(res1
[0].dn
), "OU=Test Child 2,OU=Original parent 3,%s" % self
.domain_dn
)
449 self
.assertEqual(str(res2
[0].dn
), "OU=Test Child,OU=Original parent 3,%s" % self
.domain_dn
)
450 self
.assertEqual(str(res3
[0].dn
), "OU=Test CASE Child,OU=Original parent 2,%s" % self
.domain_dn
)
452 # Delete all objects by GUID on DC1
454 self
.ldb_dc1
.delete('<GUID=%s>' % ou1_child
)
455 self
.ldb_dc1
.delete('<GUID=%s>' % ou2_child
)
456 self
.ldb_dc1
.delete('<GUID=%s>' % ou3_child
)
457 self
.ldb_dc1
.delete('<GUID=%s>' % ou1
)
458 self
.ldb_dc1
.delete('<GUID=%s>' % ou2
)
460 self
._enable
_inbound
_repl
(self
.dnsname_dc1
)
461 self
._enable
_inbound
_repl
(self
.dnsname_dc2
)
462 self
._net
_drs
_replicate
(DC
=self
.dnsname_dc2
, fromDC
=self
.dnsname_dc1
, forced
=True, full_sync
=False)
465 # Check all deleted on DC1
466 self
._check
_deleted
(self
.ldb_dc1
, ou1
)
467 self
._check
_deleted
(self
.ldb_dc1
, ou2
)
468 self
._check
_deleted
(self
.ldb_dc1
, ou1_child
)
469 self
._check
_deleted
(self
.ldb_dc1
, ou2_child
)
470 self
._check
_deleted
(self
.ldb_dc1
, ou3_child
)
471 # Check all deleted on DC2
472 self
._check
_deleted
(self
.ldb_dc2
, ou1
)
473 self
._check
_deleted
(self
.ldb_dc2
, ou2
)
474 self
._check
_deleted
(self
.ldb_dc2
, ou1_child
)
475 self
._check
_deleted
(self
.ldb_dc2
, ou2_child
)
476 self
._check
_deleted
(self
.ldb_dc2
, ou3_child
)