~lutostag/ubuntu/trusty/maas/1.5.4+keystone

« back to all changes in this revision

Viewing changes to src/provisioningserver/tests/test_tftp.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2014-02-15 12:08:23 UTC
  • mto: This revision was merged to the branch mainline in revision 48.
  • Revision ID: package-import@ubuntu.com-20140215120823-u7dkitfy0h8tbruh
Tags: upstream-1.5+bzr1948
ImportĀ upstreamĀ versionĀ 1.5+bzr1948

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
from provisioningserver.tftp import (
32
32
    BytesReader,
33
33
    TFTPBackend,
 
34
    TFTPService,
34
35
    )
35
36
from testtools.deferredruntest import AsynchronousDeferredRunTest
 
37
from testtools.matchers import (
 
38
    AfterPreprocessing,
 
39
    AllMatch,
 
40
    Equals,
 
41
    IsInstance,
 
42
    MatchesAll,
 
43
    MatchesStructure,
 
44
    )
36
45
from tftp.backend import IReader
 
46
from tftp.protocol import TFTP
 
47
from twisted.application import internet
 
48
from twisted.application.service import MultiService
 
49
from twisted.internet import reactor
37
50
from twisted.internet.defer import (
38
51
    inlineCallbacks,
39
52
    succeed,
288
301
        self.assertEqual(fake_render_result.encode("utf-8"), output)
289
302
        backend.render_pxe_config.assert_called_once_with(
290
303
            kernel_params=fake_kernel_params, **fake_params)
 
304
 
 
305
 
 
306
class TestTFTPService(MAASTestCase):
 
307
 
 
308
    def test_tftp_service(self):
 
309
        # A TFTP service is configured and added to the top-level service.
 
310
        interfaces = [
 
311
            factory.getRandomIPAddress(),
 
312
            factory.getRandomIPAddress(),
 
313
            ]
 
314
        self.patch(
 
315
            tftp_module, "get_all_interface_addresses",
 
316
            lambda: interfaces)
 
317
        example_root = self.make_dir()
 
318
        example_generator = "http://example.com/generator"
 
319
        example_port = factory.getRandomPort()
 
320
        tftp_service = TFTPService(
 
321
            root=example_root, generator=example_generator,
 
322
            port=example_port)
 
323
        tftp_service.updateServers()
 
324
        # The "tftp" service is a multi-service containing UDP servers for
 
325
        # each interface defined by get_all_interface_addresses().
 
326
        self.assertIsInstance(tftp_service, MultiService)
 
327
        # There's also a TimerService that updates the servers every 45s.
 
328
        self.assertThat(
 
329
            tftp_service.refresher, MatchesStructure.byEquality(
 
330
                step=45, parent=tftp_service, name="refresher",
 
331
                call=(tftp_service.updateServers, (), {}),
 
332
            ))
 
333
        expected_backend = MatchesAll(
 
334
            IsInstance(TFTPBackend),
 
335
            AfterPreprocessing(
 
336
                lambda backend: backend.base.path,
 
337
                Equals(example_root)),
 
338
            AfterPreprocessing(
 
339
                lambda backend: backend.generator_url.geturl(),
 
340
                Equals(example_generator)))
 
341
        expected_protocol = MatchesAll(
 
342
            IsInstance(TFTP),
 
343
            AfterPreprocessing(
 
344
                lambda protocol: protocol.backend,
 
345
                expected_backend))
 
346
        expected_server = MatchesAll(
 
347
            IsInstance(internet.UDPServer),
 
348
            AfterPreprocessing(
 
349
                lambda service: len(service.args),
 
350
                Equals(2)),
 
351
            AfterPreprocessing(
 
352
                lambda service: service.args[0],  # port
 
353
                Equals(example_port)),
 
354
            AfterPreprocessing(
 
355
                lambda service: service.args[1],  # protocol
 
356
                expected_protocol))
 
357
        self.assertThat(
 
358
            tftp_service.getServers(),
 
359
            AllMatch(expected_server))
 
360
        # Only the interface used for each service differs.
 
361
        self.assertItemsEqual(
 
362
            [svc.kwargs for svc in tftp_service.getServers()],
 
363
            [{"interface": interface} for interface in interfaces])
 
364
 
 
365
    def test_tftp_service_rebinds_on_HUP(self):
 
366
        # Initial set of interfaces to bind to.
 
367
        interfaces = {"1.1.1.1", "2.2.2.2"}
 
368
        self.patch(
 
369
            tftp_module, "get_all_interface_addresses",
 
370
            lambda: interfaces)
 
371
 
 
372
        tftp_service = TFTPService(
 
373
            root=self.make_dir(), generator="http://mighty/wind",
 
374
            port=factory.getRandomPort())
 
375
        tftp_service.updateServers()
 
376
 
 
377
        # The child services of tftp_services are named after the
 
378
        # interface they bind to.
 
379
        self.assertEqual(interfaces, {
 
380
            server.name for server in tftp_service.getServers()
 
381
        })
 
382
 
 
383
        # Update the set of interfaces to bind to.
 
384
        interfaces.add("3.3.3.3")
 
385
        interfaces.remove("1.1.1.1")
 
386
 
 
387
        # Ask the TFTP service to update its set of servers.
 
388
        tftp_service.updateServers()
 
389
 
 
390
        # We're in the reactor thread but we want to move the reactor
 
391
        # forwards, hence we need to get all explicit about it.
 
392
        reactor.runUntilCurrent()
 
393
 
 
394
        # The interfaces now bound match the updated interfaces set.
 
395
        self.assertEqual(interfaces, {
 
396
            server.name for server in tftp_service.getServers()
 
397
        })