31
32
from maasserver.rpc import getAllClients
32
from maasserver.rpc.testing.fixtures import RunningClusterRPCFixture
33
from maasserver.rpc.testing.fixtures import (
34
MockLiveRegionToClusterRPCFixture,
35
RunningClusterRPCFixture,
37
from maasserver.testing.eventloop import (
38
RegionEventLoopFixture,
39
RunningEventLoopFixture,
33
41
from maasserver.testing.factory import factory
34
42
from maasserver.testing.testcase import MAASServerTestCase
43
from maastesting.matchers import (
35
51
from provisioningserver.boot.tests import test_tftppath
36
52
from provisioningserver.boot.tftppath import (
37
53
compose_image_path,
60
from provisioningserver.rpc.cluster import (
44
64
from provisioningserver.testing.boot_images import (
45
65
make_boot_image_storage_params,
48
68
from twisted.internet.defer import succeed
69
from twisted.protocols.amp import UnhandledCommand
51
72
def make_image_dir(image_params, tftproot):
165
186
get_boot_images(nodegroup))
188
def test_calls_ListBootImagesV2_before_ListBootImages(self):
189
nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ENABLED)
190
mock_client = MagicMock()
192
boot_images_module, "getClientFor").return_value = mock_client
193
get_boot_images(nodegroup)
194
self.assertThat(mock_client, MockCalledOnceWith(ListBootImagesV2))
196
def test_calls_ListBootImages_if_raised_UnhandledCommand(self):
197
nodegroup = factory.make_NodeGroup(status=NODEGROUP_STATUS.ENABLED)
198
mock_client = MagicMock()
200
boot_images_module, "getClientFor").return_value = mock_client
201
mock_client.return_value.wait.side_effect = [
205
get_boot_images(nodegroup)
206
self.assertThat(mock_client, MockCallsMatch(
207
call(ListBootImagesV2),
208
call(ListBootImages)))
168
211
class TestGetAvailableBootImages(MAASServerTestCase):
169
212
"""Tests for `get_available_boot_images`."""
240
283
get_available_boot_images())
285
def test_fallback_to_ListBootImages_on_old_clusters(self):
286
nodegroup_1 = factory.make_NodeGroup()
288
nodegroup_2 = factory.make_NodeGroup()
290
nodegroup_3 = factory.make_NodeGroup()
293
images = [make_rpc_boot_image() for _ in range(3)]
295
# Limit the region's event loop to only the "rpc" service.
296
self.useFixture(RegionEventLoopFixture("rpc"))
297
# Now start the region's event loop.
298
self.useFixture(RunningEventLoopFixture())
299
# This fixture allows us to simulate mock clusters.
300
rpc = self.useFixture(MockLiveRegionToClusterRPCFixture())
302
# This simulates an older cluster, one without ListBootImagesV2.
303
cluster_1 = rpc.makeCluster(nodegroup_1, ListBootImages)
304
cluster_1.ListBootImages.return_value = succeed({'images': images})
306
# This simulates a newer cluster, one with ListBootImagesV2.
307
cluster_2 = rpc.makeCluster(nodegroup_2, ListBootImagesV2)
308
cluster_2.ListBootImagesV2.return_value = succeed({'images': images})
310
# This simulates a broken cluster.
311
cluster_3 = rpc.makeCluster(nodegroup_3, ListBootImagesV2)
312
cluster_3.ListBootImagesV2.side_effect = ZeroDivisionError
314
self.assertItemsEqual(images, get_available_boot_images())
242
316
def test_returns_empty_list_when_all_clusters_fail(self):
243
317
factory.make_NodeGroup().accept()
244
318
factory.make_NodeGroup().accept()