1221
1222
MockCalledOnceWith())
1223
def test_has_synced_resources_returns_true(self):
1224
factory.make_BootResource(rtype=BOOT_RESOURCE_TYPE.SYNCED)
1225
self.assertTrue(bootresources.has_synced_resources())
1227
def test_has_synced_resources_returns_false(self):
1228
factory.make_BootResource(rtype=BOOT_RESOURCE_TYPE.UPLOADED)
1229
self.assertFalse(bootresources.has_synced_resources())
1231
1224
def test__import_resources_exits_early_if_lock_held(self):
1232
has_synced_resources = self.patch_autospec(
1233
bootresources, "has_synced_resources")
1225
set_simplestreams_env = self.patch_autospec(
1226
bootresources, "set_simplestreams_env")
1234
1227
with lock_held_in_other_thread(bootresources.locks.import_images):
1235
bootresources._import_resources(force=True)
1236
# The test for already-synced resources is not called if the
1228
bootresources._import_resources()
1229
# The test for set_simplestreams_env is not called if the
1237
1230
# lock is already held.
1238
self.assertThat(has_synced_resources, MockNotCalled())
1240
def test__import_resources_exits_early_without_force(self):
1241
has_synced_resources = self.patch(
1242
bootresources, "has_synced_resources")
1243
bootresources._import_resources(force=False)
1244
# The test for already-synced resources is not performed if we're
1246
self.assertThat(has_synced_resources, MockCalledOnceWith())
1248
def test__import_resources_continues_with_force(self):
1249
has_synced_resources = self.patch(
1250
bootresources, "has_synced_resources")
1251
bootresources._import_resources(force=True)
1252
# The test for already-synced resources is performed if we're not
1254
self.assertThat(has_synced_resources, MockNotCalled())
1231
self.assertThat(set_simplestreams_env, MockNotCalled())
1256
1233
def test__import_resources_holds_lock(self):
1257
1234
fake_write_all_keyrings = self.patch(
1263
1240
fake_write_all_keyrings.side_effect = test_for_held_lock
1265
bootresources._import_resources(force=True)
1242
bootresources._import_resources()
1266
1243
self.assertFalse(bootresources.locks.import_images.is_locked())
1268
1245
def test__import_resources_calls_functions_with_correct_parameters(self):
1282
1259
set_global_default_releases = self.patch(
1283
1260
bootresources, 'set_global_default_releases')
1285
bootresources._import_resources(force=True)
1262
bootresources._import_resources()
1287
1264
self.expectThat(
1288
1265
bootresources.cache_boot_sources,
1312
1289
self.patch(bootresources, 'map_products')
1313
1290
capture = self.patch_and_capture_env_for_download_all_boot_resources()
1315
bootresources._import_resources(force=True)
1292
bootresources._import_resources()
1316
1293
self.assertEqual(
1317
1294
get_maas_user_gpghome(), capture.env['GNUPGHOME'])
1319
1296
def test__import_resources_has_env_http_and_https_proxy_set(self):
1320
1297
proxy_address = factory.make_name('proxy')
1298
self.patch(signals.bootsources, "post_commit_do")
1321
1299
Config.objects.set_config('http_proxy', proxy_address)
1323
1301
fake_image_descriptions = self.patch(
1328
1306
self.patch(bootresources, 'map_products')
1329
1307
capture = self.patch_and_capture_env_for_download_all_boot_resources()
1331
bootresources._import_resources(force=True)
1309
bootresources._import_resources()
1332
1310
self.assertEqual(
1333
1311
(proxy_address, proxy_address),
1334
1312
(capture.env['http_proxy'], capture.env['http_proxy']))
1337
1315
from maasserver.clusterrpc import boot_images
1338
1316
self.patch(boot_images.RackControllersImporter, "run")
1340
bootresources._import_resources(force=True)
1318
bootresources._import_resources()
1342
1320
self.assertThat(
1343
1321
boot_images.RackControllersImporter.run,
1350
1328
def test__defers__import_resources_to_thread(self):
1351
1329
deferToDatabase = self.patch(bootresources, "deferToDatabase")
1352
bootresources._import_resources_in_thread(force=sentinel.force)
1330
bootresources._import_resources_in_thread()
1353
1331
self.assertThat(
1354
1332
deferToDatabase, MockCalledOnceWith(
1355
bootresources._import_resources, force=sentinel.force))
1333
bootresources._import_resources))
1357
1335
def tests__defaults_force_to_False(self):
1358
1336
deferToDatabase = self.patch(bootresources, "deferToDatabase")
1359
1337
bootresources._import_resources_in_thread()
1360
1338
self.assertThat(
1361
1339
deferToDatabase, MockCalledOnceWith(
1362
bootresources._import_resources, force=False))
1340
bootresources._import_resources))
1364
1342
def test__logs_errors_and_does_not_errback(self):
1365
1343
logger = self.useFixture(TwistedLoggerFixture())
1366
1344
exception_type = factory.make_exception_type()
1367
1345
deferToDatabase = self.patch(bootresources, "deferToDatabase")
1368
1346
deferToDatabase.return_value = fail(exception_type())
1369
d = bootresources._import_resources_in_thread(force=sentinel.force)
1347
d = bootresources._import_resources_in_thread()
1370
1348
self.assertIsNone(extract_result(d))
1371
1349
self.assertDocTestMatches(
1383
1361
factory.make_name("output"))
1384
1362
deferToDatabase = self.patch(bootresources, "deferToDatabase")
1385
1363
deferToDatabase.return_value = fail(exception)
1386
d = bootresources._import_resources_in_thread(force=sentinel.force)
1364
d = bootresources._import_resources_in_thread()
1387
1365
self.assertIsNone(extract_result(d))
1388
1366
self.assertDocTestMatches(
1488
1466
service, "are_boot_images_available_in_the_region")
1489
1467
are_region_func.return_value = region_answer
1490
1468
are_cluster_func = self.patch_autospec(
1491
service, "are_boot_images_available_in_any_cluster")
1469
service, "are_boot_images_available_in_any_rack")
1492
1470
are_cluster_func.return_value = cluster_answer
1494
1472
def test__adds_warning_if_boot_images_exists_on_cluster_not_region(self):
1503
1481
error_observed = get_persistent_error(COMPONENT.IMPORT_PXE_FILES)
1504
1482
error_expected = """\
1505
One or more of your clusters currently has boot images, but your
1506
region does not. Nodes will not be able to provision until you import
1507
boot images into the region. Visit the <a href="%s">boot images</a>
1508
page to start the import.
1483
One or more of your rack controller(s) currently has boot images, but
1484
your region controller does not. Machines will not be able to provision
1485
until you import boot images into the region. Visit the
1486
<a href="%s">boot images</a> page to start the import.
1510
1488
images_link = maas_url_path + '/images/'
1511
1489
self.assertEqual(
1524
1502
error_observed = get_persistent_error(COMPONENT.IMPORT_PXE_FILES)
1525
1503
error_expected = """\
1526
Boot image import process not started. Nodes will not be able to
1504
Boot image import process not started. Machines will not be able to
1527
1505
provision without boot images. Visit the <a href="%s">boot images</a>
1528
1506
page to start the import.
1571
1549
factory.make_BootResource()
1572
1550
self.assertTrue(service.are_boot_images_available_in_the_region())
1574
def test__are_boot_images_available_in_any_cluster_v2(self):
1552
def test__are_boot_images_available_in_any_rack_v2(self):
1575
1553
# Import the websocket handlers now: merely defining DeviceHandler,
1576
1554
# e.g., causes a database access, which will crash if it happens
1577
1555
# inside the reactor thread where database access is forbidden and
1590
1568
# are_boot_images_available_in_the_region() returns False when there
1591
1569
# are no clusters connected.
1592
self.assertFalse(service.are_boot_images_available_in_any_cluster())
1570
self.assertFalse(service.are_boot_images_available_in_any_rack())
1594
1572
# Connect a rack controller to the region via RPC.
1595
1573
cluster_rpc = region_rpc.makeCluster(rack_controller, ListBootImagesV2)
1597
1575
# are_boot_images_available_in_the_region() returns False when none of
1598
1576
# the clusters have any images.
1599
1577
cluster_rpc.ListBootImagesV2.return_value = succeed({"images": []})
1600
self.assertFalse(service.are_boot_images_available_in_any_cluster())
1578
self.assertFalse(service.are_boot_images_available_in_any_rack())
1602
1580
# are_boot_images_available_in_the_region() returns True when a
1603
1581
# cluster has an imported boot image.
1604
1582
response = {"images": [make_rpc_boot_image()]}
1605
1583
cluster_rpc.ListBootImagesV2.return_value = succeed(response)
1606
self.assertTrue(service.are_boot_images_available_in_any_cluster())
1584
self.assertTrue(service.are_boot_images_available_in_any_rack())
1608
def test__are_boot_images_available_in_any_cluster_v1(self):
1586
def test__are_boot_images_available_in_any_rack_v1(self):
1609
1587
# Import the websocket handlers now: merely defining DeviceHandler,
1610
1588
# e.g., causes a database access, which will crash if it happens
1611
1589
# inside the reactor thread where database access is forbidden and
1624
1602
# are_boot_images_available_in_the_region() returns False when there
1625
1603
# are no clusters connected.
1626
self.assertFalse(service.are_boot_images_available_in_any_cluster())
1604
self.assertFalse(service.are_boot_images_available_in_any_rack())
1628
1606
# Connect a rack controller to the region via RPC.
1629
1607
cluster_rpc = region_rpc.makeCluster(
1635
1613
# are_boot_images_available_in_the_region() returns False when none of
1636
1614
# the clusters have any images.
1637
1615
cluster_rpc.ListBootImages.return_value = succeed({"images": []})
1638
self.assertFalse(service.are_boot_images_available_in_any_cluster())
1616
self.assertFalse(service.are_boot_images_available_in_any_rack())
1640
1618
# are_boot_images_available_in_the_region() returns True when a
1641
1619
# cluster has an imported boot image.
1642
1620
response = {"images": [make_rpc_boot_image()]}
1643
1621
cluster_rpc.ListBootImages.return_value = succeed(response)
1644
self.assertTrue(service.are_boot_images_available_in_any_cluster())
1622
self.assertTrue(service.are_boot_images_available_in_any_rack())