root / snf-cyclades-app / synnefo / volume / volumes.py @ c19ad1e9
History | View | Annotate | Download (4 kB)
1 |
import logging |
---|---|
2 |
|
3 |
from django.db import transaction |
4 |
from synnefo.db.models import Volume |
5 |
from snf_django.lib.api import faults |
6 |
from synnefo.volume import util |
7 |
from synnefo.logic import backend, servers |
8 |
|
9 |
log = logging.getLogger(__name__) |
10 |
|
11 |
|
12 |
@transaction.commit_on_success
|
13 |
def create(user_id, size, server_id, name=None, description=None, |
14 |
source_volume_id=None, source_snapshot_id=None, |
15 |
source_image_id=None, metadata=None): |
16 |
|
17 |
if server_id is None: |
18 |
raise faults.BadRequest("Volume must be attached to server") |
19 |
server = util.get_server(user_id, server_id, for_update=True,
|
20 |
exception=faults.BadRequest) |
21 |
|
22 |
# Assert that not more than one source are used
|
23 |
sources = filter(lambda x: x is not None, |
24 |
[source_volume_id, source_snapshot_id, source_image_id]) |
25 |
if len(sources) > 1: |
26 |
raise faults.BadRequest("Volume can not have more than one source!") |
27 |
|
28 |
# Only ext_ disk template supports cloning from another source
|
29 |
disk_template = server.flavor.disk_template |
30 |
if not disk_template.startswith("ext_") and sources: |
31 |
msg = ("Volumes of '%s' disk template cannot have a source" %
|
32 |
disk_template) |
33 |
raise faults.BadRequest(msg)
|
34 |
|
35 |
origin = None
|
36 |
source = None
|
37 |
if source_volume_id is not None: |
38 |
source_volume = util.get_volume(user_id, source_volume_id, |
39 |
for_update=True,
|
40 |
exception=faults.BadRequest) |
41 |
# Check that volume is ready to be snapshotted
|
42 |
if source_volume.status != "AVAILABLE": |
43 |
msg = ("Cannot take a snapshot while snapshot is in '%s' state"
|
44 |
% source_volume.status) |
45 |
raise faults.BadRequest(msg)
|
46 |
source = Volume.prefix_source(source_volume_id, source_type="volume")
|
47 |
origin = source_volume.backend_volume_uuid |
48 |
elif source_snapshot_id is not None: |
49 |
source_snapshot = util.get_snapshot(user_id, source_snapshot_id, |
50 |
exception=faults.BadRequest) |
51 |
# TODO: Check the state of the snapshot!!
|
52 |
source = Volume.prefix_source(source_snapshot_id, |
53 |
source_type="snapshot")
|
54 |
origin = source_snapshot["checksum"]
|
55 |
elif source_image_id is not None: |
56 |
source_image = util.get_image(user_id, source_image_id, |
57 |
exception=faults.BadRequest) |
58 |
source = Volume.prefix_source(source_image_id, source_type="image")
|
59 |
origin = source_image["checksum"]
|
60 |
|
61 |
volume = Volume.objects.create(userid=user_id, |
62 |
size=size, |
63 |
name=name, |
64 |
machine=server, |
65 |
description=description, |
66 |
source=source, |
67 |
origin=origin, |
68 |
#volume_type=volume_type,
|
69 |
status="CREATING")
|
70 |
|
71 |
if metadata is not None: |
72 |
for meta_key, meta_val in metadata.items(): |
73 |
volume.metadata.create(key=meta_key, value=meta_val) |
74 |
|
75 |
servers.attach_volume(server, volume) |
76 |
|
77 |
return volume
|
78 |
|
79 |
|
80 |
@transaction.commit_on_success
|
81 |
def delete(volume): |
82 |
"""Delete a Volume"""
|
83 |
# A volume is deleted by detaching it from the server that is attached.
|
84 |
# Deleting a detached volume is not implemented.
|
85 |
if volume.machine_id is not None: |
86 |
servers.detach_volume(volume.machine, volume) |
87 |
log.info("Detach volume '%s' from server '%s', job: %s",
|
88 |
volume.id, volume.machine_id, volume.backendjobid) |
89 |
else:
|
90 |
raise faults.BadRequest("Cannot delete a detached volume") |
91 |
|
92 |
return volume
|
93 |
|
94 |
|
95 |
@transaction.commit_on_success
|
96 |
def rename(volume, new_name): |
97 |
volume.name = new_name |
98 |
volume.save() |
99 |
return volume
|
100 |
|
101 |
|
102 |
@transaction.commit_on_success
|
103 |
def update_description(volume, new_description): |
104 |
volume.description = new_description |
105 |
volume.save() |
106 |
return volume
|