Revision ffc64d7c
b/docs/man/snf-image-creator.rst | ||
---|---|---|
16 | 16 |
|
17 | 17 |
Options |
18 | 18 |
------- |
19 |
-a URL, --authentication-url=URL |
|
20 |
use this authentication URL when uploading/registering images |
|
21 |
|
|
22 |
-c CLOUD, --cloud=CLOUD |
|
23 |
use this saved cloud account to authenticate against a cloud when |
|
24 |
uploading/registering images |
|
19 | 25 |
|
20 | 26 |
--disable-sysprep=SYSPREP |
21 | 27 |
prevent SYSPREP operation from running on the input media |
... | ... | |
42 | 48 |
dump image to FILE |
43 | 49 |
|
44 | 50 |
--public |
45 |
register image with cyclades as public
|
|
51 |
register image with the storage service as public
|
|
46 | 52 |
|
47 | 53 |
--print-sysprep |
48 | 54 |
print the enabled and disabled system preparation operations for this |
49 | 55 |
input media |
50 | 56 |
|
51 | 57 |
-r IMAGENAME, --register=IMAGENAME |
52 |
register the image with cyclades as IMAGENAME
|
|
58 |
register the image with the compute service with name IMAGENAME
|
|
53 | 59 |
|
54 | 60 |
-s, --silent |
55 | 61 |
output only errors |
56 | 62 |
|
57 | 63 |
-t TOKEN, --token=TOKEN |
58 |
use this token when uploading/registering images to a Synnefo |
|
59 |
deployment |
|
64 |
use this token when uploading/registering images |
|
60 | 65 |
|
61 | 66 |
--tmpdir=DIR |
62 | 67 |
create large temporary image files under DIR |
63 | 68 |
|
64 | 69 |
-u FILENAME, --upload=FILENAME |
65 |
upload the image to pithos with name FILENAME
|
|
70 |
save the image to the storage service with remote name FILENAME
|
|
66 | 71 |
|
67 | 72 |
--version |
68 | 73 |
show program's version number and exit |
b/docs/usage.rst | ||
---|---|---|
28 | 28 |
-f, --force overwrite output files if they exist |
29 | 29 |
-s, --silent output only errors |
30 | 30 |
-u FILENAME, --upload=FILENAME |
31 |
upload the image to pithos with name FILENAME
|
|
31 |
upload the image to the storage service with name FILENAME
|
|
32 | 32 |
-r IMAGENAME, --register=IMAGENAME |
33 |
register the image with ~okeanos as IMAGENAME
|
|
33 |
register the image with the compute service as IMAGENAME
|
|
34 | 34 |
-m KEY=VALUE, --metadata=KEY=VALUE |
35 | 35 |
add custom KEY=VALUE metadata to the image |
36 | 36 |
-t TOKEN, --token=TOKEN |
... | ... | |
51 | 51 |
media |
52 | 52 |
--no-sysprep don't perform any system preparation operation |
53 | 53 |
--no-shrink don't shrink any partition |
54 |
--public register image with cyclades as public
|
|
54 |
--public register image with the compute service as public
|
|
55 | 55 |
--tmpdir=DIR create large temporary image files under DIR |
56 | 56 |
|
57 | 57 |
Most input options are self-describing. If you want to save a local copy of |
58 | 58 |
the image you create, provide a filename using the *-o* option. To upload the |
59 |
image to *pithos+*, provide valid cloud API access info (by either using a |
|
60 |
token with *-t* and a URL with *-a* pair or a cloud name with *-c*) and a |
|
61 |
filename using *-u*. If you also want to register the image with *~okeanos*, in |
|
62 |
addition to *-u* provide a registration name using *-r*. All images are |
|
59 |
image to the storage service of a cloud, provide valid cloud API access info |
|
60 |
(by either using a token and a URL with *-t* and *-a* respectively, or a cloud |
|
61 |
name with *-c*) and a remote filename using *-u*. If you also want to register |
|
62 |
the image with the compute service of the cloud, in addition to *-u* provide a |
|
63 |
registration name using *-r*. All images are |
|
63 | 64 |
registered as *private*. Only the user that registers the image can create |
64 | 65 |
VM's out of it. If you want the image to be visible by other user too, use the |
65 | 66 |
*--public* option. |
... | ... | |
187 | 188 |
(ex. "Slackware Linux 14.0 with KDE") |
188 | 189 |
* Registration Type: Private or Public |
189 | 190 |
|
190 |
After confirming, the image will be extracted, uploaded to *pithos+* and
|
|
191 |
registered with *~okeanos*. The user will also be given the choice to keep a
|
|
192 |
local copy of it. |
|
191 |
After confirming, the image will be extracted, uploaded to the storage service
|
|
192 |
and registered with the compute service of the selected cloud. The user will
|
|
193 |
also be given the choice to keep a local copy of it.
|
|
193 | 194 |
|
194 | 195 |
For most users the functionality this mode provides should be sufficient. |
195 | 196 |
|
... | ... | |
211 | 212 |
In the *Register* sub-menu the user can provide: |
212 | 213 |
|
213 | 214 |
* Which cloud account to use |
214 |
* A *pithos+* filename for the uploaded *diskdump* image
|
|
215 |
* A name for the image to use when registering it with *~cyclades*, as well as
|
|
216 |
the registration type (*private* or *public*) |
|
215 |
* A filename for the uploaded *diskdump* image |
|
216 |
* A name for the image to use when registering it with the storage service of
|
|
217 |
the cloud, as well as the registration type (*private* or *public*)
|
|
217 | 218 |
|
218 | 219 |
By choosing the *Extract* menu entry, the user can dump the image to the local |
219 | 220 |
file system. Finally, if the user selects *Reset*, the system will ignore |
... | ... | |
283 | 284 |
|
284 | 285 |
.. image:: /snapshots/wizard.png |
285 | 286 |
|
286 |
Then you will be asked to provide a name, a description, a registration type
|
|
287 |
(*private* or *public*) and the authentication token corresponding to your
|
|
288 |
*~okeanos* account. Finally, you'll be asked to confirm the provided data.
|
|
287 |
Then you will be asked to select a cloud and provide a name, a description and
|
|
288 |
a registration type (*private* or *public*). Finally, you'll be asked to
|
|
289 |
confirm the provided data. |
|
289 | 290 |
|
290 | 291 |
.. image:: /snapshots/confirm.png |
291 | 292 |
|
292 |
Choosing *YES* will create and upload the image to your *~okeanos* account.
|
|
293 |
Choosing *YES* will create and upload the image to your cloud account.
|
|
293 | 294 |
|
294 | 295 |
Limitations |
295 | 296 |
=========== |
... | ... | |
311 | 312 |
Para-virtualized drivers |
312 | 313 |
------------------------ |
313 | 314 |
|
314 |
*~Okeanos* uses the *VirtIO* framework. The disk I/O controller and the
|
|
315 |
Ethernet cards on the VM instances are para-virtualized and need special
|
|
316 |
*VirtIO* drivers. Those drivers are included in the Linux Kernel mainline since
|
|
317 |
version 2.6.25 and are shipped with all the popular Linux distributions. The
|
|
318 |
problem is that if the driver for the para-virtualized disk I/O controller is
|
|
319 |
built as module, it needs to be preloaded using an initial ramdisk, otherwise
|
|
320 |
the VM won't be able to boot. |
|
315 |
Most synnefo deployments uses the *VirtIO* framework. The disk I/O controller
|
|
316 |
and the Ethernet cards on the VM instances are para-virtualized and need
|
|
317 |
special *VirtIO* drivers. Those drivers are included in the Linux Kernel
|
|
318 |
mainline since version 2.6.25 and are shipped with all the popular Linux
|
|
319 |
distributions. The problem is that if the driver for the para-virtualized disk
|
|
320 |
I/O controller is built as module, it needs to be preloaded using an initial
|
|
321 |
ramdisk, otherwise the VM won't be able to boot.
|
|
321 | 322 |
|
322 | 323 |
Many popular Linux distributions, like Ubuntu and Debian, will automatically |
323 | 324 |
create a generic initial ramdisk file that contains many different modules, |
b/image_creator/dialog_menu.py | ||
---|---|---|
113 | 113 |
|
114 | 114 |
|
115 | 115 |
def upload_image(session): |
116 |
"""Upload the image to pithos+"""
|
|
116 |
"""Upload the image to the storage service"""
|
|
117 | 117 |
d = session["dialog"] |
118 | 118 |
image = session['image'] |
119 | 119 |
meta = session['metadata'] |
... | ... | |
121 | 121 |
|
122 | 122 |
if "account" not in session: |
123 | 123 |
d.msgbox("You need to select a valid cloud before you can upload " |
124 |
"images to pithos+", width=SMALL_WIDTH)
|
|
124 |
"images to it", width=SMALL_WIDTH)
|
|
125 | 125 |
return False |
126 | 126 |
|
127 | 127 |
while 1: |
... | ... | |
149 | 149 |
overwrite.append(f) |
150 | 150 |
|
151 | 151 |
if len(overwrite) > 0: |
152 |
if d.yesno("The following pithos object(s) already exist(s):\n"
|
|
153 |
"%s\nDo you want to overwrite them?" % |
|
152 |
if d.yesno("The following storage service object(s) already "
|
|
153 |
"exist(s):\n%s\nDo you want to overwrite them?" %
|
|
154 | 154 |
"\n".join(overwrite), width=WIDTH, defaultno=1): |
155 | 155 |
continue |
156 | 156 |
|
... | ... | |
182 | 182 |
out.success("done") |
183 | 183 |
|
184 | 184 |
except ClientError as e: |
185 |
d.msgbox("Error in pithos+ client: %s" % e.message, |
|
186 |
title="Pithos+ Client Error", width=SMALL_WIDTH) |
|
185 |
d.msgbox( |
|
186 |
"Error in storage service client: %s" % e.message, |
|
187 |
title="Storage Service Client Error", width=SMALL_WIDTH) |
|
187 | 188 |
if 'pithos_uri' in session: |
188 | 189 |
del session['pithos_uri'] |
189 | 190 |
return False |
... | ... | |
192 | 193 |
finally: |
193 | 194 |
gauge.cleanup() |
194 | 195 |
|
195 |
d.msgbox("Image file `%s' was successfully uploaded to pithos+" % filename,
|
|
196 |
d.msgbox("Image file `%s' was successfully uploaded" % filename, |
|
196 | 197 |
width=SMALL_WIDTH) |
197 | 198 |
|
198 | 199 |
return True |
199 | 200 |
|
200 | 201 |
|
201 | 202 |
def register_image(session): |
202 |
"""Register image with cyclades"""
|
|
203 |
"""Register image with the compute service"""
|
|
203 | 204 |
d = session["dialog"] |
204 | 205 |
|
205 | 206 |
is_public = False |
206 | 207 |
|
207 | 208 |
if "account" not in session: |
208 | 209 |
d.msgbox("You need to select a valid cloud before you " |
209 |
"can register an images with cyclades", width=SMALL_WIDTH)
|
|
210 |
"can register an images with it", width=SMALL_WIDTH)
|
|
210 | 211 |
return False |
211 | 212 |
|
212 | 213 |
if "pithos_uri" not in session: |
213 |
d.msgbox("You need to upload the image to pithos+ before you can "
|
|
214 |
"register it with cyclades", width=SMALL_WIDTH)
|
|
214 |
d.msgbox("You need to upload the image to the cloud before you can "
|
|
215 |
"register it", width=SMALL_WIDTH) |
|
215 | 216 |
return False |
216 | 217 |
|
217 | 218 |
while 1: |
... | ... | |
248 | 249 |
out.add(gauge) |
249 | 250 |
try: |
250 | 251 |
try: |
251 |
out.output("Registering %s image with Cyclades..." % img_type)
|
|
252 |
out.output("Registering %s image with the cloud..." % img_type)
|
|
252 | 253 |
kamaki = Kamaki(session['account'], out) |
253 | 254 |
result = kamaki.register(name, session['pithos_uri'], metadata, |
254 | 255 |
is_public) |
... | ... | |
266 | 267 |
kamaki.share("%s.md5sum" % session['upload']) |
267 | 268 |
out.success('done') |
268 | 269 |
except ClientError as e: |
269 |
d.msgbox("Error in pithos+ client: %s" % e.message)
|
|
270 |
d.msgbox("Error in storage service client: %s" % e.message)
|
|
270 | 271 |
return False |
271 | 272 |
finally: |
272 | 273 |
out.remove(gauge) |
273 | 274 |
finally: |
274 | 275 |
gauge.cleanup() |
275 | 276 |
|
276 |
d.msgbox("%s image `%s' was successfully registered with Cyclades as `%s'"
|
|
277 |
d.msgbox("%s image `%s' was successfully registered with the cloud as `%s'"
|
|
277 | 278 |
% (img_type.title(), session['upload'], name), width=SMALL_WIDTH) |
278 | 279 |
return True |
279 | 280 |
|
... | ... | |
374 | 375 |
choices = [("Add/Edit", "Add/Edit cloud accounts"), |
375 | 376 |
("Delete", "Delete existing cloud accounts"), |
376 | 377 |
("Cloud", "Select cloud account to use: %s" % cloud), |
377 |
("Upload", "Upload image to pithos+"),
|
|
378 |
("Register", "Register the image to cyclades: %s" % upload)]
|
|
378 |
("Upload", "Upload image to the cloud"),
|
|
379 |
("Register", "Register image with the cloud: %s" % upload)]
|
|
379 | 380 |
|
380 | 381 |
(code, choice) = d.menu( |
381 | 382 |
text="Choose one of the following or press <Back> to go back.", |
... | ... | |
791 | 792 |
text="Choose one of the following or press <Exit> to exit.", |
792 | 793 |
width=WIDTH, choices=choices, cancel="Exit", height=13, |
793 | 794 |
default_item=default_item, menu_height=len(choices), |
794 |
title="Image Creator for ~okeanos (snf-image-creator version %s)" %
|
|
795 |
title="Image Creator for synnefo (snf-image-creator version %s)" %
|
|
795 | 796 |
version) |
796 | 797 |
|
797 | 798 |
if code in (d.DIALOG_CANCEL, d.DIALOG_ESC): |
b/image_creator/dialog_wizard.py | ||
---|---|---|
353 | 353 |
|
354 | 354 |
out.output() |
355 | 355 |
try: |
356 |
out.output("Uploading image to pithos:")
|
|
356 |
out.output("Uploading image to the cloud:")
|
|
357 | 357 |
account = Kamaki.get_account(wizard['Cloud']) |
358 | 358 |
assert account, "Cloud: %s is not valid" % wizard['Cloud'] |
359 | 359 |
kamaki = Kamaki(account, out) |
... | ... | |
375 | 375 |
|
376 | 376 |
is_public = True if wizard['ImageRegistration'] == "Public" else \ |
377 | 377 |
False |
378 |
out.output('Registering %s image with cyclades ...' %
|
|
378 |
out.output('Registering %s image with the cloud ...' %
|
|
379 | 379 |
wizard['ImageRegistration'].lower(), False) |
380 | 380 |
result = kamaki.register(wizard['ImageName'], pithos_file, |
381 | 381 |
metadata, is_public) |
... | ... | |
397 | 397 |
out.output() |
398 | 398 |
|
399 | 399 |
except ClientError as e: |
400 |
raise FatalError("Pithos client: %d %s" % (e.status, e.message)) |
|
400 |
raise FatalError("Storage service client: %d %s" % |
|
401 |
(e.status, e.message)) |
|
401 | 402 |
finally: |
402 | 403 |
out.remove(with_progress) |
403 | 404 |
|
404 |
msg = "The %s image was successfully uploaded to Pithos and registered " \ |
|
405 |
"with Cyclades. Would you like to keep a local copy?" \ |
|
406 |
% wizard['ImageRegistration'].lower() |
|
407 |
if not d.yesno(msg, width=PAGE_WIDTH): |
|
405 |
text = "The %s image was successfully uploaded to the storage service " \ |
|
406 |
"and registered with the compute service of %s. Would you like " \ |
|
407 |
"to keep a local copy?" % \ |
|
408 |
(wizard['Cloud'], wizard['ImageRegistration'].lower()) |
|
409 |
|
|
410 |
if not d.yesno(text, width=PAGE_WIDTH): |
|
408 | 411 |
extract_image(session) |
409 | 412 |
|
410 | 413 |
# vim: set sta sts=4 shiftwidth=4 sw=4 et ai : |
b/image_creator/help/image_properties.rst | ||
---|---|---|
11 | 11 |
This is a space-seperated list of users, whose password will |
12 | 12 |
be reset during deployment. |
13 | 13 |
- SWAP=<n>:<size> |
14 |
If this property is present, cyclades will create a swap
|
|
15 |
partition with given size at the end of the instance's disk.
|
|
14 |
If this property is present, a swap partition with given
|
|
15 |
size will be created at the end of the instance's disk.
|
|
16 | 16 |
This property only makes sense for Linux images. |
17 | 17 |
|
18 |
Properties used by the ~okeanos User Interface
|
|
18 |
Properties used by the synnefo User Interface
|
|
19 | 19 |
---------------------------------------------- |
20 | 20 |
- OS |
21 | 21 |
The value of this property is used to associate the image |
b/image_creator/kamaki_wrapper.py | ||
---|---|---|
163 | 163 |
self.CONTAINER, path) |
164 | 164 |
|
165 | 165 |
def register(self, name, location, metadata, public=False): |
166 |
"""Register an image to ~okeanos"""
|
|
166 |
"""Register an image with cyclades"""
|
|
167 | 167 |
|
168 | 168 |
# Convert all metadata to strings |
169 | 169 |
str_metadata = {} |
b/image_creator/main.py | ||
---|---|---|
83 | 83 |
|
84 | 84 |
parser.add_option("-u", "--upload", dest="upload", type="string", |
85 | 85 |
default=False, |
86 |
help="upload the image to pithos with name FILENAME",
|
|
86 |
help="upload the image to the cloud with name FILENAME",
|
|
87 | 87 |
metavar="FILENAME") |
88 | 88 |
|
89 | 89 |
parser.add_option("-r", "--register", dest="register", type="string", |
90 | 90 |
default=False, |
91 |
help="register the image with ~okeanos as IMAGENAME",
|
|
91 |
help="register the image with a cloud as IMAGENAME",
|
|
92 | 92 |
metavar="IMAGENAME") |
93 | 93 |
|
94 | 94 |
parser.add_option("-m", "--metadata", dest="metadata", default=[], |
... | ... | |
129 | 129 |
help="don't shrink any partition", action="store_false") |
130 | 130 |
|
131 | 131 |
parser.add_option("--public", dest="public", default=False, |
132 |
help="register image with cyclades as public",
|
|
132 |
help="register image with the cloud as public",
|
|
133 | 133 |
action="store_true") |
134 | 134 |
|
135 | 135 |
parser.add_option("--tmpdir", dest="tmp", type="string", default=None, |
... | ... | |
231 | 231 |
|
232 | 232 |
if options.upload and not options.force: |
233 | 233 |
if kamaki.object_exists(options.upload): |
234 |
raise FatalError("Remote pithos object `%s' exists "
|
|
234 |
raise FatalError("Remote storage service object: `%s' exists "
|
|
235 | 235 |
"(use --force to overwrite it)." % options.upload) |
236 | 236 |
if kamaki.object_exists("%s.md5sum" % options.upload): |
237 |
raise FatalError("Remote pithos object `%s.md5sum' exists " |
|
238 |
"(use --force to overwrite it)." % options.upload) |
|
237 |
raise FatalError("Remote storage service object: `%s.md5sum' " |
|
238 |
"exists (use --force to overwrite it)." % |
|
239 |
options.upload) |
|
239 | 240 |
|
240 | 241 |
if options.register and not options.force: |
241 | 242 |
if kamaki.object_exists("%s.meta" % options.upload): |
242 |
raise FatalError("Remote pithos object `%s.meta' exists "
|
|
243 |
raise FatalError("Remote storage service object `%s.meta' exists "
|
|
243 | 244 |
"(use --force to overwrite it)." % options.upload) |
244 | 245 |
|
245 | 246 |
disk = Disk(options.source, out, options.tmp) |
... | ... | |
306 | 307 |
try: |
307 | 308 |
uploaded_obj = "" |
308 | 309 |
if options.upload: |
309 |
out.output("Uploading image to pithos:")
|
|
310 |
out.output("Uploading image to the storage service:")
|
|
310 | 311 |
with open(snapshot, 'rb') as f: |
311 | 312 |
uploaded_obj = kamaki.upload( |
312 | 313 |
f, size, options.upload, |
... | ... | |
323 | 324 |
|
324 | 325 |
if options.register: |
325 | 326 |
img_type = 'public' if options.public else 'private' |
326 |
out.output('Registering %s image with ~okeanos ...' % img_type,
|
|
327 |
False) |
|
327 |
out.output('Registering %s image with the compute service ...'
|
|
328 |
% img_type, False)
|
|
328 | 329 |
result = kamaki.register(options.register, uploaded_obj, |
329 | 330 |
metadata, options.public) |
330 | 331 |
out.success('done') |
... | ... | |
344 | 345 |
|
345 | 346 |
out.output() |
346 | 347 |
except ClientError as e: |
347 |
raise FatalError("Pithos client: %d %s" % (e.status, e.message))
|
|
348 |
raise FatalError("Service client: %d %s" % (e.status, e.message))
|
|
348 | 349 |
|
349 | 350 |
finally: |
350 | 351 |
out.output('cleaning up ...') |
Also available in: Unified diff