Statistics
| Branch: | Tag: | Revision:

root / snf-cyclades-app / synnefo / logic / backend.py @ 567ffb85

History | View | Annotate | Download (14.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 2b1db26f Giorgos Verigakis
import json
35 2b1db26f Giorgos Verigakis
36 2035039b Giorgos Verigakis
from logging import getLogger
37 2035039b Giorgos Verigakis
38 529178b1 Giorgos Verigakis
from django.conf import settings
39 207b70d5 Giorgos Verigakis
from django.db import transaction
40 207b70d5 Giorgos Verigakis
41 adee02b8 Giorgos Verigakis
from synnefo.db.models import (VirtualMachine, Network, NetworkInterface,
42 adee02b8 Giorgos Verigakis
                                NetworkLink)
43 234f8b07 Vangelis Koukis
from synnefo.logic import utils
44 529178b1 Giorgos Verigakis
from synnefo.util.rapi import GanetiRapiClient
45 529178b1 Giorgos Verigakis
46 529178b1 Giorgos Verigakis
47 9e98ba3c Giorgos Verigakis
log = getLogger('synnefo.logic')
48 9e98ba3c Giorgos Verigakis
49 529178b1 Giorgos Verigakis
rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
50 529178b1 Giorgos Verigakis
51 efff6193 Giorgos Verigakis
_firewall_tags = {
52 efff6193 Giorgos Verigakis
    'ENABLED': settings.GANETI_FIREWALL_ENABLED_TAG,
53 efff6193 Giorgos Verigakis
    'DISABLED': settings.GANETI_FIREWALL_DISABLED_TAG,
54 efff6193 Giorgos Verigakis
    'PROTECTED': settings.GANETI_FIREWALL_PROTECTED_TAG}
55 efff6193 Giorgos Verigakis
56 efff6193 Giorgos Verigakis
_reverse_tags = dict((v.split(':')[3], k) for k, v in _firewall_tags.items())
57 efff6193 Giorgos Verigakis
58 02feca11 Vassilios Karakoidas
59 093f9c53 Vangelis Koukis
@transaction.commit_on_success
60 ad2d6807 Vangelis Koukis
def process_op_status(vm, jobid, opcode, status, logmsg):
61 ad2d6807 Vangelis Koukis
    """Process a job progress notification from the backend
62 02feca11 Vassilios Karakoidas

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

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

107 ad2d6807 Vangelis Koukis
    Process an incoming message from the Ganeti backend,
108 ad2d6807 Vangelis Koukis
    detailing the NIC configuration of a VM instance.
109 ad2d6807 Vangelis Koukis

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