Merge lp:~hazmat/pyjuju/sans-ami into lp:pyjuju
- sans-ami
- Merge into trunk
Status: | Merged | ||||||||
---|---|---|---|---|---|---|---|---|---|
Approved by: | Kapil Thangavelu | ||||||||
Approved revision: | 269 | ||||||||
Merged at revision: | 266 | ||||||||
Proposed branch: | lp:~hazmat/pyjuju/sans-ami | ||||||||
Merge into: | lp:pyjuju | ||||||||
Diff against target: |
286 lines (+131/-35) 5 files modified
ensemble/providers/ec2/launch.py (+29/-13) ensemble/providers/ec2/tests/data/natty.txt (+21/-0) ensemble/providers/ec2/tests/test_launch.py (+1/-1) ensemble/providers/ec2/tests/test_utils.py (+54/-13) ensemble/providers/ec2/utils.py (+26/-8) |
||||||||
To merge this branch: | bzr merge lp:~hazmat/pyjuju/sans-ami | ||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Benjamin Saller (community) | Approve | ||
Gustavo Niemeyer | Approve | ||
Review via email: mp+66203@code.launchpad.net |
Commit message
Description of the change
This branch (re) enables usage of standard ubuntu amis for ensemble machines, utilizing the ensemble ppa as the default mechanism for installing ensemble, as an added bonus this removes the extraneous zk instances on service unit machines. It also preserves the ability to install ensemble from a public lp branch
Kapil Thangavelu (hazmat) wrote : | # |
[0]. I think we're a little early to support static packages atm, we're not upstream on any release we're actually using atm, so its a dead option, and we're iterating on features way to fast to let people use a static version.
[1]. Its still needed for (c) a source install case.
[3] allow a distro spec from the environment yaml file sounds good
Gustavo Niemeyer (niemeyer) wrote : | # |
This looks good, thanks for sorting this out so quickly. +1, assuming
both deployment scenarios were tested.
[0]
Ben's [0] is a very good point, but I agree we can sort it out in a
follow up. We have to deal with picking the proper package until the
sprint in Austin. We really can't let it go through without it, or
we'll be in trouble soon.
[1]
def get_machine_
(...)
del kw[a_name]
(...)
data=kw)
The way we have a blob of data spreading through to various locations
which poke at it and pick what they need isn't entirely comforting.
I guess it's fine since it's fairly well contained ATM, but we should
look at opportunities to refactor that into a more understandable
flow if we continue growing into this direction.
[2]
+ # XXX ideally should come from latest available or client release name.
We really have to sort out the situation of the way Ubuntu releases
are selected, and take into account the formula preference. We'll
necessarily have to solve that up to the sprint in Austin, otherwise
we risk going out with an unmanaged situation which will bite us
heavily later.
Gustavo Niemeyer (niemeyer) wrote : | # |
Moved back to WIP until Ben's points are sorted.
Kapil Thangavelu (hazmat) wrote : | # |
Excerpts from Benjamin Saller's message of Fri Jul 01 15:12:53 UTC 2011:
0 and 1 in the works.
>
> [1] This _should_ be in the deb.
>
> 123 class EC2UtilsTest(
> 124 @@ -28,7 +28,7 @@
> 125 a LookupError is raised.
> 126 """
> 127 page = self.mocker.
> 128 - page(SAMPLE_URI)
> 129 + page(IMAGE_
> 130 self.mocker.
> 131 self.mocker.
> 132 d = get_current_
>
> [2] Our consumers are already plotting about 11.10. Even in our test cases we might benefit from removing release names to avoid feeling of bit rot as things move forward. Every 6 months these references look older and older. release-1, release-2 etc might make as much sense. I think we should also remove actual release names from the codebase like get_current_ami.
I think this is just testing against a known data set, the notion of bitrot here seems limited, its a test verifying a parsing process with a known input and output.
> [3] related to the last note but I think ensemble.
>
This is a little unclear to me, an ensemble environment might have multiple distributions within it. Its an easy option to add, i'm just unclear for both this and instance-type if we really want to be spec'ing this at the environment level. For a default distro if not spec'd in the environment, i'd assume the distro release name of the machine that the admin tools are running from.
Its unclear how this should react with nightlies, but perhaps that notion is more ec2 image centric.
Benjamin Saller (bcsaller) wrote : | # |
We've agreed that the changes mentioned in [0] can come in a later branch. There is pressing need for a solution now, so +1
Preview Diff
1 | === modified file 'ensemble/providers/ec2/launch.py' |
2 | --- ensemble/providers/ec2/launch.py 2011-06-02 17:50:24 +0000 |
3 | +++ ensemble/providers/ec2/launch.py 2011-06-28 20:16:40 +0000 |
4 | @@ -128,22 +128,39 @@ |
5 | return group_created.addCallback(lambda x: groups) |
6 | return groups |
7 | |
8 | + def _get_branch_install_scripts(self, branch): |
9 | + """Returns the commands to install ensemble from a bzr branch. |
10 | + |
11 | + The branch identifier must be a valid publicly accessible bzr |
12 | + url that can be used by bzr to checkout the branch. The install |
13 | + commands will setup local directories and installation of the branch. |
14 | + """ |
15 | + ensemble_vcs = ("cd /usr/lib/ensemble " |
16 | + "&& sudo /usr/bin/bzr co %s ensemble" % branch) |
17 | + ensemble_install = [ |
18 | + "sudo apt-get install -y python-txzookeeper", |
19 | + "sudo mkdir -p /usr/lib/ensemble", |
20 | + ensemble_vcs, |
21 | + "cd /usr/lib/ensemble/ensemble && sudo python setup.py develop"] |
22 | + |
23 | + return ensemble_install |
24 | + |
25 | def get_launch_scripts(self, machine_data): |
26 | """Get the scripts that will execute after the machine has launched.""" |
27 | |
28 | + launch_scripts = ["sudo apt-get -y install ensemble"] |
29 | + |
30 | + # Support installation of ensemble directly from an LP hosted branch. |
31 | if machine_data.get("ensemble-branch"): |
32 | - ensemble_vcs = ENSEMBLE_UPDATE_TEMPLATE % ( |
33 | - "switch %s" % machine_data["ensemble-branch"]) |
34 | - else: |
35 | - ensemble_vcs = ENSEMBLE_UPDATE |
36 | - |
37 | - launch_scripts = [ |
38 | - "sudo mkdir -p /usr/lib/ensemble", |
39 | - ensemble_vcs, |
40 | - "cd /usr/lib/ensemble/ensemble && sudo python setup.py develop", |
41 | - "cd /usr/lib/ensemble/txzookeeper && sudo /usr/bin/bzr up", |
42 | - "cd /usr/lib/ensemble/txzookeeper && sudo python setup.py develop"] |
43 | - |
44 | + launch_scripts = self._get_branch_install_scripts( |
45 | + machine_data["ensemble-branch"]) |
46 | + |
47 | + # These should be in the deb |
48 | + launch_scripts.extend([ |
49 | + "sudo mkdir -p /var/lib/ensemble", |
50 | + "sudo mkdir -p /var/log/ensemble"]) |
51 | + |
52 | + # Every machine has its own agent. |
53 | machine_agent_script = ( |
54 | "ENSEMBLE_MACHINE_ID=%(machine-id)s " |
55 | "ENSEMBLE_ZOOKEEPER=%(ensemble-zookeeper-hosts)s " |
56 | @@ -151,7 +168,6 @@ |
57 | "--logfile=/var/log/ensemble/machine-agent.log " |
58 | "--pidfile=/var/run/ensemble/machine-agent.pid") |
59 | launch_scripts.append(machine_agent_script % machine_data) |
60 | - |
61 | return launch_scripts |
62 | |
63 | def get_machine_variables(self, machine_data): |
64 | |
65 | === renamed file 'ensemble/providers/ec2/tests/data/lucid-release.txt' => 'ensemble/providers/ec2/tests/data/lucid.txt' |
66 | === added file 'ensemble/providers/ec2/tests/data/natty.txt' |
67 | --- ensemble/providers/ec2/tests/data/natty.txt 1970-01-01 00:00:00 +0000 |
68 | +++ ensemble/providers/ec2/tests/data/natty.txt 2011-06-28 20:16:40 +0000 |
69 | @@ -0,0 +1,21 @@ |
70 | +natty server release 20110426 ebs amd64 ap-northeast-1 ami-dab812db aki-d409a2d5 paravirtual |
71 | +natty server release 20110426 ebs i386 ap-northeast-1 ami-d8b812d9 aki-d209a2d3 paravirtual |
72 | +natty server release 20110426 instance-store amd64 ap-northeast-1 ami-a4b812a5 aki-d409a2d5 paravirtual |
73 | +natty server release 20110426 instance-store i386 ap-northeast-1 ami-46b81247 aki-d209a2d3 paravirtual |
74 | +natty server release 20110426 ebs amd64 ap-southeast-1 ami-60582132 aki-11d5aa43 paravirtual |
75 | +natty server release 20110426 ebs i386 ap-southeast-1 ami-62582130 aki-13d5aa41 paravirtual |
76 | +natty server release 20110426 instance-store amd64 ap-southeast-1 ami-aa5920f8 aki-11d5aa43 paravirtual |
77 | +natty server release 20110426 instance-store i386 ap-southeast-1 ami-c0592092 aki-13d5aa41 paravirtual |
78 | +natty server release 20110426 ebs amd64 eu-west-1 ami-379ea943 aki-4feec43b paravirtual |
79 | +natty server release 20110426 ebs i386 eu-west-1 ami-359ea941 aki-4deec439 paravirtual |
80 | +natty server release 20110426 instance-store amd64 eu-west-1 ami-619ea915 aki-4feec43b paravirtual |
81 | +natty server release 20110426 instance-store i386 eu-west-1 ami-1b9fa86f aki-4deec439 paravirtual |
82 | +natty server release 20110426 ebs amd64 us-east-1 ami-1cad5275 hvm |
83 | +natty server release 20110426 ebs amd64 us-east-1 ami-1aad5273 aki-427d952b paravirtual |
84 | +natty server release 20110426 ebs i386 us-east-1 ami-06ad526f aki-407d9529 paravirtual |
85 | +natty server release 20110426 instance-store amd64 us-east-1 ami-68ad5201 aki-427d952b paravirtual |
86 | +natty server release 20110426 instance-store i386 us-east-1 ami-e2af508b aki-407d9529 paravirtual |
87 | +natty server release 20110426 ebs amd64 us-west-1 ami-136f3c56 aki-9ba0f1de paravirtual |
88 | +natty server release 20110426 ebs i386 us-west-1 ami-116f3c54 aki-99a0f1dc paravirtual |
89 | +natty server release 20110426 instance-store amd64 us-west-1 ami-0b6f3c4e aki-9ba0f1de paravirtual |
90 | +natty server release 20110426 instance-store i386 us-west-1 ami-596f3c1c aki-99a0f1dc paravirtual |
91 | |
92 | === modified file 'ensemble/providers/ec2/tests/test_launch.py' |
93 | --- ensemble/providers/ec2/tests/test_launch.py 2011-06-03 18:11:39 +0000 |
94 | +++ ensemble/providers/ec2/tests/test_launch.py 2011-06-28 20:16:40 +0000 |
95 | @@ -200,7 +200,7 @@ |
96 | machine_data={ |
97 | "machine-id": "machine-2", |
98 | "ensemble-zookeeper-hosts": get_test_zookeeper_address()}) |
99 | - cmd = "cd /usr/lib/ensemble/ensemble && sudo /usr/bin/bzr switch %s"%( |
100 | + cmd = "cd /usr/lib/ensemble && sudo /usr/bin/bzr co %s" % ( |
101 | custom_branch) |
102 | self.failUnlessIn(cmd, variables["scripts"]) |
103 | self.assertEqual(variables["ensemble-branch"], custom_branch) |
104 | |
105 | === modified file 'ensemble/providers/ec2/tests/test_utils.py' |
106 | --- ensemble/providers/ec2/tests/test_utils.py 2011-06-03 18:11:39 +0000 |
107 | +++ ensemble/providers/ec2/tests/test_utils.py 2011-06-28 20:16:40 +0000 |
108 | @@ -13,11 +13,11 @@ |
109 | |
110 | from ensemble.lib.testing import TestCase |
111 | |
112 | -SAMPLE_URI = "\ |
113 | -http://uec-images.ubuntu.com/query/lucid/server/released.current.txt" |
114 | +IMAGE_URI_TEMPLATE = "\ |
115 | +http://uec-images.ubuntu.com/query/%s/server/released.current.txt" |
116 | |
117 | -SAMPLE_FILE = os.path.join(os.path.dirname(inspect.getabsfile(ec2)), |
118 | - "tests", "data", "lucid-release.txt") |
119 | +IMAGE_DATA_DIR = os.path.join( |
120 | + os.path.dirname(inspect.getabsfile(ec2)), "tests", "data") |
121 | |
122 | |
123 | class EC2UtilsTest(TestCase): |
124 | @@ -28,7 +28,7 @@ |
125 | a LookupError is raised. |
126 | """ |
127 | page = self.mocker.replace("twisted.web.client.getPage") |
128 | - page(SAMPLE_URI) |
129 | + page(IMAGE_URI_TEMPLATE % "lucid") |
130 | self.mocker.result(succeed("")) |
131 | self.mocker.replay() |
132 | d = get_current_ami(ubuntu_release_name="lucid") |
133 | @@ -38,8 +38,10 @@ |
134 | def test_current_ami(self): |
135 | """The current server machine image can be retrieved.""" |
136 | page = self.mocker.replace("twisted.web.client.getPage") |
137 | - page(SAMPLE_URI) |
138 | - self.mocker.result(succeed(open(SAMPLE_FILE).read())) |
139 | + page(IMAGE_URI_TEMPLATE % "lucid") |
140 | + self.mocker.result(succeed( |
141 | + open(os.path.join(IMAGE_DATA_DIR, "lucid.txt")).read())) |
142 | + |
143 | self.mocker.replay() |
144 | d = get_current_ami(ubuntu_release_name="lucid") |
145 | |
146 | @@ -52,8 +54,10 @@ |
147 | def test_current_ami_by_region(self): |
148 | """The current server machine image can be retrieved by region.""" |
149 | page = self.mocker.replace("twisted.web.client.getPage") |
150 | - page(SAMPLE_URI) |
151 | - self.mocker.result(succeed(open(SAMPLE_FILE).read())) |
152 | + page(IMAGE_URI_TEMPLATE % "lucid") |
153 | + self.mocker.result( |
154 | + succeed(open( |
155 | + os.path.join(IMAGE_DATA_DIR, "lucid.txt")).read())) |
156 | self.mocker.replay() |
157 | d = get_current_ami(ubuntu_release_name="lucid", region="us-west-1") |
158 | |
159 | @@ -69,8 +73,9 @@ |
160 | to guide image selection. |
161 | """ |
162 | page = self.mocker.replace("twisted.web.client.getPage") |
163 | - page(SAMPLE_URI) |
164 | - self.mocker.result(succeed(open(SAMPLE_FILE).read())) |
165 | + page(IMAGE_URI_TEMPLATE % "lucid") |
166 | + self.mocker.result(succeed( |
167 | + open(os.path.join(IMAGE_DATA_DIR, "lucid.txt")).read())) |
168 | self.mocker.replay() |
169 | d = get_current_ami(ubuntu_release_name="lucid", ebs=False) |
170 | |
171 | @@ -173,18 +178,54 @@ |
172 | the ec2 client's run instance method. A known set of default |
173 | is utilized. |
174 | """ |
175 | + |
176 | + page = self.mocker.replace("twisted.web.client.getPage") |
177 | + page(IMAGE_URI_TEMPLATE % "natty") |
178 | + self.mocker.result( |
179 | + succeed(open( |
180 | + os.path.join(IMAGE_DATA_DIR, "natty.txt")).read())) |
181 | + self.mocker.replay() |
182 | + |
183 | config = {} |
184 | - |
185 | d = get_machine_options(config, "zebra") |
186 | |
187 | def verify_result(result): |
188 | self.assertTrue(isinstance(result, dict)) |
189 | - self.assertEqual(result["image_id"], "ami-d2ba45bb") |
190 | + self.assertEqual(result["image_id"], "ami-06ad526f") |
191 | self.assertEqual(result["instance_type"], "m1.small") |
192 | |
193 | d.addCallback(verify_result) |
194 | return d |
195 | |
196 | + def test_get_machine_options_with_params(self): |
197 | + """ |
198 | + Image parameters can be specified to determine which ami is to |
199 | + be launched. Image paramters specified are not passed to the |
200 | + instance via user data. |
201 | + """ |
202 | + page = self.mocker.replace("twisted.web.client.getPage") |
203 | + page(IMAGE_URI_TEMPLATE % "natty") |
204 | + self.mocker.result( |
205 | + succeed(open( |
206 | + os.path.join(IMAGE_DATA_DIR, "natty.txt")).read())) |
207 | + self.mocker.replay() |
208 | + |
209 | + d = get_machine_options( |
210 | + {"default-instance-type": "m1.large"}, |
211 | + "zebra", image_arch="amd64", image_ebs=False) |
212 | + |
213 | + def verify_result(result): |
214 | + self.assertTrue(isinstance(result, dict)) |
215 | + self.assertEqual(result["image_id"], "ami-68ad5201") |
216 | + self.assertEqual(result["instance_type"], "m1.large") |
217 | + self.assertNotIn( |
218 | + "arch", result["user_data"]) |
219 | + self.assertNotIn( |
220 | + "ebs", result["user_data"]) |
221 | + |
222 | + d.addCallback(verify_result) |
223 | + return d |
224 | + |
225 | def test_configured_default_image_has_precedence_over_region(self): |
226 | """If the server machine image is specified it takes precendence over |
227 | region.""" |
228 | |
229 | === modified file 'ensemble/providers/ec2/utils.py' |
230 | --- ensemble/providers/ec2/utils.py 2011-06-03 18:11:39 +0000 |
231 | +++ ensemble/providers/ec2/utils.py 2011-06-28 20:16:40 +0000 |
232 | @@ -27,7 +27,7 @@ |
233 | return "https://ec2.%s.amazonaws.com" % region |
234 | |
235 | |
236 | -def get_current_ami(ubuntu_release_name="lucid", arch="i386", ebs=True, |
237 | +def get_current_ami(ubuntu_release_name="natty", arch="i386", ebs=True, |
238 | region="us-east-1", daily=False, desktop=False, |
239 | url_fetch=None): |
240 | """Get the latest ami for the last release of ubuntu.""" |
241 | @@ -143,6 +143,31 @@ |
242 | Given an ensemble environment configuration, extract the proper machine |
243 | information to be used for launching the machine via the ec2 api. |
244 | """ |
245 | + |
246 | + instance_type = config.get("default-instance-type", "m1.small") |
247 | + |
248 | + # XXX ideally should come from latest available or client release name. |
249 | + region = config.get("region", "us-east-1") |
250 | + image_id = config.get("default-image-id", None) |
251 | + |
252 | + # Lookup a standard ami by region, if none is specified, use any |
253 | + # specified image specification to locate an image, and remove the |
254 | + # image specification so it doesn't propogate to user data. |
255 | + if not image_id: |
256 | + params = {} |
257 | + for a_name, p_name in ( |
258 | + ("image_release_name", "ubuntu_release_name"), |
259 | + ("image_arch", "arch"), |
260 | + ("image_ebs", "ebs"), |
261 | + ("image_daily", "daily")): |
262 | + if a_name in kw: |
263 | + params[p_name] = kw[a_name] |
264 | + del kw[a_name] |
265 | + params["region"] = region |
266 | + d = get_current_ami(**params) |
267 | + else: |
268 | + d = succeed(image_id) |
269 | + |
270 | user_data = format_cloud_ini( |
271 | authorized_keys=authorized_keys, |
272 | packages=packages, |
273 | @@ -150,13 +175,6 @@ |
274 | scripts=scripts, |
275 | data=kw) |
276 | |
277 | - instance_type = config.get("default-instance-type", "m1.small") |
278 | - # XXX ideally should come from latest available or client release name, |
279 | - # for now to speed bootstrap, we use a prepopulated image by region. |
280 | - region = config.get("region", "us-east-1") |
281 | - image_id = config.get("default-image-id", AMI_REGION_MAP[region]) |
282 | - d = succeed(image_id) |
283 | - |
284 | def on_machine_image(current_image_id): |
285 | return {"image_id": current_image_id, |
286 | "min_count": 1, |
Overall, fine, I think point 0 is important and where we want to be in terms of installing ensemble on top of 'clean' APIs. I think the point I'm trying to make in [3] about configuration is also important. The rest is kinda nitpicky.
[0]
I think in general we need to support 3 options for the ensemble code.
a. distro's packages (which will be the 11.10 default)
b. a ppa's packages (tip will be be the default for most of our initial consumers)
c. a lp branch (the developers common case)
I think its a minor refactoring to support all 3 and will be well worth while to get this right.
47 + # These should be in the deb scripts. extend( [ ensemble" ])
48 + launch_
49 + "sudo mkdir -p /var/lib/ensemble",
50 + "sudo mkdir -p /var/log/
51 +
[1] This _should_ be in the deb.
123 class EC2UtilsTest( TestCase) : replace( "twisted. web.client. getPage" ) URI_TEMPLATE % "lucid") result( succeed( "")) replay( ) ami(ubuntu_ release_ name="lucid" )
124 @@ -28,7 +28,7 @@
125 a LookupError is raised.
126 """
127 page = self.mocker.
128 - page(SAMPLE_URI)
129 + page(IMAGE_
130 self.mocker.
131 self.mocker.
132 d = get_current_
[2] Our consumers are already plotting about 11.10. Even in our test cases we might benefit from removing release names to avoid feeling of bit rot as things move forward. Every 6 months these references look older and older. release-1, release-2 etc might make as much sense. I think we should also remove actual release names from the codebase like get_current_ami.
[3] related to the last note but I think ensemble. providers. ec2.utils. get_current_ ami should be renamed and retargeted based on a default from the environment file and remove the default disto assumption from here. This is something that will have to generally be in sync with what happens on orchestra and lxc providers in the future (even if they don't actually use an AMI). When someone is ready to transition their dev or production deployment environment to a new Ubuntu rev series it should default to a single decision they have to take.