Statistics
| Branch: | Tag: | Revision:

root / test / py / ganeti.tools.prepare_node_join_unittest.py @ 91c17910

History | View | Annotate | Download (8.7 kB)

1 d12b9f66 Michael Hanselmann
#!/usr/bin/python
2 d12b9f66 Michael Hanselmann
#
3 d12b9f66 Michael Hanselmann
4 d12b9f66 Michael Hanselmann
# Copyright (C) 2012 Google Inc.
5 d12b9f66 Michael Hanselmann
#
6 d12b9f66 Michael Hanselmann
# This program is free software; you can redistribute it and/or modify
7 d12b9f66 Michael Hanselmann
# it under the terms of the GNU General Public License as published by
8 d12b9f66 Michael Hanselmann
# the Free Software Foundation; either version 2 of the License, or
9 d12b9f66 Michael Hanselmann
# (at your option) any later version.
10 d12b9f66 Michael Hanselmann
#
11 d12b9f66 Michael Hanselmann
# This program is distributed in the hope that it will be useful, but
12 d12b9f66 Michael Hanselmann
# WITHOUT ANY WARRANTY; without even the implied warranty of
13 d12b9f66 Michael Hanselmann
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 d12b9f66 Michael Hanselmann
# General Public License for more details.
15 d12b9f66 Michael Hanselmann
#
16 d12b9f66 Michael Hanselmann
# You should have received a copy of the GNU General Public License
17 d12b9f66 Michael Hanselmann
# along with this program; if not, write to the Free Software
18 d12b9f66 Michael Hanselmann
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 d12b9f66 Michael Hanselmann
# 02110-1301, USA.
20 d12b9f66 Michael Hanselmann
21 d12b9f66 Michael Hanselmann
22 d12b9f66 Michael Hanselmann
"""Script for testing ganeti.tools.prepare_node_join"""
23 d12b9f66 Michael Hanselmann
24 d12b9f66 Michael Hanselmann
import unittest
25 d12b9f66 Michael Hanselmann
import shutil
26 d12b9f66 Michael Hanselmann
import tempfile
27 d12b9f66 Michael Hanselmann
import os.path
28 d12b9f66 Michael Hanselmann
import OpenSSL
29 d12b9f66 Michael Hanselmann
30 d12b9f66 Michael Hanselmann
from ganeti import errors
31 d12b9f66 Michael Hanselmann
from ganeti import constants
32 d12b9f66 Michael Hanselmann
from ganeti import serializer
33 d12b9f66 Michael Hanselmann
from ganeti import pathutils
34 d12b9f66 Michael Hanselmann
from ganeti import compat
35 d12b9f66 Michael Hanselmann
from ganeti import utils
36 d12b9f66 Michael Hanselmann
from ganeti.tools import prepare_node_join
37 d12b9f66 Michael Hanselmann
38 d12b9f66 Michael Hanselmann
import testutils
39 d12b9f66 Michael Hanselmann
40 d12b9f66 Michael Hanselmann
41 d12b9f66 Michael Hanselmann
_JoinError = prepare_node_join.JoinError
42 d12b9f66 Michael Hanselmann
43 d12b9f66 Michael Hanselmann
44 d12b9f66 Michael Hanselmann
class TestLoadData(unittest.TestCase):
45 d12b9f66 Michael Hanselmann
  def testNoJson(self):
46 d12b9f66 Michael Hanselmann
    self.assertRaises(errors.ParseError, prepare_node_join.LoadData, "")
47 d12b9f66 Michael Hanselmann
    self.assertRaises(errors.ParseError, prepare_node_join.LoadData, "}")
48 d12b9f66 Michael Hanselmann
49 d12b9f66 Michael Hanselmann
  def testInvalidDataStructure(self):
50 d12b9f66 Michael Hanselmann
    raw = serializer.DumpJson({
51 d12b9f66 Michael Hanselmann
      "some other thing": False,
52 d12b9f66 Michael Hanselmann
      })
53 d12b9f66 Michael Hanselmann
    self.assertRaises(errors.ParseError, prepare_node_join.LoadData, raw)
54 d12b9f66 Michael Hanselmann
55 d12b9f66 Michael Hanselmann
    raw = serializer.DumpJson([])
56 d12b9f66 Michael Hanselmann
    self.assertRaises(errors.ParseError, prepare_node_join.LoadData, raw)
57 d12b9f66 Michael Hanselmann
58 d12b9f66 Michael Hanselmann
  def testValidData(self):
59 d12b9f66 Michael Hanselmann
    raw = serializer.DumpJson({})
60 d12b9f66 Michael Hanselmann
    self.assertEqual(prepare_node_join.LoadData(raw), {})
61 d12b9f66 Michael Hanselmann
62 d12b9f66 Michael Hanselmann
63 d12b9f66 Michael Hanselmann
class TestVerifyCertificate(testutils.GanetiTestCase):
64 d12b9f66 Michael Hanselmann
  def setUp(self):
65 d12b9f66 Michael Hanselmann
    testutils.GanetiTestCase.setUp(self)
66 d12b9f66 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
67 d12b9f66 Michael Hanselmann
68 d12b9f66 Michael Hanselmann
  def tearDown(self):
69 d12b9f66 Michael Hanselmann
    testutils.GanetiTestCase.tearDown(self)
70 d12b9f66 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
71 d12b9f66 Michael Hanselmann
72 d12b9f66 Michael Hanselmann
  def testNoCert(self):
73 d12b9f66 Michael Hanselmann
    prepare_node_join.VerifyCertificate({}, _verify_fn=NotImplemented)
74 d12b9f66 Michael Hanselmann
75 d12b9f66 Michael Hanselmann
  def testGivenPrivateKey(self):
76 00ef625c Michael Hanselmann
    cert_filename = testutils.TestDataFilename("cert2.pem")
77 d12b9f66 Michael Hanselmann
    cert_pem = utils.ReadFile(cert_filename)
78 d12b9f66 Michael Hanselmann
79 d12b9f66 Michael Hanselmann
    self.assertRaises(_JoinError, prepare_node_join._VerifyCertificate,
80 0602cef3 Michael Hanselmann
                      cert_pem, _check_fn=NotImplemented)
81 d12b9f66 Michael Hanselmann
82 d12b9f66 Michael Hanselmann
  def testInvalidCertificate(self):
83 d12b9f66 Michael Hanselmann
    self.assertRaises(errors.X509CertError,
84 d12b9f66 Michael Hanselmann
                      prepare_node_join._VerifyCertificate,
85 d12b9f66 Michael Hanselmann
                      "Something that's not a certificate",
86 0602cef3 Michael Hanselmann
                      _check_fn=NotImplemented)
87 d12b9f66 Michael Hanselmann
88 0602cef3 Michael Hanselmann
  @staticmethod
89 0602cef3 Michael Hanselmann
  def _Check(cert):
90 0602cef3 Michael Hanselmann
    assert cert.get_subject()
91 0602cef3 Michael Hanselmann
92 0602cef3 Michael Hanselmann
  def testSuccessfulCheck(self):
93 00ef625c Michael Hanselmann
    cert_filename = testutils.TestDataFilename("cert1.pem")
94 0602cef3 Michael Hanselmann
    cert_pem = utils.ReadFile(cert_filename)
95 0602cef3 Michael Hanselmann
    prepare_node_join._VerifyCertificate(cert_pem, _check_fn=self._Check)
96 d12b9f66 Michael Hanselmann
97 d12b9f66 Michael Hanselmann
98 d12b9f66 Michael Hanselmann
class TestVerifyClusterName(unittest.TestCase):
99 d12b9f66 Michael Hanselmann
  def setUp(self):
100 d12b9f66 Michael Hanselmann
    unittest.TestCase.setUp(self)
101 d12b9f66 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
102 d12b9f66 Michael Hanselmann
103 d12b9f66 Michael Hanselmann
  def tearDown(self):
104 d12b9f66 Michael Hanselmann
    unittest.TestCase.tearDown(self)
105 d12b9f66 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
106 d12b9f66 Michael Hanselmann
107 d12b9f66 Michael Hanselmann
  def testNoName(self):
108 d12b9f66 Michael Hanselmann
    self.assertRaises(_JoinError, prepare_node_join.VerifyClusterName,
109 d12b9f66 Michael Hanselmann
                      {}, _verify_fn=NotImplemented)
110 d12b9f66 Michael Hanselmann
111 dffa96d6 Michael Hanselmann
  @staticmethod
112 dffa96d6 Michael Hanselmann
  def _FailingVerify(name):
113 dffa96d6 Michael Hanselmann
    assert name == "cluster.example.com"
114 dffa96d6 Michael Hanselmann
    raise errors.GenericError()
115 dffa96d6 Michael Hanselmann
116 dffa96d6 Michael Hanselmann
  def testFailingVerification(self):
117 dffa96d6 Michael Hanselmann
    data = {
118 dffa96d6 Michael Hanselmann
      constants.SSHS_CLUSTER_NAME: "cluster.example.com",
119 dffa96d6 Michael Hanselmann
      }
120 dffa96d6 Michael Hanselmann
121 dffa96d6 Michael Hanselmann
    self.assertRaises(errors.GenericError, prepare_node_join.VerifyClusterName,
122 dffa96d6 Michael Hanselmann
                      data, _verify_fn=self._FailingVerify)
123 d12b9f66 Michael Hanselmann
124 d12b9f66 Michael Hanselmann
125 d12b9f66 Michael Hanselmann
class TestUpdateSshDaemon(unittest.TestCase):
126 d12b9f66 Michael Hanselmann
  def setUp(self):
127 d12b9f66 Michael Hanselmann
    unittest.TestCase.setUp(self)
128 d12b9f66 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
129 d12b9f66 Michael Hanselmann
130 d12b9f66 Michael Hanselmann
    self.keyfiles = {
131 d12b9f66 Michael Hanselmann
      constants.SSHK_RSA:
132 340ae7da Michael Hanselmann
        (utils.PathJoin(self.tmpdir, "rsa.private"),
133 340ae7da Michael Hanselmann
         utils.PathJoin(self.tmpdir, "rsa.public")),
134 d12b9f66 Michael Hanselmann
      constants.SSHK_DSA:
135 340ae7da Michael Hanselmann
        (utils.PathJoin(self.tmpdir, "dsa.private"),
136 340ae7da Michael Hanselmann
         utils.PathJoin(self.tmpdir, "dsa.public")),
137 d12b9f66 Michael Hanselmann
      }
138 d12b9f66 Michael Hanselmann
139 d12b9f66 Michael Hanselmann
  def tearDown(self):
140 d12b9f66 Michael Hanselmann
    unittest.TestCase.tearDown(self)
141 d12b9f66 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
142 d12b9f66 Michael Hanselmann
143 d12b9f66 Michael Hanselmann
  def testNoKeys(self):
144 d12b9f66 Michael Hanselmann
    data_empty_keys = {
145 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_HOST_KEY: [],
146 d12b9f66 Michael Hanselmann
      }
147 d12b9f66 Michael Hanselmann
148 d12b9f66 Michael Hanselmann
    for data in [{}, data_empty_keys]:
149 d12b9f66 Michael Hanselmann
      for dry_run in [False, True]:
150 d12b9f66 Michael Hanselmann
        prepare_node_join.UpdateSshDaemon(data, dry_run,
151 d12b9f66 Michael Hanselmann
                                          _runcmd_fn=NotImplemented,
152 d12b9f66 Michael Hanselmann
                                          _keyfiles=NotImplemented)
153 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), [])
154 d12b9f66 Michael Hanselmann
155 d12b9f66 Michael Hanselmann
  def _TestDryRun(self, data):
156 d12b9f66 Michael Hanselmann
    prepare_node_join.UpdateSshDaemon(data, True, _runcmd_fn=NotImplemented,
157 d12b9f66 Michael Hanselmann
                                      _keyfiles=self.keyfiles)
158 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), [])
159 d12b9f66 Michael Hanselmann
160 d12b9f66 Michael Hanselmann
  def testDryRunRsa(self):
161 d12b9f66 Michael Hanselmann
    self._TestDryRun({
162 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_HOST_KEY: [
163 340ae7da Michael Hanselmann
        (constants.SSHK_RSA, "rsapriv", "rsapub"),
164 d12b9f66 Michael Hanselmann
        ],
165 d12b9f66 Michael Hanselmann
      })
166 d12b9f66 Michael Hanselmann
167 d12b9f66 Michael Hanselmann
  def testDryRunDsa(self):
168 d12b9f66 Michael Hanselmann
    self._TestDryRun({
169 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_HOST_KEY: [
170 340ae7da Michael Hanselmann
        (constants.SSHK_DSA, "dsapriv", "dsapub"),
171 d12b9f66 Michael Hanselmann
        ],
172 d12b9f66 Michael Hanselmann
      })
173 d12b9f66 Michael Hanselmann
174 d12b9f66 Michael Hanselmann
  def _RunCmd(self, fail, cmd, interactive=NotImplemented):
175 d12b9f66 Michael Hanselmann
    self.assertTrue(interactive)
176 d12b9f66 Michael Hanselmann
    self.assertEqual(cmd, [pathutils.DAEMON_UTIL, "reload-ssh-keys"])
177 d12b9f66 Michael Hanselmann
    if fail:
178 d12b9f66 Michael Hanselmann
      exit_code = constants.EXIT_FAILURE
179 d12b9f66 Michael Hanselmann
    else:
180 d12b9f66 Michael Hanselmann
      exit_code = constants.EXIT_SUCCESS
181 d12b9f66 Michael Hanselmann
    return utils.RunResult(exit_code, None, "stdout", "stderr",
182 d12b9f66 Michael Hanselmann
                           utils.ShellQuoteArgs(cmd),
183 d12b9f66 Michael Hanselmann
                           NotImplemented, NotImplemented)
184 d12b9f66 Michael Hanselmann
185 d12b9f66 Michael Hanselmann
  def _TestUpdate(self, failcmd):
186 d12b9f66 Michael Hanselmann
    data = {
187 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_HOST_KEY: [
188 340ae7da Michael Hanselmann
        (constants.SSHK_DSA, "dsapriv", "dsapub"),
189 340ae7da Michael Hanselmann
        (constants.SSHK_RSA, "rsapriv", "rsapub"),
190 d12b9f66 Michael Hanselmann
        ],
191 d12b9f66 Michael Hanselmann
      }
192 d12b9f66 Michael Hanselmann
    runcmd_fn = compat.partial(self._RunCmd, failcmd)
193 d12b9f66 Michael Hanselmann
    if failcmd:
194 d12b9f66 Michael Hanselmann
      self.assertRaises(_JoinError, prepare_node_join.UpdateSshDaemon,
195 d12b9f66 Michael Hanselmann
                        data, False, _runcmd_fn=runcmd_fn,
196 d12b9f66 Michael Hanselmann
                        _keyfiles=self.keyfiles)
197 d12b9f66 Michael Hanselmann
    else:
198 d12b9f66 Michael Hanselmann
      prepare_node_join.UpdateSshDaemon(data, False, _runcmd_fn=runcmd_fn,
199 d12b9f66 Michael Hanselmann
                                        _keyfiles=self.keyfiles)
200 d12b9f66 Michael Hanselmann
    self.assertEqual(sorted(os.listdir(self.tmpdir)), sorted([
201 340ae7da Michael Hanselmann
      "rsa.public", "rsa.private",
202 340ae7da Michael Hanselmann
      "dsa.public", "dsa.private",
203 d12b9f66 Michael Hanselmann
      ]))
204 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.tmpdir, "rsa.public")),
205 d12b9f66 Michael Hanselmann
                     "rsapub")
206 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.tmpdir, "rsa.private")),
207 d12b9f66 Michael Hanselmann
                     "rsapriv")
208 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.tmpdir, "dsa.public")),
209 d12b9f66 Michael Hanselmann
                     "dsapub")
210 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.tmpdir, "dsa.private")),
211 d12b9f66 Michael Hanselmann
                     "dsapriv")
212 d12b9f66 Michael Hanselmann
213 d12b9f66 Michael Hanselmann
  def testSuccess(self):
214 d12b9f66 Michael Hanselmann
    self._TestUpdate(False)
215 d12b9f66 Michael Hanselmann
216 d12b9f66 Michael Hanselmann
  def testFailure(self):
217 d12b9f66 Michael Hanselmann
    self._TestUpdate(True)
218 d12b9f66 Michael Hanselmann
219 d12b9f66 Michael Hanselmann
220 d12b9f66 Michael Hanselmann
class TestUpdateSshRoot(unittest.TestCase):
221 d12b9f66 Michael Hanselmann
  def setUp(self):
222 d12b9f66 Michael Hanselmann
    unittest.TestCase.setUp(self)
223 d12b9f66 Michael Hanselmann
    self.tmpdir = tempfile.mkdtemp()
224 d12b9f66 Michael Hanselmann
    self.sshdir = utils.PathJoin(self.tmpdir, ".ssh")
225 d12b9f66 Michael Hanselmann
226 d12b9f66 Michael Hanselmann
  def tearDown(self):
227 d12b9f66 Michael Hanselmann
    unittest.TestCase.tearDown(self)
228 d12b9f66 Michael Hanselmann
    shutil.rmtree(self.tmpdir)
229 d12b9f66 Michael Hanselmann
230 d12b9f66 Michael Hanselmann
  def _GetHomeDir(self, user):
231 d12b9f66 Michael Hanselmann
    self.assertEqual(user, constants.SSH_LOGIN_USER)
232 d12b9f66 Michael Hanselmann
    return self.tmpdir
233 d12b9f66 Michael Hanselmann
234 d12b9f66 Michael Hanselmann
  def testNoKeys(self):
235 d12b9f66 Michael Hanselmann
    data_empty_keys = {
236 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_ROOT_KEY: [],
237 d12b9f66 Michael Hanselmann
      }
238 d12b9f66 Michael Hanselmann
239 d12b9f66 Michael Hanselmann
    for data in [{}, data_empty_keys]:
240 d12b9f66 Michael Hanselmann
      for dry_run in [False, True]:
241 d12b9f66 Michael Hanselmann
        prepare_node_join.UpdateSshRoot(data, dry_run,
242 d12b9f66 Michael Hanselmann
                                        _homedir_fn=NotImplemented)
243 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), [])
244 d12b9f66 Michael Hanselmann
245 d12b9f66 Michael Hanselmann
  def testDryRun(self):
246 d12b9f66 Michael Hanselmann
    data = {
247 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_ROOT_KEY: [
248 d12b9f66 Michael Hanselmann
        (constants.SSHK_RSA, "aaa", "bbb"),
249 d12b9f66 Michael Hanselmann
        ]
250 d12b9f66 Michael Hanselmann
      }
251 d12b9f66 Michael Hanselmann
252 d12b9f66 Michael Hanselmann
    prepare_node_join.UpdateSshRoot(data, True,
253 d12b9f66 Michael Hanselmann
                                    _homedir_fn=self._GetHomeDir)
254 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), [".ssh"])
255 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.sshdir), [])
256 d12b9f66 Michael Hanselmann
257 d12b9f66 Michael Hanselmann
  def testUpdate(self):
258 d12b9f66 Michael Hanselmann
    data = {
259 d12b9f66 Michael Hanselmann
      constants.SSHS_SSH_ROOT_KEY: [
260 340ae7da Michael Hanselmann
        (constants.SSHK_DSA, "privatedsa", "ssh-dss pubdsa"),
261 d12b9f66 Michael Hanselmann
        ]
262 d12b9f66 Michael Hanselmann
      }
263 d12b9f66 Michael Hanselmann
264 d12b9f66 Michael Hanselmann
    prepare_node_join.UpdateSshRoot(data, False,
265 d12b9f66 Michael Hanselmann
                                    _homedir_fn=self._GetHomeDir)
266 d12b9f66 Michael Hanselmann
    self.assertEqual(os.listdir(self.tmpdir), [".ssh"])
267 d12b9f66 Michael Hanselmann
    self.assertEqual(sorted(os.listdir(self.sshdir)),
268 d12b9f66 Michael Hanselmann
                     sorted(["authorized_keys", "id_dsa", "id_dsa.pub"]))
269 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.sshdir, "id_dsa")),
270 d12b9f66 Michael Hanselmann
                     "privatedsa")
271 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.sshdir, "id_dsa.pub")),
272 910ef222 Michael Hanselmann
                     "ssh-dss pubdsa")
273 d12b9f66 Michael Hanselmann
    self.assertEqual(utils.ReadFile(utils.PathJoin(self.sshdir,
274 d12b9f66 Michael Hanselmann
                                                   "authorized_keys")),
275 d12b9f66 Michael Hanselmann
                     "ssh-dss pubdsa\n")
276 d12b9f66 Michael Hanselmann
277 d12b9f66 Michael Hanselmann
278 d12b9f66 Michael Hanselmann
if __name__ == "__main__":
279 d12b9f66 Michael Hanselmann
  testutils.GanetiTestProgram()