Statistics
| Branch: | Tag: | Revision:

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