Merge lp:~blake-rouse/maas/cache-cluster-boot-images 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: 3430
Proposed branch: lp:~blake-rouse/maas/cache-cluster-boot-images
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 176 lines (+73/-3)
4 files modified
src/maasserver/clusterrpc/tests/test_boot_images.py (+3/-0)
src/provisioningserver/rpc/boot_images.py (+25/-2)
src/provisioningserver/rpc/tests/test_boot_images.py (+43/-1)
src/provisioningserver/rpc/tests/test_clusterservice.py (+2/-0)
To merge this branch: bzr merge lp:~blake-rouse/maas/cache-cluster-boot-images
Reviewer Review Type Date Requested Status
Jason Hobbs (community) Approve
Review via email: mp+244754@code.launchpad.net

Commit message

Cache the list of boot images on the cluster. Instead of reading from the disk on every request of the boot images, it is only updated when the contents of the disk have changed from an import.

To post a comment you must log in.
Revision history for this message
Jason Hobbs (jason-hobbs) wrote :

lgtm.

review: Approve
Revision history for this message
MAAS Lander (maas-lander) wrote :
Download full text (24.6 KiB)

The attempt to merge lp:~blake-rouse/maas/cache-cluster-boot-images into lp:maas failed. Below is the output from the failed tests.

Ign http://security.ubuntu.com trusty-security InRelease
Hit http://security.ubuntu.com trusty-security Release.gpg
Ign http://nova.clouds.archive.ubuntu.com trusty InRelease
Hit http://security.ubuntu.com trusty-security Release
Ign http://nova.clouds.archive.ubuntu.com trusty-updates InRelease
Hit http://nova.clouds.archive.ubuntu.com trusty Release.gpg
Get:1 http://nova.clouds.archive.ubuntu.com trusty-updates Release.gpg [933 B]
Hit http://nova.clouds.archive.ubuntu.com trusty Release
Get:2 http://nova.clouds.archive.ubuntu.com trusty-updates Release [62.0 kB]
Hit http://security.ubuntu.com trusty-security/main Sources
Hit http://security.ubuntu.com trusty-security/universe Sources
Hit http://nova.clouds.archive.ubuntu.com trusty/main Sources
Hit http://security.ubuntu.com trusty-security/main amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Sources
Hit http://security.ubuntu.com trusty-security/universe amd64 Packages
Hit http://nova.clouds.archive.ubuntu.com trusty/main amd64 Packages
Hit http://security.ubuntu.com trusty-security/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe amd64 Packages
Hit http://security.ubuntu.com trusty-security/universe Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en
Ign http://nova.clouds.archive.ubuntu.com trusty/main Translation-en_US
Ign http://nova.clouds.archive.ubuntu.com trusty/universe Translation-en_US
Get:3 http://nova.clouds.archive.ubuntu.com trusty-updates/main Sources [148 kB]
Get:4 http://nova.clouds.archive.ubuntu.com trusty-updates/universe Sources [94.7 kB]
Get:5 http://nova.clouds.archive.ubuntu.com trusty-updates/main amd64 Packages [384 kB]
Get:6 http://nova.clouds.archive.ubuntu.com trusty-updates/universe amd64 Packages [227 kB]
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/main Translation-en
Hit http://nova.clouds.archive.ubuntu.com trusty-updates/universe Translation-en
Fetched 917 kB in 2s (321 kB/s)
Reading package lists...
sudo DEBIAN_FRONTEND=noninteractive apt-get -y \
     --no-install-recommends install apache2 authbind bind9 bind9utils build-essential bzr-builddeb curl daemontools debhelper dh-apport distro-info dnsutils firefox freeipmi-tools gjs ipython isc-dhcp-common libjs-raphael libjs-yui3-full libjs-yui3-min libpq-dev make pep8 postgresql pyflakes python-amqplib python-bzrlib python-celery python-convoy python-crochet python-cssselect python-curtin python-dev python-distro-info python-django python-django-piston python-django-south python-djorm-ext-pgarray python-docutils python-extras python-fixtures python-flake8 python-formencode python-hivex python-httplib2 python-jinja2 python-jsonschema python-lockfile python-lxml python-mimeparse python-mock python-netaddr python-netifaces python-nose python-oauth python-oops python-oops-amqp python-oops-datedir-repo python-oops-twisted python-oops-wsgi python-openssl python-paramiko python-pexpect python-pip python-pocket-lin...

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/maasserver/clusterrpc/tests/test_boot_images.py'
2--- src/maasserver/clusterrpc/tests/test_boot_images.py 2014-10-30 13:39:50 +0000
3+++ src/maasserver/clusterrpc/tests/test_boot_images.py 2014-12-16 18:59:29 +0000
4@@ -144,6 +144,7 @@
5 resource_dir = self.make_dir()
6 self.tftproot = os.path.join(resource_dir, 'current')
7 os.mkdir(self.tftproot)
8+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
9 self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir)
10
11 def test_returns_boot_images(self):
12@@ -172,6 +173,7 @@
13 resource_dir = self.make_dir()
14 self.tftproot = os.path.join(resource_dir, 'current')
15 os.mkdir(self.tftproot)
16+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
17 self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir)
18
19 def test_returns_boot_images_for_one_cluster(self):
20@@ -261,6 +263,7 @@
21 resource_dir = self.make_dir()
22 self.tftproot = os.path.join(resource_dir, 'current')
23 os.mkdir(self.tftproot)
24+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
25 self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', resource_dir)
26
27 def make_boot_images(self):
28
29=== modified file 'src/provisioningserver/rpc/boot_images.py'
30--- src/provisioningserver/rpc/boot_images.py 2014-10-30 13:17:51 +0000
31+++ src/provisioningserver/rpc/boot_images.py 2014-12-16 18:59:29 +0000
32@@ -31,9 +31,28 @@
33 from twisted.internet.threads import deferToThread
34
35
36+CACHED_BOOT_IMAGES = None
37+
38+
39 def list_boot_images():
40- """List the boot images that exist on the cluster."""
41- return tftppath.list_boot_images(
42+ """List the boot images that exist on the cluster.
43+
44+ This return value of this function is cached. This helps reduce the amount
45+ of IO, as this function is called often. To update the cache call
46+ `reload_boot_images`.
47+ """
48+ global CACHED_BOOT_IMAGES
49+ if CACHED_BOOT_IMAGES is None:
50+ CACHED_BOOT_IMAGES = tftppath.list_boot_images(
51+ os.path.join(BOOT_RESOURCES_STORAGE, 'current'))
52+ return CACHED_BOOT_IMAGES
53+
54+
55+def reload_boot_images():
56+ """Update the cached boot images so `list_boot_images` returns the
57+ most up-to-date boot images list."""
58+ global CACHED_BOOT_IMAGES
59+ CACHED_BOOT_IMAGES = tftppath.list_boot_images(
60 os.path.join(BOOT_RESOURCES_STORAGE, 'current'))
61
62
63@@ -67,6 +86,10 @@
64 with environment_variables(variables):
65 boot_resources.import_images(sources)
66
67+ # Update the boot images cache so `list_boot_images` returns the
68+ # correct information.
69+ reload_boot_images()
70+
71
72 def import_boot_images(sources, http_proxy=None, https_proxy=None):
73 """Imports the boot images from the given sources."""
74
75=== modified file 'src/provisioningserver/rpc/tests/test_boot_images.py'
76--- src/provisioningserver/rpc/tests/test_boot_images.py 2014-10-30 13:17:51 +0000
77+++ src/provisioningserver/rpc/tests/test_boot_images.py 2014-12-16 18:59:29 +0000
78@@ -23,7 +23,10 @@
79 MockNotCalled,
80 )
81 from maastesting.testcase import MAASTwistedRunTest
82-from mock import sentinel
83+from mock import (
84+ ANY,
85+ sentinel,
86+ )
87 from provisioningserver import concurrency
88 from provisioningserver.boot import tftppath
89 from provisioningserver.config import BOOT_RESOURCES_STORAGE
90@@ -35,6 +38,7 @@
91 import_boot_images,
92 is_import_boot_images_running,
93 list_boot_images,
94+ reload_boot_images,
95 )
96 from provisioningserver.testing.config import BootSourcesFixture
97 from provisioningserver.testing.testcase import PservTestCase
98@@ -61,6 +65,7 @@
99 class TestListBootImages(PservTestCase):
100
101 def test__calls_list_boot_images_with_boot_resource_storage(self):
102+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
103 mock_list_boot_images = self.patch(tftppath, 'list_boot_images')
104 list_boot_images()
105 self.assertThat(
106@@ -68,6 +73,36 @@
107 MockCalledOnceWith(
108 os.path.join(BOOT_RESOURCES_STORAGE, "current")))
109
110+ def test__calls_list_boot_images_when_cache_is_None(self):
111+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
112+ mock_list_boot_images = self.patch(tftppath, 'list_boot_images')
113+ list_boot_images()
114+ self.assertThat(
115+ mock_list_boot_images,
116+ MockCalledOnceWith(ANY))
117+
118+ def test__doesnt_call_list_boot_images_when_cache_is_not_None(self):
119+ fake_boot_images = [factory.make_name('image') for _ in range(3)]
120+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', fake_boot_images)
121+ mock_list_boot_images = self.patch(tftppath, 'list_boot_images')
122+ self.expectThat(list_boot_images(), Equals(fake_boot_images))
123+ self.expectThat(
124+ mock_list_boot_images,
125+ MockNotCalled())
126+
127+
128+class TestReloadBootImages(PservTestCase):
129+
130+ def test__sets_CACHED_BOOT_IMAGES(self):
131+ self.patch(
132+ boot_images, 'CACHED_BOOT_IMAGES', factory.make_name('old_cache'))
133+ fake_boot_images = [factory.make_name('image') for _ in range(3)]
134+ mock_list_boot_images = self.patch(tftppath, 'list_boot_images')
135+ mock_list_boot_images.return_value = fake_boot_images
136+ reload_boot_images()
137+ self.assertEquals(
138+ boot_images.CACHED_BOOT_IMAGES, fake_boot_images)
139+
140
141 class TestGetHostsFromSources(PservTestCase):
142
143@@ -141,6 +176,13 @@
144 _run_import(sources=sources)
145 self.assertThat(fake, MockCalledOnceWith(sources))
146
147+ def test__run_import_calls_reload_boot_images(self):
148+ fake_reload = self.patch(boot_images, 'reload_boot_images')
149+ self.patch(boot_resources, 'import_images')
150+ sources, _ = make_sources()
151+ _run_import(sources=sources)
152+ self.assertThat(fake_reload, MockCalledOnceWith())
153+
154
155 class TestImportBootImages(PservTestCase):
156
157
158=== modified file 'src/provisioningserver/rpc/tests/test_clusterservice.py'
159--- src/provisioningserver/rpc/tests/test_clusterservice.py 2014-12-12 00:56:22 +0000
160+++ src/provisioningserver/rpc/tests/test_clusterservice.py 2014-12-16 18:59:29 +0000
161@@ -227,6 +227,7 @@
162
163 @inlineCallbacks
164 def test_list_boot_images_can_be_called(self):
165+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
166 list_boot_images = self.patch(tftppath, "list_boot_images")
167 list_boot_images.return_value = []
168
169@@ -256,6 +257,7 @@
170 os.makedirs(os.path.join(current_dir, *options))
171 make_osystem(self, options[0], purposes)
172 self.patch(boot_images, 'BOOT_RESOURCES_STORAGE', tftpdir)
173+ self.patch(boot_images, 'CACHED_BOOT_IMAGES', None)
174
175 expected_images = [
176 {