root / snf-cyclades-app / synnefo / volume / snapshots.py @ f518210b
History | View | Annotate | Download (3.3 kB)
1 | dec501fa | Christos Stavrakakis | import datetime |
---|---|---|---|
2 | dec501fa | Christos Stavrakakis | from django.utils import simplejson as json |
3 | dec501fa | Christos Stavrakakis | from django.db import transaction |
4 | dec501fa | Christos Stavrakakis | from snf_django.lib.api import faults |
5 | dec501fa | Christos Stavrakakis | from snf_django.lib.api.utils import isoformat |
6 | dec501fa | Christos Stavrakakis | from synnefo.plankton.utils import image_backend |
7 | dec501fa | Christos Stavrakakis | from synnefo.logic import backend |
8 | dec501fa | Christos Stavrakakis | from synnefo.volume import util |
9 | dec501fa | Christos Stavrakakis | |
10 | dec501fa | Christos Stavrakakis | SNAPSHOTS_CONTAINER = "snapshots"
|
11 | dec501fa | Christos Stavrakakis | SNAPSHOTS_DOMAIN = "plankton"
|
12 | dec501fa | Christos Stavrakakis | SNAPSHOTS_PREFIX = "plankton:"
|
13 | dec501fa | Christos Stavrakakis | SNAPSHOTS_TYPE = "application/octet-stream"
|
14 | dec501fa | Christos Stavrakakis | SNAPSHOTS_MAPFILE_PREFIX = "archip:"
|
15 | dec501fa | Christos Stavrakakis | |
16 | dec501fa | Christos Stavrakakis | |
17 | dec501fa | Christos Stavrakakis | @transaction.commit_on_success
|
18 | dec501fa | Christos Stavrakakis | def create(user_id, volume, name, description, metadata, force=False): |
19 | dec501fa | Christos Stavrakakis | |
20 | dec501fa | Christos Stavrakakis | if volume.machine is None: |
21 | dec501fa | Christos Stavrakakis | raise faults.BadRequest("Can not snapshot detached volume!") |
22 | dec501fa | Christos Stavrakakis | |
23 | f518210b | Christos Stavrakakis | flavor = volume.machine.flavor |
24 | f518210b | Christos Stavrakakis | if not flavor.disk_template.startswith("ext_"): |
25 | f518210b | Christos Stavrakakis | msg = ("Snapshots are supported only for volumes of ext_*"
|
26 | f518210b | Christos Stavrakakis | " disk template")
|
27 | f518210b | Christos Stavrakakis | raise faults.BadRequest(msg)
|
28 | f518210b | Christos Stavrakakis | |
29 | dec501fa | Christos Stavrakakis | volume.snapshot_counter += 1
|
30 | dec501fa | Christos Stavrakakis | volume.save() |
31 | e7953d63 | Christos Stavrakakis | transaction.commit() |
32 | dec501fa | Christos Stavrakakis | |
33 | dec501fa | Christos Stavrakakis | snapshot_metadata = {} |
34 | e7953d63 | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "name"] = name
|
35 | dec501fa | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "description"] = description
|
36 | dec501fa | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "metadata"] = json.dumps(metadata)
|
37 | dec501fa | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "volume_id"] = volume.id
|
38 | dec501fa | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "status"] = "CREATING" |
39 | dec501fa | Christos Stavrakakis | #XXX: just to work
|
40 | dec501fa | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "is_snapshot"] = True |
41 | e7953d63 | Christos Stavrakakis | #XXX: for images
|
42 | e7953d63 | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "store"] = "pithos" |
43 | e7953d63 | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "disk_format"] = "diskdump" |
44 | e7953d63 | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "default_container_format"] = "bare" |
45 | e7953d63 | Christos Stavrakakis | # XXX: Hack-ish way to clone the metadata
|
46 | e7953d63 | Christos Stavrakakis | image_properties = {"EXCLUDE_ALL_TASKS": "yes", |
47 | e7953d63 | Christos Stavrakakis | "description": description}
|
48 | e7953d63 | Christos Stavrakakis | vm_metadata = dict(volume.machine.metadata.values_list("meta_key", "meta_value")) |
49 | e7953d63 | Christos Stavrakakis | for key in ["OS", "users"]: |
50 | e7953d63 | Christos Stavrakakis | val = vm_metadata.get(key) |
51 | e7953d63 | Christos Stavrakakis | if val is not None: |
52 | e7953d63 | Christos Stavrakakis | image_properties[key] = val |
53 | e7953d63 | Christos Stavrakakis | snapshot_metadata[SNAPSHOTS_PREFIX + "properties"] = json.dumps(image_properties)
|
54 | dec501fa | Christos Stavrakakis | |
55 | dec501fa | Christos Stavrakakis | snapshot_name = generate_snapshot_name(volume) |
56 | dec501fa | Christos Stavrakakis | mapfile = SNAPSHOTS_MAPFILE_PREFIX + snapshot_name |
57 | dec501fa | Christos Stavrakakis | |
58 | e7953d63 | Christos Stavrakakis | size = volume.size << 30
|
59 | dec501fa | Christos Stavrakakis | with image_backend(user_id) as pithos_backend: |
60 | dec501fa | Christos Stavrakakis | # move this to plankton backend
|
61 | dec501fa | Christos Stavrakakis | snapshot_uuid = pithos_backend.backend.register_object_map( |
62 | dec501fa | Christos Stavrakakis | user=user_id, |
63 | dec501fa | Christos Stavrakakis | account=user_id, |
64 | dec501fa | Christos Stavrakakis | container=SNAPSHOTS_CONTAINER, |
65 | e7953d63 | Christos Stavrakakis | name=snapshot_name, |
66 | e7953d63 | Christos Stavrakakis | size=size, |
67 | e7953d63 | Christos Stavrakakis | domain=SNAPSHOTS_DOMAIN, |
68 | dec501fa | Christos Stavrakakis | type=SNAPSHOTS_TYPE, |
69 | dec501fa | Christos Stavrakakis | mapfile=mapfile, |
70 | dec501fa | Christos Stavrakakis | meta=snapshot_metadata, |
71 | e7953d63 | Christos Stavrakakis | replace_meta=True,
|
72 | dec501fa | Christos Stavrakakis | permissions=None)
|
73 | dec501fa | Christos Stavrakakis | #checksum=None,
|
74 | dec501fa | Christos Stavrakakis | |
75 | e7953d63 | Christos Stavrakakis | backend.snapshot_instance(volume.machine, snapshot_name=snapshot_name) |
76 | dec501fa | Christos Stavrakakis | |
77 | dec501fa | Christos Stavrakakis | snapshot = util.get_snapshot(user_id, snapshot_uuid) |
78 | dec501fa | Christos Stavrakakis | |
79 | dec501fa | Christos Stavrakakis | return snapshot
|
80 | dec501fa | Christos Stavrakakis | |
81 | dec501fa | Christos Stavrakakis | |
82 | dec501fa | Christos Stavrakakis | def generate_snapshot_name(volume): |
83 | dec501fa | Christos Stavrakakis | time = isoformat(datetime.datetime.now()) |
84 | e7953d63 | Christos Stavrakakis | return "snf-snapshot-of-volume-%s-%s" % (volume.id, |
85 | e7953d63 | Christos Stavrakakis | volume.snapshot_counter) |
86 | dec501fa | Christos Stavrakakis | |
87 | dec501fa | Christos Stavrakakis | |
88 | dec501fa | Christos Stavrakakis | @transaction.commit_on_success
|
89 | dec501fa | Christos Stavrakakis | def delete(snapshot): |
90 | dec501fa | Christos Stavrakakis | user_id = snapshot["owner"]
|
91 | dec501fa | Christos Stavrakakis | with image_backend(user_id) as pithos_backend: |
92 | dec501fa | Christos Stavrakakis | pithos_backend.delete_snapshot(snapshot["uuid"])
|
93 | dec501fa | Christos Stavrakakis | return snapshot |