Statistics
| Branch: | Tag: | Revision:

root / logic / backend.py @ c25cc9ec

History | View | Annotate | Download (13.1 kB)

1 adee02b8 Giorgos Verigakis
# Copyright 2011 GRNET S.A. All rights reserved.
2 37ca953f Christodoulos Psaltis
#
3 adee02b8 Giorgos Verigakis
# Redistribution and use in source and binary forms, with or
4 adee02b8 Giorgos Verigakis
# without modification, are permitted provided that the following
5 adee02b8 Giorgos Verigakis
# conditions are met:
6 37ca953f Christodoulos Psaltis
#
7 adee02b8 Giorgos Verigakis
#   1. Redistributions of source code must retain the above
8 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
9 adee02b8 Giorgos Verigakis
#      disclaimer.
10 37ca953f Christodoulos Psaltis
#
11 adee02b8 Giorgos Verigakis
#   2. Redistributions in binary form must reproduce the above
12 adee02b8 Giorgos Verigakis
#      copyright notice, this list of conditions and the following
13 adee02b8 Giorgos Verigakis
#      disclaimer in the documentation and/or other materials
14 adee02b8 Giorgos Verigakis
#      provided with the distribution.
15 37ca953f Christodoulos Psaltis
#
16 adee02b8 Giorgos Verigakis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 adee02b8 Giorgos Verigakis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 adee02b8 Giorgos Verigakis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 adee02b8 Giorgos Verigakis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 adee02b8 Giorgos Verigakis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 adee02b8 Giorgos Verigakis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 adee02b8 Giorgos Verigakis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 adee02b8 Giorgos Verigakis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 adee02b8 Giorgos Verigakis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 adee02b8 Giorgos Verigakis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 adee02b8 Giorgos Verigakis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 adee02b8 Giorgos Verigakis
# POSSIBILITY OF SUCH DAMAGE.
28 37ca953f Christodoulos Psaltis
#
29 adee02b8 Giorgos Verigakis
# The views and conclusions contained in the software and
30 adee02b8 Giorgos Verigakis
# documentation are those of the authors and should not be
31 adee02b8 Giorgos Verigakis
# interpreted as representing official policies, either expressed
32 adee02b8 Giorgos Verigakis
# or implied, of GRNET S.A.
33 02feca11 Vassilios Karakoidas
34 529178b1 Giorgos Verigakis
from django.conf import settings
35 207b70d5 Giorgos Verigakis
from django.db import transaction
36 207b70d5 Giorgos Verigakis
37 adee02b8 Giorgos Verigakis
from synnefo.db.models import (VirtualMachine, Network, NetworkInterface,
38 adee02b8 Giorgos Verigakis
                                NetworkLink)
39 234f8b07 Vangelis Koukis
from synnefo.logic import utils
40 529178b1 Giorgos Verigakis
from synnefo.util.rapi import GanetiRapiClient
41 529178b1 Giorgos Verigakis
42 529178b1 Giorgos Verigakis
43 529178b1 Giorgos Verigakis
rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
44 529178b1 Giorgos Verigakis
45 efff6193 Giorgos Verigakis
_firewall_tags = {
46 efff6193 Giorgos Verigakis
    'ENABLED': settings.GANETI_FIREWALL_ENABLED_TAG,
47 efff6193 Giorgos Verigakis
    'DISABLED': settings.GANETI_FIREWALL_DISABLED_TAG,
48 efff6193 Giorgos Verigakis
    'PROTECTED': settings.GANETI_FIREWALL_PROTECTED_TAG}
49 efff6193 Giorgos Verigakis
50 efff6193 Giorgos Verigakis
_reverse_tags = dict((v.split(':')[3], k) for k, v in _firewall_tags.items())
51 efff6193 Giorgos Verigakis
52 02feca11 Vassilios Karakoidas
53 093f9c53 Vangelis Koukis
@transaction.commit_on_success
54 ad2d6807 Vangelis Koukis
def process_op_status(vm, jobid, opcode, status, logmsg):
55 ad2d6807 Vangelis Koukis
    """Process a job progress notification from the backend
56 02feca11 Vassilios Karakoidas

57 02feca11 Vassilios Karakoidas
    Process an incoming message from the backend (currently Ganeti).
58 02feca11 Vassilios Karakoidas
    Job notifications with a terminating status (sucess, error, or canceled),
59 02feca11 Vassilios Karakoidas
    also update the operating state of the VM.
60 02feca11 Vassilios Karakoidas

61 02feca11 Vassilios Karakoidas
    """
62 02feca11 Vassilios Karakoidas
    if (opcode not in [x[0] for x in VirtualMachine.BACKEND_OPCODES] or
63 02feca11 Vassilios Karakoidas
       status not in [x[0] for x in VirtualMachine.BACKEND_STATUSES]):
64 02feca11 Vassilios Karakoidas
        raise VirtualMachine.InvalidBackendMsgError(opcode, status)
65 02feca11 Vassilios Karakoidas
66 dfd19c2d Vassilios Karakoidas
    vm.backendjobid = jobid
67 dfd19c2d Vassilios Karakoidas
    vm.backendjobstatus = status
68 dfd19c2d Vassilios Karakoidas
    vm.backendopcode = opcode
69 dfd19c2d Vassilios Karakoidas
    vm.backendlogmsg = logmsg
70 02feca11 Vassilios Karakoidas
71 02feca11 Vassilios Karakoidas
    # Notifications of success change the operating state
72 ac63eb4f Vangelis Koukis
    if status == 'success' and VirtualMachine.OPER_STATE_FROM_OPCODE[opcode] is not None:
73 234f8b07 Vangelis Koukis
        utils.update_state(vm, VirtualMachine.OPER_STATE_FROM_OPCODE[opcode])
74 685b219e Vangelis Koukis
        # Set the deleted flag explicitly, to cater for admin-initiated removals
75 685b219e Vangelis Koukis
        if opcode == 'OP_INSTANCE_REMOVE':
76 685b219e Vangelis Koukis
            vm.deleted = True
77 685b219e Vangelis Koukis
78 685b219e Vangelis Koukis
    # Special case: if OP_INSTANCE_CREATE fails --> ERROR
79 02feca11 Vassilios Karakoidas
    if status in ('canceled', 'error') and opcode == 'OP_INSTANCE_CREATE':
80 234f8b07 Vangelis Koukis
        utils.update_state(vm, 'ERROR')
81 093f9c53 Vangelis Koukis
82 093f9c53 Vangelis Koukis
    # Special case: OP_INSTANCE_REMOVE fails for machines in ERROR,
83 093f9c53 Vangelis Koukis
    # when no instance exists at the Ganeti backend.
84 093f9c53 Vangelis Koukis
    # See ticket #799 for all the details.
85 093f9c53 Vangelis Koukis
    #
86 093f9c53 Vangelis Koukis
    if (status == 'error' and opcode == 'OP_INSTANCE_REMOVE' and
87 093f9c53 Vangelis Koukis
        vm.operstate == 'ERROR'):
88 093f9c53 Vangelis Koukis
        vm.deleted = True
89 093f9c53 Vangelis Koukis
90 02feca11 Vassilios Karakoidas
    # Any other notification of failure leaves the operating state unchanged
91 02feca11 Vassilios Karakoidas
92 02feca11 Vassilios Karakoidas
    vm.save()
93 22e52ede Vassilios Karakoidas
94 ad2d6807 Vangelis Koukis
95 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
96 ad2d6807 Vangelis Koukis
def process_net_status(vm, nics):
97 ad2d6807 Vangelis Koukis
    """Process a net status notification from the backend
98 ad2d6807 Vangelis Koukis

99 ad2d6807 Vangelis Koukis
    Process an incoming message from the Ganeti backend,
100 ad2d6807 Vangelis Koukis
    detailing the NIC configuration of a VM instance.
101 ad2d6807 Vangelis Koukis

102 ad2d6807 Vangelis Koukis
    Update the state of the VM in the DB accordingly.
103 ad2d6807 Vangelis Koukis
    """
104 37ca953f Christodoulos Psaltis
105 64938cb0 Giorgos Verigakis
    vm.nics.all().delete()
106 64938cb0 Giorgos Verigakis
    for i, nic in enumerate(nics):
107 64938cb0 Giorgos Verigakis
        if i == 0:
108 ca792e04 Giorgos Verigakis
            net = Network.objects.get(public=True)
109 64938cb0 Giorgos Verigakis
        else:
110 a1dccf43 Vangelis Koukis
            try:
111 a1dccf43 Vangelis Koukis
                link = NetworkLink.objects.get(name=nic['link'])
112 a1dccf43 Vangelis Koukis
            except NetworkLink.DoesNotExist:
113 a1dccf43 Vangelis Koukis
                # Cannot find an instance of NetworkLink for
114 a1dccf43 Vangelis Koukis
                # the link attribute specified in the notification
115 a1dccf43 Vangelis Koukis
                raise NetworkLink.DoesNotExist("Cannot find a NetworkLink "
116 a1dccf43 Vangelis Koukis
                    "object for link='%s'" % nic['link'])
117 64938cb0 Giorgos Verigakis
            net = link.network
118 a1dccf43 Vangelis Koukis
            if net is None:
119 a1dccf43 Vangelis Koukis
                raise Network.DoesNotExist("NetworkLink for link='%s' not "
120 a1dccf43 Vangelis Koukis
                    "associated with an existing Network instance." %
121 a1dccf43 Vangelis Koukis
                    nic['link'])
122 d1387ed7 Christodoulos Psaltis
    
123 658a825a Giorgos Verigakis
        firewall = nic.get('firewall', '')
124 658a825a Giorgos Verigakis
        firewall_profile = _reverse_tags.get(firewall, '')
125 658a825a Giorgos Verigakis
        if not firewall_profile and net.public:
126 658a825a Giorgos Verigakis
            firewall_profile = settings.DEFAULT_FIREWALL_PROFILE
127 d1387ed7 Christodoulos Psaltis
    
128 64938cb0 Giorgos Verigakis
        vm.nics.create(
129 64938cb0 Giorgos Verigakis
            network=net,
130 64938cb0 Giorgos Verigakis
            index=i,
131 64938cb0 Giorgos Verigakis
            mac=nic.get('mac', ''),
132 746c6bf4 Vangelis Koukis
            ipv4=nic.get('ip', ''),
133 efff6193 Giorgos Verigakis
            ipv6=nic.get('ipv6',''),
134 efff6193 Giorgos Verigakis
            firewall_profile=firewall_profile)
135 ad2d6807 Vangelis Koukis
    vm.save()
136 ad2d6807 Vangelis Koukis
137 c25cc9ec Vangelis Koukis
138 9068cd85 Georgios Gousios
@transaction.commit_on_success
139 c25cc9ec Vangelis Koukis
def process_create_progress(vm, rprogress, wprogress):
140 9068cd85 Georgios Gousios
141 c25cc9ec Vangelis Koukis
    # XXX: This only uses the read progress for now.
142 c25cc9ec Vangelis Koukis
    #      Explore whether it would make sense to use the value of wprogress
143 c25cc9ec Vangelis Koukis
    #      somewhere.
144 c25cc9ec Vangelis Koukis
    percentage = int(rprogress)
145 9068cd85 Georgios Gousios
146 c25cc9ec Vangelis Koukis
    if percentage < 0 or percentage > 100:
147 c25cc9ec Vangelis Koukis
        raise ValueError("Percentage not in range [0, 100]")
148 9068cd85 Georgios Gousios
149 9068cd85 Georgios Gousios
    last_update = vm.buildpercentage
150 9068cd85 Georgios Gousios
151 c25cc9ec Vangelis Koukis
    if last_update > percentage:
152 c25cc9ec Vangelis Koukis
        raise ValueError("Build percentage should increase monotonically " \
153 c25cc9ec Vangelis Koukis
                        "(old = %d, new = %d)" % (last_update, percentage))
154 9068cd85 Georgios Gousios
155 c25cc9ec Vangelis Koukis
    # This assumes that no message of type 'ganeti-create-progress' is going to
156 c25cc9ec Vangelis Koukis
    # arrive once OP_INSTANCE_CREATE has succeeded for a Ganeti instance and
157 c25cc9ec Vangelis Koukis
    # the instance is STARTED.  What if the two messages are processed by two
158 c25cc9ec Vangelis Koukis
    # separate dispatcher threads, and the 'ganeti-op-status' message for
159 c25cc9ec Vangelis Koukis
    # successful creation gets processed before the 'ganeti-create-progress'
160 c25cc9ec Vangelis Koukis
    # message? [vkoukis]
161 c25cc9ec Vangelis Koukis
    #
162 c25cc9ec Vangelis Koukis
    #if not vm.operstate == 'BUILD':
163 c25cc9ec Vangelis Koukis
    #    raise VirtualMachine.IllegalState("VM is not in building state")
164 9068cd85 Georgios Gousios
165 c25cc9ec Vangelis Koukis
    vm.buildpercentage = percentage
166 9068cd85 Georgios Gousios
    vm.save()
167 ad2d6807 Vangelis Koukis
168 c25cc9ec Vangelis Koukis
169 22e52ede Vassilios Karakoidas
def start_action(vm, action):
170 22e52ede Vassilios Karakoidas
    """Update the state of a VM when a new action is initiated."""
171 22e52ede Vassilios Karakoidas
    if not action in [x[0] for x in VirtualMachine.ACTIONS]:
172 22e52ede Vassilios Karakoidas
        raise VirtualMachine.InvalidActionError(action)
173 22e52ede Vassilios Karakoidas
174 22e52ede Vassilios Karakoidas
    # No actions to deleted and no actions beside destroy to suspended VMs
175 22e52ede Vassilios Karakoidas
    if vm.deleted:
176 5231a38a Giorgos Verigakis
        raise VirtualMachine.DeletedError
177 37ca953f Christodoulos Psaltis
178 30f3b5e5 Vangelis Koukis
    # No actions to machines being built. They may be destroyed, however.
179 30f3b5e5 Vangelis Koukis
    if vm.operstate == 'BUILD' and action != 'DESTROY':
180 5231a38a Giorgos Verigakis
        raise VirtualMachine.BuildingError
181 37ca953f Christodoulos Psaltis
182 dfd19c2d Vassilios Karakoidas
    vm.action = action
183 dfd19c2d Vassilios Karakoidas
    vm.backendjobid = None
184 dfd19c2d Vassilios Karakoidas
    vm.backendopcode = None
185 dfd19c2d Vassilios Karakoidas
    vm.backendjobstatus = None
186 dfd19c2d Vassilios Karakoidas
    vm.backendlogmsg = None
187 22e52ede Vassilios Karakoidas
188 f90c3d8c Vangelis Koukis
    # Update the relevant flags if the VM is being suspended or destroyed.
189 f90c3d8c Vangelis Koukis
    # Do not set the deleted flag here, see ticket #721.
190 f90c3d8c Vangelis Koukis
    #
191 f90c3d8c Vangelis Koukis
    # The deleted flag is set asynchronously, when an OP_INSTANCE_REMOVE
192 f90c3d8c Vangelis Koukis
    # completes successfully. Hence, a server may be visible for some time
193 f90c3d8c Vangelis Koukis
    # after a DELETE /servers/id returns HTTP 204.
194 f90c3d8c Vangelis Koukis
    #
195 22e52ede Vassilios Karakoidas
    if action == "DESTROY":
196 f90c3d8c Vangelis Koukis
        # vm.deleted = True
197 f90c3d8c Vangelis Koukis
        pass
198 22e52ede Vassilios Karakoidas
    elif action == "SUSPEND":
199 22e52ede Vassilios Karakoidas
        vm.suspended = True
200 22e52ede Vassilios Karakoidas
    elif action == "START":
201 22e52ede Vassilios Karakoidas
        vm.suspended = False
202 22e52ede Vassilios Karakoidas
    vm.save()
203 529178b1 Giorgos Verigakis
204 ad2d6807 Vangelis Koukis
205 1ef58e5b Constantinos Venetsanopoulos
def create_instance(vm, flavor, image, password):
206 37ca953f Christodoulos Psaltis
207 64938cb0 Giorgos Verigakis
    nic = {'ip': 'pool', 'mode': 'routed', 'link': settings.GANETI_PUBLIC_LINK}
208 61868190 Vangelis Koukis
209 61868190 Vangelis Koukis
    if settings.IGNORE_FLAVOR_DISK_SIZES:
210 61868190 Vangelis Koukis
        if image.backend_id.find("windows") >= 0:
211 61868190 Vangelis Koukis
            sz = 14000
212 61868190 Vangelis Koukis
        else:
213 61868190 Vangelis Koukis
            sz = 4000
214 cf0e4232 Vangelis Koukis
    else:
215 61868190 Vangelis Koukis
        sz = flavor.disk * 1024
216 37ca953f Christodoulos Psaltis
217 1c382247 Vangelis Koukis
    # Handle arguments to CreateInstance() as a dictionary,
218 1c382247 Vangelis Koukis
    # initialize it based on a deployment-specific value.
219 1c382247 Vangelis Koukis
    # This enables the administrator to override deployment-specific
220 c25cc9ec Vangelis Koukis
    # arguments, such as the disk template to use, name of os provider
221 1c382247 Vangelis Koukis
    # and hypervisor-specific parameters at will (see Synnefo #785, #835).
222 1c382247 Vangelis Koukis
    #
223 1c382247 Vangelis Koukis
    kw = settings.GANETI_CREATEINSTANCE_KWARGS
224 1c382247 Vangelis Koukis
    kw['mode'] = 'create'
225 1c382247 Vangelis Koukis
    kw['name'] = vm.backend_id
226 1c382247 Vangelis Koukis
    # Defined in settings.GANETI_CREATE_INSTANCE_KWARGS
227 1c382247 Vangelis Koukis
    # kw['disk_template'] = settings.GANETI_DISK_TEMPLATE
228 1c382247 Vangelis Koukis
    kw['disks'] = [{"size": sz}]
229 1c382247 Vangelis Koukis
    kw['nics'] = [nic]
230 1c382247 Vangelis Koukis
    # Defined in settings.GANETI_CREATE_INSTANCE_KWARGS
231 1c382247 Vangelis Koukis
    # kw['os'] = settings.GANETI_OS_PROVIDER
232 1c382247 Vangelis Koukis
    kw['ip_check'] = False
233 1c382247 Vangelis Koukis
    kw['name_check'] = False
234 1c382247 Vangelis Koukis
    # Do not specific a node explicitly, have
235 1c382247 Vangelis Koukis
    # Ganeti use an iallocator instead
236 1c382247 Vangelis Koukis
    #
237 1c382247 Vangelis Koukis
    # kw['pnode']=rapi.GetNodes()[0]
238 1c382247 Vangelis Koukis
    kw['dry_run'] = settings.TEST
239 1c382247 Vangelis Koukis
    kw['beparams'] = dict(auto_balance=True, vcpus=flavor.cpu,
240 1c382247 Vangelis Koukis
                          memory=flavor.ram)
241 1c382247 Vangelis Koukis
    kw['osparams'] = dict(img_id=image.backend_id, img_passwd=password,
242 1c382247 Vangelis Koukis
                         img_format=image.format)
243 1c382247 Vangelis Koukis
    # Defined in settings.GANETI_CREATE_INSTANCE_KWARGS
244 1c382247 Vangelis Koukis
    # kw['hvparams'] = dict(serial_console=False)
245 1c382247 Vangelis Koukis
246 1c382247 Vangelis Koukis
    return rapi.CreateInstance(**kw)
247 f533f224 Vangelis Koukis
248 529178b1 Giorgos Verigakis
249 529178b1 Giorgos Verigakis
def delete_instance(vm):
250 529178b1 Giorgos Verigakis
    start_action(vm, 'DESTROY')
251 64938cb0 Giorgos Verigakis
    rapi.DeleteInstance(vm.backend_id, dry_run=settings.TEST)
252 d44c236b Giorgos Verigakis
    vm.nics.all().delete()
253 529178b1 Giorgos Verigakis
254 ad2d6807 Vangelis Koukis
255 529178b1 Giorgos Verigakis
def reboot_instance(vm, reboot_type):
256 529178b1 Giorgos Verigakis
    assert reboot_type in ('soft', 'hard')
257 64938cb0 Giorgos Verigakis
    rapi.RebootInstance(vm.backend_id, reboot_type, dry_run=settings.TEST)
258 529178b1 Giorgos Verigakis
259 ad2d6807 Vangelis Koukis
260 529178b1 Giorgos Verigakis
def startup_instance(vm):
261 529178b1 Giorgos Verigakis
    start_action(vm, 'START')
262 64938cb0 Giorgos Verigakis
    rapi.StartupInstance(vm.backend_id, dry_run=settings.TEST)
263 529178b1 Giorgos Verigakis
264 ad2d6807 Vangelis Koukis
265 529178b1 Giorgos Verigakis
def shutdown_instance(vm):
266 529178b1 Giorgos Verigakis
    start_action(vm, 'STOP')
267 64938cb0 Giorgos Verigakis
    rapi.ShutdownInstance(vm.backend_id, dry_run=settings.TEST)
268 529178b1 Giorgos Verigakis
269 ad2d6807 Vangelis Koukis
270 529178b1 Giorgos Verigakis
def get_instance_console(vm):
271 71099804 Vangelis Koukis
    # RAPI GetInstanceConsole() returns endpoints to the vnc_bind_address,
272 71099804 Vangelis Koukis
    # which is a cluster-wide setting, either 0.0.0.0 or 127.0.0.1, and pretty
273 71099804 Vangelis Koukis
    # useless (see #783).
274 71099804 Vangelis Koukis
    #
275 71099804 Vangelis Koukis
    # Until this is fixed on the Ganeti side, construct a console info reply
276 71099804 Vangelis Koukis
    # directly.
277 71099804 Vangelis Koukis
    # 
278 71099804 Vangelis Koukis
    # WARNING: This assumes that VNC runs on port network_port on
279 71099804 Vangelis Koukis
    #          the instance's primary node, and is probably
280 71099804 Vangelis Koukis
    #          hypervisor-specific.
281 71099804 Vangelis Koukis
    #
282 71099804 Vangelis Koukis
    console = {}
283 71099804 Vangelis Koukis
    console['kind'] = 'vnc'
284 71099804 Vangelis Koukis
    i = rapi.GetInstance(vm.backend_id)
285 71099804 Vangelis Koukis
    if i['hvparams']['serial_console']:
286 71099804 Vangelis Koukis
        raise Exception("hv parameter serial_console cannot be true")
287 71099804 Vangelis Koukis
    console['host'] = i['pnode']
288 71099804 Vangelis Koukis
    console['port'] = i['network_port']
289 71099804 Vangelis Koukis
    
290 71099804 Vangelis Koukis
    return console
291 71099804 Vangelis Koukis
    # return rapi.GetInstanceConsole(vm.backend_id)
292 64938cb0 Giorgos Verigakis
293 c25cc9ec Vangelis Koukis
294 604b2bf8 Georgios Gousios
def request_status_update(vm):
295 604b2bf8 Georgios Gousios
    return rapi.GetInstanceInfo(vm.backend_id)
296 604b2bf8 Georgios Gousios
297 604b2bf8 Georgios Gousios
298 604b2bf8 Georgios Gousios
def get_job_status(jobid):
299 604b2bf8 Georgios Gousios
    return rapi.GetJobStatus(jobid)
300 604b2bf8 Georgios Gousios
301 604b2bf8 Georgios Gousios
302 604b2bf8 Georgios Gousios
def update_status(vm, status):
303 db7a3230 Vangelis Koukis
    utils.update_state(vm, status)
304 f533f224 Vangelis Koukis
305 c25cc9ec Vangelis Koukis
306 64938cb0 Giorgos Verigakis
def create_network_link():
307 64938cb0 Giorgos Verigakis
    try:
308 64938cb0 Giorgos Verigakis
        last = NetworkLink.objects.order_by('-index')[0]
309 64938cb0 Giorgos Verigakis
        index = last.index + 1
310 64938cb0 Giorgos Verigakis
    except IndexError:
311 64938cb0 Giorgos Verigakis
        index = 1
312 37ca953f Christodoulos Psaltis
313 64938cb0 Giorgos Verigakis
    if index <= settings.GANETI_MAX_LINK_NUMBER:
314 64938cb0 Giorgos Verigakis
        name = '%s%d' % (settings.GANETI_LINK_PREFIX, index)
315 f533f224 Vangelis Koukis
        return NetworkLink.objects.create(index=index, name=name,
316 a191bd4d Giorgos Verigakis
                                            available=True)
317 64938cb0 Giorgos Verigakis
    return None     # All link slots are filled
318 64938cb0 Giorgos Verigakis
319 c25cc9ec Vangelis Koukis
320 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
321 a3992827 Giorgos Verigakis
def create_network(name, owner):
322 64938cb0 Giorgos Verigakis
    try:
323 64938cb0 Giorgos Verigakis
        link = NetworkLink.objects.filter(available=True)[0]
324 64938cb0 Giorgos Verigakis
    except IndexError:
325 64938cb0 Giorgos Verigakis
        link = create_network_link()
326 64938cb0 Giorgos Verigakis
        if not link:
327 a3992827 Giorgos Verigakis
            return None
328 37ca953f Christodoulos Psaltis
329 a3992827 Giorgos Verigakis
    network = Network.objects.create(
330 a3992827 Giorgos Verigakis
        name=name,
331 a3992827 Giorgos Verigakis
        owner=owner,
332 a3992827 Giorgos Verigakis
        state='ACTIVE',
333 a3992827 Giorgos Verigakis
        link=link)
334 37ca953f Christodoulos Psaltis
335 a3992827 Giorgos Verigakis
    link.network = network
336 64938cb0 Giorgos Verigakis
    link.available = False
337 64938cb0 Giorgos Verigakis
    link.save()
338 37ca953f Christodoulos Psaltis
339 a3992827 Giorgos Verigakis
    return network
340 64938cb0 Giorgos Verigakis
341 c25cc9ec Vangelis Koukis
342 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
343 64938cb0 Giorgos Verigakis
def delete_network(net):
344 64938cb0 Giorgos Verigakis
    link = net.link
345 06a16b24 Giorgos Verigakis
    if link.name != settings.GANETI_NULL_LINK:
346 06a16b24 Giorgos Verigakis
        link.available = True
347 06a16b24 Giorgos Verigakis
        link.network = None
348 06a16b24 Giorgos Verigakis
        link.save()
349 37ca953f Christodoulos Psaltis
350 64938cb0 Giorgos Verigakis
    for vm in net.machines.all():
351 64938cb0 Giorgos Verigakis
        disconnect_from_network(vm, net)
352 64938cb0 Giorgos Verigakis
        vm.save()
353 64938cb0 Giorgos Verigakis
    net.state = 'DELETED'
354 64938cb0 Giorgos Verigakis
    net.save()
355 64938cb0 Giorgos Verigakis
356 c25cc9ec Vangelis Koukis
357 64938cb0 Giorgos Verigakis
def connect_to_network(vm, net):
358 64938cb0 Giorgos Verigakis
    nic = {'mode': 'bridged', 'link': net.link.name}
359 ca792e04 Giorgos Verigakis
    rapi.ModifyInstance(vm.backend_id,
360 ca792e04 Giorgos Verigakis
        nics=[('add', nic)],
361 ca792e04 Giorgos Verigakis
        dry_run=settings.TEST)
362 64938cb0 Giorgos Verigakis
363 c25cc9ec Vangelis Koukis
364 64938cb0 Giorgos Verigakis
def disconnect_from_network(vm, net):
365 ca792e04 Giorgos Verigakis
    nics = vm.nics.filter(network__public=False).order_by('index')
366 ca792e04 Giorgos Verigakis
    new_nics = [nic for nic in nics if nic.network != net]
367 ca792e04 Giorgos Verigakis
    if new_nics == nics:
368 ca792e04 Giorgos Verigakis
        return      # Nothing to remove
369 ca792e04 Giorgos Verigakis
    ops = [('remove', {})]
370 ca792e04 Giorgos Verigakis
    for i, nic in enumerate(new_nics):
371 ca792e04 Giorgos Verigakis
        ops.append((i + 1, {
372 64938cb0 Giorgos Verigakis
            'mode': 'bridged',
373 ca792e04 Giorgos Verigakis
            'link': nic.network.link.name}))
374 ca792e04 Giorgos Verigakis
    rapi.ModifyInstance(vm.backend_id, nics=ops, dry_run=settings.TEST)
375 91826390 Giorgos Verigakis
376 c25cc9ec Vangelis Koukis
377 91826390 Giorgos Verigakis
def set_firewall_profile(vm, profile):
378 26563957 Giorgos Verigakis
    try:
379 26563957 Giorgos Verigakis
        tag = _firewall_tags[profile]
380 26563957 Giorgos Verigakis
    except KeyError:
381 91826390 Giorgos Verigakis
        raise ValueError("Unsopported Firewall Profile: %s" % profile)
382 37ca953f Christodoulos Psaltis
383 26563957 Giorgos Verigakis
    # Delete all firewall tags
384 efff6193 Giorgos Verigakis
    for t in _firewall_tags.values():
385 efff6193 Giorgos Verigakis
        rapi.DeleteInstanceTags(vm.backend_id, [t], dry_run=settings.TEST)
386 37ca953f Christodoulos Psaltis
387 26563957 Giorgos Verigakis
    rapi.AddInstanceTags(vm.backend_id, [tag], dry_run=settings.TEST)
388 2da5f785 Giorgos Verigakis
    
389 2da5f785 Giorgos Verigakis
    # XXX NOP ModifyInstance call to force process_net_status to run
390 2da5f785 Giorgos Verigakis
    # on the dispatcher
391 5eedb0e4 Vangelis Koukis
    rapi.ModifyInstance(vm.backend_id,
392 5eedb0e4 Vangelis Koukis
                        os_name=settings.GANETI_CREATEINSTANCE_KWARGS['os'])