Merge lp:~blake-rouse/maas/fix-1629045 into lp:~maas-committers/maas/trunk

Proposed by Blake Rouse
Status: Merged
Approved by: Blake Rouse
Approved revision: no longer in the source branch.
Merged at revision: 5422
Proposed branch: lp:~blake-rouse/maas/fix-1629045
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 129 lines (+57/-8)
4 files modified
src/provisioningserver/import_images/boot_resources.py (+10/-2)
src/provisioningserver/import_images/cleanup.py (+12/-6)
src/provisioningserver/import_images/tests/test_boot_resources.py (+25/-0)
src/provisioningserver/import_images/tests/test_cleanup.py (+10/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/fix-1629045
Reviewer Review Type Date Requested Status
Andres Rodriguez (community) Approve
Review via email: mp+307337@code.launchpad.net

Commit message

Cleanup snapshots and cache directory when import fails.

To post a comment you must log in.
Revision history for this message
Andres Rodriguez (andreserl) wrote :

lgtm! Just one comment inline that needs to be addressed beforehand.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/provisioningserver/import_images/boot_resources.py'
2--- src/provisioningserver/import_images/boot_resources.py 2016-09-11 21:35:53 +0000
3+++ src/provisioningserver/import_images/boot_resources.py 2016-09-30 18:15:17 +0000
4@@ -275,8 +275,16 @@
5
6 product_mapping = map_products(image_descriptions)
7
8- snapshot_path = download_all_boot_resources(
9- sources, storage, product_mapping)
10+ try:
11+ snapshot_path = download_all_boot_resources(
12+ sources, storage, product_mapping)
13+ except:
14+ # Cleanup snapshots and cache since download failed.
15+ maaslog.warning(
16+ "Unable to import boot images; cleaning up failed snapshot "
17+ "and cache.")
18+ cleanup_snapshots_and_cache(storage)
19+ raise
20
21 maaslog.info("Writing boot image metadata and iSCSI targets.")
22 write_snapshot_metadata(snapshot_path, meta_file_content)
23
24=== modified file 'src/provisioningserver/import_images/cleanup.py'
25--- src/provisioningserver/import_images/cleanup.py 2016-03-28 13:54:47 +0000
26+++ src/provisioningserver/import_images/cleanup.py 2016-09-30 18:15:17 +0000
27@@ -14,7 +14,10 @@
28 def list_old_snapshots(storage):
29 """List of snapshot directories that are no longer in use."""
30 current_dir = os.path.join(storage, 'current')
31- current_snapshot = os.path.basename(os.readlink(current_dir))
32+ if os.path.exists(current_dir):
33+ current_snapshot = os.path.basename(os.readlink(current_dir))
34+ else:
35+ current_snapshot = None
36 return [
37 os.path.join(storage, directory)
38 for directory in os.listdir(storage)
39@@ -32,11 +35,14 @@
40 def list_unused_cache_files(storage):
41 """List of cache files that are no longer being referenced by snapshots."""
42 cache_dir = os.path.join(storage, 'cache')
43- cache_files = [
44- os.path.join(cache_dir, filename)
45- for filename in os.listdir(cache_dir)
46- if os.path.isfile(os.path.join(cache_dir, filename))
47- ]
48+ if os.path.exists(cache_dir):
49+ cache_files = [
50+ os.path.join(cache_dir, filename)
51+ for filename in os.listdir(cache_dir)
52+ if os.path.isfile(os.path.join(cache_dir, filename))
53+ ]
54+ else:
55+ cache_files = []
56 return [
57 cache_file
58 for cache_file in cache_files
59
60=== modified file 'src/provisioningserver/import_images/tests/test_boot_resources.py'
61--- src/provisioningserver/import_images/tests/test_boot_resources.py 2016-08-30 18:45:05 +0000
62+++ src/provisioningserver/import_images/tests/test_boot_resources.py 2016-09-30 18:15:17 +0000
63@@ -56,6 +56,7 @@
64 from testtools.matchers import (
65 DirExists,
66 FileExists,
67+ Not,
68 )
69 import yaml
70
71@@ -484,6 +485,30 @@
72 ],
73 list(meta_data[osystem][arch][subarch][release][label]))
74
75+ def test_failed_run_deletes_snapshot(self):
76+ # Patch out things that we don't want running during the test. Patch
77+ # at a low level, so that we exercise all the function calls that a
78+ # unit test might not put to the test.
79+ self.patch_maaslog()
80+ self.patch(boot_resources, 'call_and_check')
81+ self.patch(boot_resources, "service_monitor")
82+
83+ args = self.make_working_args()
84+
85+ # Cause the import to fail.
86+ exception_type = factory.make_exception_type()
87+ mock_download = self.patch(
88+ boot_resources, "download_all_boot_resources")
89+ mock_download.side_effect = exception_type()
90+
91+ # Run the import code.
92+ self.assertRaises(exception_type, boot_resources.main, args)
93+
94+ # Verify the reuslts.
95+ self.assertThat(os.path.join(self.storage, 'cache'), Not(DirExists()))
96+ self.assertThat(
97+ os.path.join(self.storage, 'current'), Not(DirExists()))
98+
99 def test_warns_if_no_sources_selected(self):
100 self.patch_maaslog()
101 sources_fixture = self.useFixture(BootSourcesFixture([]))
102
103=== modified file 'src/provisioningserver/import_images/tests/test_cleanup.py'
104--- src/provisioningserver/import_images/tests/test_cleanup.py 2016-03-28 13:54:47 +0000
105+++ src/provisioningserver/import_images/tests/test_cleanup.py 2016-09-30 18:15:17 +0000
106@@ -40,6 +40,11 @@
107 os.link(cache_path, link_path)
108 return cache_path
109
110+ def test_list_old_snapshots_returns_all(self):
111+ storage = self.make_dir()
112+ snapshots = [self.make_snapshot_dir(storage) for _ in range(3)]
113+ self.assertItemsEqual(snapshots, cleanup.list_old_snapshots(storage))
114+
115 def test_list_old_snapshots_returns_all_but_current_directory(self):
116 storage = self.make_dir()
117 snapshots = [self.make_snapshot_dir(storage) for _ in range(3)]
118@@ -62,6 +67,11 @@
119 ]
120 self.assertEqual([], remaining_snapshots)
121
122+ def test_list_unused_cache_files_returns_empty(self):
123+ storage = self.make_dir()
124+ self.assertItemsEqual(
125+ [], cleanup.list_unused_cache_files(storage))
126+
127 def test_list_unused_cache_files_returns_all_files_nlink_equal_one(self):
128 storage = self.make_dir()
129 cache_nlink_1 = [self.make_cache_file(storage) for _ in range(3)]