root / snf-cyclades-app / synnefo / logic / server_attachments.py @ d05e5324
History | View | Annotate | Download (5.1 kB)
1 | 5d805533 | Christos Stavrakakis | # Copyright 2011, 2012, 2013 GRNET S.A. All rights reserved.
|
---|---|---|---|
2 | 5d805533 | Christos Stavrakakis | #
|
3 | 5d805533 | Christos Stavrakakis | # Redistribution and use in source and binary forms, with or without
|
4 | 5d805533 | Christos Stavrakakis | # modification, are permitted provided that the following conditions
|
5 | 5d805533 | Christos Stavrakakis | # are met:
|
6 | 5d805533 | Christos Stavrakakis | #
|
7 | 5d805533 | Christos Stavrakakis | # 1. Redistributions of source code must retain the above copyright
|
8 | 5d805533 | Christos Stavrakakis | # notice, this list of conditions and the following disclaimer.
|
9 | 5d805533 | Christos Stavrakakis | #
|
10 | 5d805533 | Christos Stavrakakis | # 2. Redistributions in binary form must reproduce the above copyright
|
11 | 5d805533 | Christos Stavrakakis | # notice, this list of conditions and the following disclaimer in the
|
12 | 5d805533 | Christos Stavrakakis | # documentation and/or other materials provided with the distribution.
|
13 | 5d805533 | Christos Stavrakakis | #
|
14 | 5d805533 | Christos Stavrakakis | # THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
15 | 5d805533 | Christos Stavrakakis | # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
16 | 5d805533 | Christos Stavrakakis | # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
17 | 5d805533 | Christos Stavrakakis | # ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
18 | 5d805533 | Christos Stavrakakis | # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
19 | 5d805533 | Christos Stavrakakis | # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
20 | 5d805533 | Christos Stavrakakis | # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
21 | 5d805533 | Christos Stavrakakis | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
22 | 5d805533 | Christos Stavrakakis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
23 | 5d805533 | Christos Stavrakakis | # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
24 | 5d805533 | Christos Stavrakakis | # SUCH DAMAGE.
|
25 | 5d805533 | Christos Stavrakakis | #
|
26 | 5d805533 | Christos Stavrakakis | # The views and conclusions contained in the software and documentation are
|
27 | 5d805533 | Christos Stavrakakis | # those of the authors and should not be interpreted as representing official
|
28 | 5d805533 | Christos Stavrakakis | # policies, either expressed or implied, of GRNET S.A.
|
29 | 5d805533 | Christos Stavrakakis | |
30 | 5d805533 | Christos Stavrakakis | import logging |
31 | 5d805533 | Christos Stavrakakis | |
32 | 5d805533 | Christos Stavrakakis | from snf_django.lib.api import faults |
33 | 5d805533 | Christos Stavrakakis | from django.conf import settings |
34 | 5d805533 | Christos Stavrakakis | from synnefo.logic import backend, commands |
35 | 5d805533 | Christos Stavrakakis | |
36 | 5d805533 | Christos Stavrakakis | log = logging.getLogger(__name__) |
37 | 5d805533 | Christos Stavrakakis | |
38 | 5d805533 | Christos Stavrakakis | |
39 | 5d805533 | Christos Stavrakakis | def attach_volume(vm, volume): |
40 | 5d805533 | Christos Stavrakakis | """Attach a volume to a server.
|
41 | 5d805533 | Christos Stavrakakis |
|
42 | 5d805533 | Christos Stavrakakis | The volume must be in 'AVAILABLE' status in order to be attached. Also,
|
43 | 5d805533 | Christos Stavrakakis | number of the volumes that are attached to the server must remain less
|
44 | 5d805533 | Christos Stavrakakis | than 'GANETI_MAX_DISKS_PER_INSTANCE' setting. This function will send
|
45 | 5d805533 | Christos Stavrakakis | the corresponding job to Ganeti backend and update the status of the
|
46 | 5d805533 | Christos Stavrakakis | volume to 'ATTACHING'.
|
47 | 5d805533 | Christos Stavrakakis |
|
48 | 5d805533 | Christos Stavrakakis | """
|
49 | 5d805533 | Christos Stavrakakis | # Check volume state
|
50 | 5d805533 | Christos Stavrakakis | if volume.status not in ["AVAILABLE", "CREATING"]: |
51 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest("Cannot attach volume while volume is in" |
52 | 5d805533 | Christos Stavrakakis | " '%s' status." % volume.status)
|
53 | 5d805533 | Christos Stavrakakis | |
54 | 5d805533 | Christos Stavrakakis | # Check that disk templates are the same
|
55 | 5d805533 | Christos Stavrakakis | if volume.disk_template != vm.flavor.disk_template:
|
56 | 5d805533 | Christos Stavrakakis | msg = ("Volume and server must have the same disk template. Volume has"
|
57 | 5d805533 | Christos Stavrakakis | " disk template '%s' while server has '%s'"
|
58 | 5d805533 | Christos Stavrakakis | % (volume.disk_template, vm.flavor.disk_template)) |
59 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest(msg)
|
60 | 5d805533 | Christos Stavrakakis | |
61 | 5d805533 | Christos Stavrakakis | # Check maximum disk per instance hard limit
|
62 | d05e5324 | Christos Stavrakakis | vm_volumes_num = vm.volumes.filter(deleted=False).count()
|
63 | d05e5324 | Christos Stavrakakis | if vm_volumes_num == settings.GANETI_MAX_DISKS_PER_INSTANCE:
|
64 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest("Maximum volumes per server limit reached") |
65 | 5d805533 | Christos Stavrakakis | |
66 | d05e5324 | Christos Stavrakakis | if volume.status == "CREATING": |
67 | d05e5324 | Christos Stavrakakis | action_fields = {"disks": [("add", volume, {})]} |
68 | d05e5324 | Christos Stavrakakis | comm = commands.server_command("ATTACH_VOLUME",
|
69 | d05e5324 | Christos Stavrakakis | action_fields=action_fields) |
70 | d05e5324 | Christos Stavrakakis | return comm(_attach_volume)(vm, volume)
|
71 | d05e5324 | Christos Stavrakakis | |
72 | 5d805533 | Christos Stavrakakis | |
73 | d05e5324 | Christos Stavrakakis | def _attach_volume(vm, volume): |
74 | d05e5324 | Christos Stavrakakis | """Attach a Volume to a VM and update the Volume's status."""
|
75 | d05e5324 | Christos Stavrakakis | jobid = backend.attach_volume(vm, volume) |
76 | 5d805533 | Christos Stavrakakis | log.info("Attached volume '%s' to server '%s'. JobID: '%s'", volume.id,
|
77 | 5d805533 | Christos Stavrakakis | volume.machine_id, jobid) |
78 | 5d805533 | Christos Stavrakakis | volume.backendjobid = jobid |
79 | 5d805533 | Christos Stavrakakis | volume.machine = vm |
80 | d05e5324 | Christos Stavrakakis | if volume.status == "AVAILALBE": |
81 | d05e5324 | Christos Stavrakakis | volume.status = "ATTACHING"
|
82 | d05e5324 | Christos Stavrakakis | else:
|
83 | d05e5324 | Christos Stavrakakis | volume.status = "CREATING"
|
84 | 5d805533 | Christos Stavrakakis | volume.save() |
85 | 5d805533 | Christos Stavrakakis | return jobid
|
86 | 5d805533 | Christos Stavrakakis | |
87 | 5d805533 | Christos Stavrakakis | |
88 | 5d805533 | Christos Stavrakakis | def detach_volume(vm, volume): |
89 | d05e5324 | Christos Stavrakakis | """Detach a Volume from a VM
|
90 | 5d805533 | Christos Stavrakakis |
|
91 | 5d805533 | Christos Stavrakakis | The volume must be in 'IN_USE' status in order to be detached. Also,
|
92 | 5d805533 | Christos Stavrakakis | the root volume of the instance (index=0) can not be detached. This
|
93 | 5d805533 | Christos Stavrakakis | function will send the corresponding job to Ganeti backend and update the
|
94 | 5d805533 | Christos Stavrakakis | status of the volume to 'DETACHING'.
|
95 | 5d805533 | Christos Stavrakakis |
|
96 | 5d805533 | Christos Stavrakakis | """
|
97 | 5d805533 | Christos Stavrakakis | |
98 | 5d805533 | Christos Stavrakakis | _check_attachment(vm, volume) |
99 | d05e5324 | Christos Stavrakakis | if volume.status not in ["IN_USE", "ERROR"]: |
100 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest("Cannot detach volume while volume is in" |
101 | 5d805533 | Christos Stavrakakis | " '%s' status." % volume.status)
|
102 | 5d805533 | Christos Stavrakakis | if volume.index == 0: |
103 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest("Cannot detach the root volume of a server") |
104 | d05e5324 | Christos Stavrakakis | |
105 | d05e5324 | Christos Stavrakakis | action_fields = {"disks": [("remove", volume, {})]} |
106 | d05e5324 | Christos Stavrakakis | comm = commands.server_command("DETACH_VOLUME",
|
107 | d05e5324 | Christos Stavrakakis | action_fields=action_fields) |
108 | d05e5324 | Christos Stavrakakis | return comm(_detach_volume)(vm, volume)
|
109 | d05e5324 | Christos Stavrakakis | |
110 | d05e5324 | Christos Stavrakakis | |
111 | d05e5324 | Christos Stavrakakis | def _detach_volume(vm, volume): |
112 | d05e5324 | Christos Stavrakakis | """Detach a Volume from a VM and update the Volume's status"""
|
113 | 5d805533 | Christos Stavrakakis | jobid = backend.detach_volume(vm, volume) |
114 | 5d805533 | Christos Stavrakakis | log.info("Detached volume '%s' from server '%s'. JobID: '%s'", volume.id,
|
115 | 5d805533 | Christos Stavrakakis | volume.machine_id, jobid) |
116 | 5d805533 | Christos Stavrakakis | volume.backendjobid = jobid |
117 | d05e5324 | Christos Stavrakakis | if volume.delete_on_termination:
|
118 | d05e5324 | Christos Stavrakakis | volume.status = "DELETING"
|
119 | d05e5324 | Christos Stavrakakis | else:
|
120 | d05e5324 | Christos Stavrakakis | volume.status = "DETACHING"
|
121 | 5d805533 | Christos Stavrakakis | volume.save() |
122 | 5d805533 | Christos Stavrakakis | return jobid
|
123 | 5d805533 | Christos Stavrakakis | |
124 | 5d805533 | Christos Stavrakakis | |
125 | 5d805533 | Christos Stavrakakis | def _check_attachment(vm, volume): |
126 | d05e5324 | Christos Stavrakakis | """Check that the Volume is attached to the VM"""
|
127 | 5d805533 | Christos Stavrakakis | if volume.machine_id != vm.id:
|
128 | 5d805533 | Christos Stavrakakis | raise faults.BadRequest("Volume '%s' is not attached to server '%s'" |
129 | 5d805533 | Christos Stavrakakis | % volume.id, vm.id) |