Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / volume / volumes.py @ 18ca395d

History | View | Annotate | Download (4.1 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
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.SOURCE_VOLUME_PREFIX + str(source_volume_id)
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
        origin = source_snapshot["checksum"]
53
        source = Volume.SOURCE_SNAPSHOT_PREFIX + str(source_snapshot_id)
54
    elif source_image_id is not None:
55
        source_image = util.get_image(user_id, source_image_id,
56
                                      exception=faults.BadRequest)
57
        origin = source_image["checksum"]
58
        source = Volume.SOURCE_IMAGE_PREFIX + str(source_image_id)
59

    
60
    volume = Volume.objects.create(userid=user_id,
61
                                   size=size,
62
                                   name=name,
63
                                   machine=server,
64
                                   description=description,
65
                                   source=source,
66
                                   origin=origin,
67
                                   #volume_type=volume_type,
68
                                   status="CREATING")
69

    
70
    if metadata is not None:
71
        for meta_key, meta_val in metadata.items():
72
            volume.metadata.create(key=meta_key, value=meta_val)
73

    
74
    # Create the disk in the backend
75
    volume.backendjobid = backend.attach_volume(server, volume)
76
    volume.save()
77

    
78
    return volume
79

    
80

    
81
@transaction.commit_on_success
82
def delete(volume):
83
    """Delete a Volume"""
84
    # A volume is deleted by detaching it from the server that is attached.
85
    # Deleting a detached volume is not implemented.
86
    if volume.index == 0:
87
        raise faults.BadRequest("Cannot detach the root volume of a server")
88

    
89
    if volume.machine_id is not None:
90
        volume.backendjobid = backend.detach_volume(volume.machine, volume)
91
        log.info("Detach volume '%s' from server '%s', job: %s",
92
                 volume.id, volume.machine_id, volume.backendjobid)
93
    else:
94
        raise faults.BadRequest("Cannot delete a detached volume")
95

    
96
    return volume
97

    
98

    
99
@transaction.commit_on_success
100
def rename(volume, new_name):
101
    volume.name = new_name
102
    volume.save()
103
    return volume
104

    
105

    
106
@transaction.commit_on_success
107
def update_description(volume, new_description):
108
    volume.description = new_description
109
    volume.save()
110
    return volume