tests/samba-tool: add tests for new computer management commands
[Samba.git] / python / samba / tests / samba_tool / computer.py
blob8c378b8e51a5c501e784885b0950b26a05f46d32
1 # Unix SMB/CIFS implementation.
3 # Copyright (C) Bjoern Baumbach <bb@sernet.de> 2018
5 # based on group.py:
6 # Copyright (C) Michael Adam 2012
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/>.
22 import os
23 import ldb
24 from samba.tests.samba_tool.base import SambaToolCmdTest
25 from samba import dsdb
27 class ComputerCmdTestCase(SambaToolCmdTest):
28 """Tests for samba-tool computer subcommands"""
29 computers = []
30 samdb = None
32 def setUp(self):
33 super(ComputerCmdTestCase, self).setUp()
34 self.samdb = self.getSamDB("-H", "ldap://%s" % os.environ["DC_SERVER"],
35 "-U%s%%%s" % (os.environ["DC_USERNAME"], os.environ["DC_PASSWORD"]))
36 self.computers = []
37 self.computers.append(self._randomComputer({"name": "testcomputer1"}))
38 self.computers.append(self._randomComputer({"name": "testcomputer2"}))
39 self.computers.append(self._randomComputer({"name": "testcomputer3$"}))
40 self.computers.append(self._randomComputer({"name": "testcomputer4$"}))
42 # setup the 4 computers and ensure they are correct
43 for computer in self.computers:
44 (result, out, err) = self._create_computer(computer)
46 self.assertCmdSuccess(result, out, err)
47 self.assertEquals(err, "", "There shouldn't be any error message")
48 self.assertIn("Computer '%s' created successfully" %
49 computer["name"], out)
51 found = self._find_computer(computer["name"])
53 self.assertIsNotNone(found)
55 expectedname = computer["name"].rstrip('$')
56 expectedsamaccountname = computer["name"]
57 if not computer["name"].endswith('$'):
58 expectedsamaccountname = "%s$" % computer["name"]
59 self.assertEquals("%s" % found.get("name"), expectedname)
60 self.assertEquals("%s" % found.get("sAMAccountName"),
61 expectedsamaccountname)
62 self.assertEquals("%s" % found.get("description"),
63 computer["description"])
65 def tearDown(self):
66 super(ComputerCmdTestCase, self).tearDown()
67 # clean up all the left over computers, just in case
68 for computer in self.computers:
69 if self._find_computer(computer["name"]):
70 (result, out, err) = self.runsubcmd("computer", "delete",
71 "%s" % computer["name"])
72 self.assertCmdSuccess(result, out, err,
73 "Failed to delete computer '%s'" %
74 computer["name"])
77 def test_newcomputer(self):
78 """This tests the "computer create" and "computer delete" commands"""
79 # try to create all the computers again, this should fail
80 for computer in self.computers:
81 (result, out, err) = self._create_computer(computer)
82 self.assertCmdFail(result, "Succeeded to create existing computer")
83 self.assertIn("already exists", err)
85 # try to delete all the computers we just created
86 for computer in self.computers:
87 (result, out, err) = self.runsubcmd("computer", "delete", "%s" %
88 computer["name"])
89 self.assertCmdSuccess(result, out, err,
90 "Failed to delete computer '%s'" %
91 computer["name"])
92 found = self._find_computer(computer["name"])
93 self.assertIsNone(found,
94 "Deleted computer '%s' still exists" %
95 computer["name"])
97 # test creating computers
98 for computer in self.computers:
99 (result, out, err) = self.runsubcmd(
100 "computer", "create", "%s" % computer["name"],
101 "--description=%s" % computer["description"])
103 self.assertCmdSuccess(result, out, err)
104 self.assertEquals(err, "", "There shouldn't be any error message")
105 self.assertIn("Computer '%s' created successfully" %
106 computer["name"], out)
108 found = self._find_computer(computer["name"])
110 expectedname = computer["name"].rstrip('$')
111 expectedsamaccountname = computer["name"]
112 if not computer["name"].endswith('$'):
113 expectedsamaccountname = "%s$" % computer["name"]
114 self.assertEquals("%s" % found.get("name"), expectedname)
115 self.assertEquals("%s" % found.get("sAMAccountName"),
116 expectedsamaccountname)
117 self.assertEquals("%s" % found.get("description"),
118 computer["description"])
120 def test_list(self):
121 (result, out, err) = self.runsubcmd("computer", "list")
122 self.assertCmdSuccess(result, out, err, "Error running list")
124 search_filter = ("(sAMAccountType=%u)" %
125 dsdb.ATYPE_WORKSTATION_TRUST)
127 computerlist = self.samdb.search(base=self.samdb.domain_dn(),
128 scope=ldb.SCOPE_SUBTREE,
129 expression=search_filter,
130 attrs=["samaccountname"])
132 self.assertTrue(len(computerlist) > 0, "no computers found in samdb")
134 for computerobj in computerlist:
135 name = computerobj.get("samaccountname", idx=0)
136 found = self.assertMatch(out, name,
137 "computer '%s' not found" % name)
139 def test_move(self):
140 parentou = self._randomOU({"name": "parentOU"})
141 (result, out, err) = self._create_ou(parentou)
142 self.assertCmdSuccess(result, out, err)
144 for computer in self.computers:
145 olddn = self._find_computer(computer["name"]).get("dn")
147 (result, out, err) = self.runsubcmd("computer", "move",
148 "%s" % computer["name"],
149 "OU=%s" % parentou["name"])
150 self.assertCmdSuccess(result, out, err,
151 "Failed to move computer '%s'" %
152 computer["name"])
153 self.assertEquals(err, "", "There shouldn't be any error message")
154 self.assertIn('Moved computer "%s"' % computer["name"], out)
156 found = self._find_computer(computer["name"])
157 self.assertNotEquals(found.get("dn"), olddn,
158 ("Moved computer '%s' still exists with the "
159 "same dn" % computer["name"]))
160 computername = computer["name"].rstrip('$')
161 newexpecteddn = ldb.Dn(self.samdb,
162 "CN=%s,OU=%s,%s" %
163 (computername, parentou["name"],
164 self.samdb.domain_dn()))
165 self.assertEquals(found.get("dn"), newexpecteddn,
166 "Moved computer '%s' does not exist" %
167 computer["name"])
169 (result, out, err) = self.runsubcmd("computer", "move",
170 "%s" % computer["name"],
171 "%s" % olddn.parent())
172 self.assertCmdSuccess(result, out, err,
173 "Failed to move computer '%s'" %
174 computer["name"])
176 (result, out, err) = self.runsubcmd("ou", "delete",
177 "OU=%s" % parentou["name"])
178 self.assertCmdSuccess(result, out, err,
179 "Failed to delete ou '%s'" % parentou["name"])
181 def _randomComputer(self, base={}):
182 """create a computer with random attribute values, you can specify base
183 attributes"""
185 computer = {
186 "name": self.randomName(),
187 "description": self.randomName(count=100),
189 computer.update(base)
190 return computer
192 def _randomOU(self, base={}):
193 """create an ou with random attribute values, you can specify base
194 attributes"""
196 ou = {
197 "name": self.randomName(),
198 "description": self.randomName(count=100),
200 ou.update(base)
201 return ou
203 def _create_computer(self, computer):
204 return self.runsubcmd("computer", "create", "%s" % computer["name"],
205 "--description=%s" % computer["description"])
207 def _create_ou(self, ou):
208 return self.runsubcmd("ou", "create", "OU=%s" % ou["name"],
209 "--description=%s" % ou["description"])
211 def _find_computer(self, name):
212 samaccountname = name
213 if not name.endswith('$'):
214 samaccountname = "%s$" % name
215 search_filter = ("(&(sAMAccountName=%s)(objectCategory=%s,%s))" %
216 (ldb.binary_encode(samaccountname),
217 "CN=Computer,CN=Schema,CN=Configuration",
218 self.samdb.domain_dn()))
219 computerlist = self.samdb.search(base=self.samdb.domain_dn(),
220 scope=ldb.SCOPE_SUBTREE,
221 expression=search_filter, attrs=[])
222 if computerlist:
223 return computerlist[0]
224 else:
225 return None