Statistics
| Branch: | Tag: | Revision:

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

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

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

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

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

109 ad2d6807 Vangelis Koukis
    Update the state of the VM in the DB accordingly.
110 ad2d6807 Vangelis Koukis
    """
111 37ca953f Christodoulos Psaltis
112 64938cb0 Giorgos Verigakis
    vm.nics.all().delete()
113 64938cb0 Giorgos Verigakis
    for i, nic in enumerate(nics):
114 64938cb0 Giorgos Verigakis
        if i == 0:
115 ca792e04 Giorgos Verigakis
            net = Network.objects.get(public=True)
116 64938cb0 Giorgos Verigakis
        else:
117 a1dccf43 Vangelis Koukis
            try:
118 a1dccf43 Vangelis Koukis
                link = NetworkLink.objects.get(name=nic['link'])
119 a1dccf43 Vangelis Koukis
            except NetworkLink.DoesNotExist:
120 a1dccf43 Vangelis Koukis
                # Cannot find an instance of NetworkLink for
121 a1dccf43 Vangelis Koukis
                # the link attribute specified in the notification
122 a1dccf43 Vangelis Koukis
                raise NetworkLink.DoesNotExist("Cannot find a NetworkLink "
123 a1dccf43 Vangelis Koukis
                    "object for link='%s'" % nic['link'])
124 64938cb0 Giorgos Verigakis
            net = link.network
125 a1dccf43 Vangelis Koukis
            if net is None:
126 a1dccf43 Vangelis Koukis
                raise Network.DoesNotExist("NetworkLink for link='%s' not "
127 a1dccf43 Vangelis Koukis
                    "associated with an existing Network instance." %
128 a1dccf43 Vangelis Koukis
                    nic['link'])
129 9afeb669 Kostas Papadimitriou
130 658a825a Giorgos Verigakis
        firewall = nic.get('firewall', '')
131 658a825a Giorgos Verigakis
        firewall_profile = _reverse_tags.get(firewall, '')
132 658a825a Giorgos Verigakis
        if not firewall_profile and net.public:
133 658a825a Giorgos Verigakis
            firewall_profile = settings.DEFAULT_FIREWALL_PROFILE
134 9afeb669 Kostas Papadimitriou
135 64938cb0 Giorgos Verigakis
        vm.nics.create(
136 64938cb0 Giorgos Verigakis
            network=net,
137 64938cb0 Giorgos Verigakis
            index=i,
138 64938cb0 Giorgos Verigakis
            mac=nic.get('mac', ''),
139 746c6bf4 Vangelis Koukis
            ipv4=nic.get('ip', ''),
140 41303ed0 Vangelis Koukis
            ipv6=nic.get('ipv6', ''),
141 efff6193 Giorgos Verigakis
            firewall_profile=firewall_profile)
142 9afeb669 Kostas Papadimitriou
143 9afeb669 Kostas Papadimitriou
        # network nics modified, update network object
144 9afeb669 Kostas Papadimitriou
        net.save()
145 9afeb669 Kostas Papadimitriou
146 ad2d6807 Vangelis Koukis
    vm.save()
147 ad2d6807 Vangelis Koukis
148 c25cc9ec Vangelis Koukis
149 9068cd85 Georgios Gousios
@transaction.commit_on_success
150 c25cc9ec Vangelis Koukis
def process_create_progress(vm, rprogress, wprogress):
151 9068cd85 Georgios Gousios
152 c25cc9ec Vangelis Koukis
    # XXX: This only uses the read progress for now.
153 c25cc9ec Vangelis Koukis
    #      Explore whether it would make sense to use the value of wprogress
154 c25cc9ec Vangelis Koukis
    #      somewhere.
155 c25cc9ec Vangelis Koukis
    percentage = int(rprogress)
156 9068cd85 Georgios Gousios
157 af90d919 Vangelis Koukis
    # The percentage may exceed 100%, due to the way
158 af90d919 Vangelis Koukis
    # snf-progress-monitor tracks bytes read by image handling processes
159 af90d919 Vangelis Koukis
    percentage = 100 if percentage > 100 else percentage
160 af90d919 Vangelis Koukis
    if percentage < 0:
161 af90d919 Vangelis Koukis
        raise ValueError("Percentage cannot be negative")
162 9068cd85 Georgios Gousios
163 9068cd85 Georgios Gousios
    last_update = vm.buildpercentage
164 9068cd85 Georgios Gousios
165 7ec9558b Vangelis Koukis
    # FIXME: log a warning here, see #1033
166 7ec9558b Vangelis Koukis
#   if last_update > percentage:
167 7ec9558b Vangelis Koukis
#       raise ValueError("Build percentage should increase monotonically " \
168 7ec9558b Vangelis Koukis
#                        "(old = %d, new = %d)" % (last_update, percentage))
169 9068cd85 Georgios Gousios
170 c25cc9ec Vangelis Koukis
    # This assumes that no message of type 'ganeti-create-progress' is going to
171 c25cc9ec Vangelis Koukis
    # arrive once OP_INSTANCE_CREATE has succeeded for a Ganeti instance and
172 c25cc9ec Vangelis Koukis
    # the instance is STARTED.  What if the two messages are processed by two
173 c25cc9ec Vangelis Koukis
    # separate dispatcher threads, and the 'ganeti-op-status' message for
174 c25cc9ec Vangelis Koukis
    # successful creation gets processed before the 'ganeti-create-progress'
175 c25cc9ec Vangelis Koukis
    # message? [vkoukis]
176 c25cc9ec Vangelis Koukis
    #
177 c25cc9ec Vangelis Koukis
    #if not vm.operstate == 'BUILD':
178 c25cc9ec Vangelis Koukis
    #    raise VirtualMachine.IllegalState("VM is not in building state")
179 9068cd85 Georgios Gousios
180 c25cc9ec Vangelis Koukis
    vm.buildpercentage = percentage
181 9068cd85 Georgios Gousios
    vm.save()
182 ad2d6807 Vangelis Koukis
183 c25cc9ec Vangelis Koukis
184 22e52ede Vassilios Karakoidas
def start_action(vm, action):
185 22e52ede Vassilios Karakoidas
    """Update the state of a VM when a new action is initiated."""
186 22e52ede Vassilios Karakoidas
    if not action in [x[0] for x in VirtualMachine.ACTIONS]:
187 22e52ede Vassilios Karakoidas
        raise VirtualMachine.InvalidActionError(action)
188 22e52ede Vassilios Karakoidas
189 22e52ede Vassilios Karakoidas
    # No actions to deleted and no actions beside destroy to suspended VMs
190 22e52ede Vassilios Karakoidas
    if vm.deleted:
191 5231a38a Giorgos Verigakis
        raise VirtualMachine.DeletedError
192 37ca953f Christodoulos Psaltis
193 30f3b5e5 Vangelis Koukis
    # No actions to machines being built. They may be destroyed, however.
194 30f3b5e5 Vangelis Koukis
    if vm.operstate == 'BUILD' and action != 'DESTROY':
195 5231a38a Giorgos Verigakis
        raise VirtualMachine.BuildingError
196 37ca953f Christodoulos Psaltis
197 dfd19c2d Vassilios Karakoidas
    vm.action = action
198 dfd19c2d Vassilios Karakoidas
    vm.backendjobid = None
199 dfd19c2d Vassilios Karakoidas
    vm.backendopcode = None
200 dfd19c2d Vassilios Karakoidas
    vm.backendjobstatus = None
201 dfd19c2d Vassilios Karakoidas
    vm.backendlogmsg = None
202 22e52ede Vassilios Karakoidas
203 f90c3d8c Vangelis Koukis
    # Update the relevant flags if the VM is being suspended or destroyed.
204 f90c3d8c Vangelis Koukis
    # Do not set the deleted flag here, see ticket #721.
205 f90c3d8c Vangelis Koukis
    #
206 f90c3d8c Vangelis Koukis
    # The deleted flag is set asynchronously, when an OP_INSTANCE_REMOVE
207 f90c3d8c Vangelis Koukis
    # completes successfully. Hence, a server may be visible for some time
208 f90c3d8c Vangelis Koukis
    # after a DELETE /servers/id returns HTTP 204.
209 f90c3d8c Vangelis Koukis
    #
210 22e52ede Vassilios Karakoidas
    if action == "DESTROY":
211 f90c3d8c Vangelis Koukis
        # vm.deleted = True
212 f90c3d8c Vangelis Koukis
        pass
213 22e52ede Vassilios Karakoidas
    elif action == "SUSPEND":
214 22e52ede Vassilios Karakoidas
        vm.suspended = True
215 22e52ede Vassilios Karakoidas
    elif action == "START":
216 22e52ede Vassilios Karakoidas
        vm.suspended = False
217 22e52ede Vassilios Karakoidas
    vm.save()
218 529178b1 Giorgos Verigakis
219 ad2d6807 Vangelis Koukis
220 2b1db26f Giorgos Verigakis
def create_instance(vm, flavor, image, password, personality):
221 3a9b3cde Giorgos Verigakis
    """`image` is a dictionary which should contain the keys:
222 3a9b3cde Giorgos Verigakis
            'backend_id', 'format' and 'metadata'
223 7f691719 Christos Stavrakakis

224 3a9b3cde Giorgos Verigakis
        metadata value should be a dictionary.
225 3a9b3cde Giorgos Verigakis
    """
226 7f691719 Christos Stavrakakis
    nic = {'ip': 'pool', 'network': settings.GANETI_PUBLIC_NETWORK}
227 61868190 Vangelis Koukis
228 61868190 Vangelis Koukis
    if settings.IGNORE_FLAVOR_DISK_SIZES:
229 3a9b3cde Giorgos Verigakis
        if image['backend_id'].find("windows") >= 0:
230 61868190 Vangelis Koukis
            sz = 14000
231 61868190 Vangelis Koukis
        else:
232 61868190 Vangelis Koukis
            sz = 4000
233 cf0e4232 Vangelis Koukis
    else:
234 61868190 Vangelis Koukis
        sz = flavor.disk * 1024
235 37ca953f Christodoulos Psaltis
236 1c382247 Vangelis Koukis
    # Handle arguments to CreateInstance() as a dictionary,
237 1c382247 Vangelis Koukis
    # initialize it based on a deployment-specific value.
238 1c382247 Vangelis Koukis
    # This enables the administrator to override deployment-specific
239 c25cc9ec Vangelis Koukis
    # arguments, such as the disk template to use, name of os provider
240 1c382247 Vangelis Koukis
    # and hypervisor-specific parameters at will (see Synnefo #785, #835).
241 1c382247 Vangelis Koukis
    #
242 1c382247 Vangelis Koukis
    kw = settings.GANETI_CREATEINSTANCE_KWARGS
243 1c382247 Vangelis Koukis
    kw['mode'] = 'create'
244 1c382247 Vangelis Koukis
    kw['name'] = vm.backend_id
245 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
246 805c79ae Giorgos Verigakis
    kw['disk_template'] = flavor.disk_template
247 1c382247 Vangelis Koukis
    kw['disks'] = [{"size": sz}]
248 1c382247 Vangelis Koukis
    kw['nics'] = [nic]
249 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
250 1c382247 Vangelis Koukis
    # kw['os'] = settings.GANETI_OS_PROVIDER
251 1c382247 Vangelis Koukis
    kw['ip_check'] = False
252 1c382247 Vangelis Koukis
    kw['name_check'] = False
253 1c382247 Vangelis Koukis
    # Do not specific a node explicitly, have
254 1c382247 Vangelis Koukis
    # Ganeti use an iallocator instead
255 1c382247 Vangelis Koukis
    #
256 1c382247 Vangelis Koukis
    # kw['pnode']=rapi.GetNodes()[0]
257 1c382247 Vangelis Koukis
    kw['dry_run'] = settings.TEST
258 41303ed0 Vangelis Koukis
259 2b1db26f Giorgos Verigakis
    kw['beparams'] = {
260 2b1db26f Giorgos Verigakis
        'auto_balance': True,
261 2b1db26f Giorgos Verigakis
        'vcpus': flavor.cpu,
262 2b1db26f Giorgos Verigakis
        'memory': flavor.ram}
263 41303ed0 Vangelis Koukis
264 e3b5be49 Giorgos Verigakis
    kw['osparams'] = {
265 3a9b3cde Giorgos Verigakis
        'img_id': image['backend_id'],
266 e3b5be49 Giorgos Verigakis
        'img_passwd': password,
267 3a9b3cde Giorgos Verigakis
        'img_format': image['format']}
268 2b1db26f Giorgos Verigakis
    if personality:
269 e3b5be49 Giorgos Verigakis
        kw['osparams']['img_personality'] = json.dumps(personality)
270 d1eaa651 Christos Stavrakakis
271 3a9b3cde Giorgos Verigakis
    kw['osparams']['img_properties'] = json.dumps(image['metadata'])
272 d1eaa651 Christos Stavrakakis
273 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
274 1c382247 Vangelis Koukis
    # kw['hvparams'] = dict(serial_console=False)
275 1c382247 Vangelis Koukis
276 1c382247 Vangelis Koukis
    return rapi.CreateInstance(**kw)
277 f533f224 Vangelis Koukis
278 529178b1 Giorgos Verigakis
279 529178b1 Giorgos Verigakis
def delete_instance(vm):
280 529178b1 Giorgos Verigakis
    start_action(vm, 'DESTROY')
281 64938cb0 Giorgos Verigakis
    rapi.DeleteInstance(vm.backend_id, dry_run=settings.TEST)
282 d44c236b Giorgos Verigakis
    vm.nics.all().delete()
283 529178b1 Giorgos Verigakis
284 ad2d6807 Vangelis Koukis
285 529178b1 Giorgos Verigakis
def reboot_instance(vm, reboot_type):
286 529178b1 Giorgos Verigakis
    assert reboot_type in ('soft', 'hard')
287 64938cb0 Giorgos Verigakis
    rapi.RebootInstance(vm.backend_id, reboot_type, dry_run=settings.TEST)
288 9e98ba3c Giorgos Verigakis
    log.info('Rebooting instance %s', vm.backend_id)
289 529178b1 Giorgos Verigakis
290 ad2d6807 Vangelis Koukis
291 529178b1 Giorgos Verigakis
def startup_instance(vm):
292 529178b1 Giorgos Verigakis
    start_action(vm, 'START')
293 64938cb0 Giorgos Verigakis
    rapi.StartupInstance(vm.backend_id, dry_run=settings.TEST)
294 529178b1 Giorgos Verigakis
295 ad2d6807 Vangelis Koukis
296 529178b1 Giorgos Verigakis
def shutdown_instance(vm):
297 529178b1 Giorgos Verigakis
    start_action(vm, 'STOP')
298 64938cb0 Giorgos Verigakis
    rapi.ShutdownInstance(vm.backend_id, dry_run=settings.TEST)
299 529178b1 Giorgos Verigakis
300 ad2d6807 Vangelis Koukis
301 529178b1 Giorgos Verigakis
def get_instance_console(vm):
302 71099804 Vangelis Koukis
    # RAPI GetInstanceConsole() returns endpoints to the vnc_bind_address,
303 71099804 Vangelis Koukis
    # which is a cluster-wide setting, either 0.0.0.0 or 127.0.0.1, and pretty
304 71099804 Vangelis Koukis
    # useless (see #783).
305 71099804 Vangelis Koukis
    #
306 71099804 Vangelis Koukis
    # Until this is fixed on the Ganeti side, construct a console info reply
307 71099804 Vangelis Koukis
    # directly.
308 9afeb669 Kostas Papadimitriou
    #
309 71099804 Vangelis Koukis
    # WARNING: This assumes that VNC runs on port network_port on
310 71099804 Vangelis Koukis
    #          the instance's primary node, and is probably
311 71099804 Vangelis Koukis
    #          hypervisor-specific.
312 71099804 Vangelis Koukis
    #
313 71099804 Vangelis Koukis
    console = {}
314 71099804 Vangelis Koukis
    console['kind'] = 'vnc'
315 71099804 Vangelis Koukis
    i = rapi.GetInstance(vm.backend_id)
316 71099804 Vangelis Koukis
    if i['hvparams']['serial_console']:
317 71099804 Vangelis Koukis
        raise Exception("hv parameter serial_console cannot be true")
318 71099804 Vangelis Koukis
    console['host'] = i['pnode']
319 71099804 Vangelis Koukis
    console['port'] = i['network_port']
320 9afeb669 Kostas Papadimitriou
321 71099804 Vangelis Koukis
    return console
322 71099804 Vangelis Koukis
    # return rapi.GetInstanceConsole(vm.backend_id)
323 64938cb0 Giorgos Verigakis
324 c25cc9ec Vangelis Koukis
325 604b2bf8 Georgios Gousios
def request_status_update(vm):
326 604b2bf8 Georgios Gousios
    return rapi.GetInstanceInfo(vm.backend_id)
327 604b2bf8 Georgios Gousios
328 604b2bf8 Georgios Gousios
329 604b2bf8 Georgios Gousios
def get_job_status(jobid):
330 604b2bf8 Georgios Gousios
    return rapi.GetJobStatus(jobid)
331 604b2bf8 Georgios Gousios
332 604b2bf8 Georgios Gousios
333 604b2bf8 Georgios Gousios
def update_status(vm, status):
334 db7a3230 Vangelis Koukis
    utils.update_state(vm, status)
335 f533f224 Vangelis Koukis
336 c25cc9ec Vangelis Koukis
337 64938cb0 Giorgos Verigakis
def create_network_link():
338 64938cb0 Giorgos Verigakis
    try:
339 64938cb0 Giorgos Verigakis
        last = NetworkLink.objects.order_by('-index')[0]
340 64938cb0 Giorgos Verigakis
        index = last.index + 1
341 64938cb0 Giorgos Verigakis
    except IndexError:
342 64938cb0 Giorgos Verigakis
        index = 1
343 37ca953f Christodoulos Psaltis
344 64938cb0 Giorgos Verigakis
    if index <= settings.GANETI_MAX_LINK_NUMBER:
345 64938cb0 Giorgos Verigakis
        name = '%s%d' % (settings.GANETI_LINK_PREFIX, index)
346 f533f224 Vangelis Koukis
        return NetworkLink.objects.create(index=index, name=name,
347 a191bd4d Giorgos Verigakis
                                            available=True)
348 64938cb0 Giorgos Verigakis
    return None     # All link slots are filled
349 64938cb0 Giorgos Verigakis
350 c25cc9ec Vangelis Koukis
351 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
352 6ef51e9f Giorgos Verigakis
def create_network(name, user_id):
353 64938cb0 Giorgos Verigakis
    try:
354 64938cb0 Giorgos Verigakis
        link = NetworkLink.objects.filter(available=True)[0]
355 64938cb0 Giorgos Verigakis
    except IndexError:
356 64938cb0 Giorgos Verigakis
        link = create_network_link()
357 64938cb0 Giorgos Verigakis
        if not link:
358 a3992827 Giorgos Verigakis
            return None
359 37ca953f Christodoulos Psaltis
360 a3992827 Giorgos Verigakis
    network = Network.objects.create(
361 a3992827 Giorgos Verigakis
        name=name,
362 6ef51e9f Giorgos Verigakis
        userid=user_id,
363 a3992827 Giorgos Verigakis
        state='ACTIVE',
364 a3992827 Giorgos Verigakis
        link=link)
365 37ca953f Christodoulos Psaltis
366 a3992827 Giorgos Verigakis
    link.network = network
367 64938cb0 Giorgos Verigakis
    link.available = False
368 64938cb0 Giorgos Verigakis
    link.save()
369 37ca953f Christodoulos Psaltis
370 a3992827 Giorgos Verigakis
    return network
371 64938cb0 Giorgos Verigakis
372 c25cc9ec Vangelis Koukis
373 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
374 64938cb0 Giorgos Verigakis
def delete_network(net):
375 64938cb0 Giorgos Verigakis
    link = net.link
376 06a16b24 Giorgos Verigakis
    if link.name != settings.GANETI_NULL_LINK:
377 06a16b24 Giorgos Verigakis
        link.available = True
378 06a16b24 Giorgos Verigakis
        link.network = None
379 06a16b24 Giorgos Verigakis
        link.save()
380 37ca953f Christodoulos Psaltis
381 64938cb0 Giorgos Verigakis
    for vm in net.machines.all():
382 64938cb0 Giorgos Verigakis
        disconnect_from_network(vm, net)
383 64938cb0 Giorgos Verigakis
        vm.save()
384 64938cb0 Giorgos Verigakis
    net.state = 'DELETED'
385 64938cb0 Giorgos Verigakis
    net.save()
386 64938cb0 Giorgos Verigakis
387 c25cc9ec Vangelis Koukis
388 64938cb0 Giorgos Verigakis
def connect_to_network(vm, net):
389 64938cb0 Giorgos Verigakis
    nic = {'mode': 'bridged', 'link': net.link.name}
390 d1eaa651 Christos Stavrakakis
    rapi.ModifyInstance(vm.backend_id, nics=[('add', nic)],
391 d1eaa651 Christos Stavrakakis
                        dry_run=settings.TEST)
392 64938cb0 Giorgos Verigakis
393 c25cc9ec Vangelis Koukis
394 64938cb0 Giorgos Verigakis
def disconnect_from_network(vm, net):
395 ca792e04 Giorgos Verigakis
    nics = vm.nics.filter(network__public=False).order_by('index')
396 d1eaa651 Christos Stavrakakis
    ops = [('remove', nic.index, {}) for nic in nics if nic.network == net]
397 d1eaa651 Christos Stavrakakis
    if not ops: # Vm not connected to network
398 d1eaa651 Christos Stavrakakis
        return
399 d1eaa651 Christos Stavrakakis
    rapi.ModifyInstance(vm.backend_id, nics=ops[::-1], dry_run=settings.TEST)
400 91826390 Giorgos Verigakis
401 c25cc9ec Vangelis Koukis
402 91826390 Giorgos Verigakis
def set_firewall_profile(vm, profile):
403 26563957 Giorgos Verigakis
    try:
404 26563957 Giorgos Verigakis
        tag = _firewall_tags[profile]
405 26563957 Giorgos Verigakis
    except KeyError:
406 91826390 Giorgos Verigakis
        raise ValueError("Unsopported Firewall Profile: %s" % profile)
407 37ca953f Christodoulos Psaltis
408 26563957 Giorgos Verigakis
    # Delete all firewall tags
409 efff6193 Giorgos Verigakis
    for t in _firewall_tags.values():
410 efff6193 Giorgos Verigakis
        rapi.DeleteInstanceTags(vm.backend_id, [t], dry_run=settings.TEST)
411 37ca953f Christodoulos Psaltis
412 26563957 Giorgos Verigakis
    rapi.AddInstanceTags(vm.backend_id, [tag], dry_run=settings.TEST)
413 9afeb669 Kostas Papadimitriou
414 2da5f785 Giorgos Verigakis
    # XXX NOP ModifyInstance call to force process_net_status to run
415 2da5f785 Giorgos Verigakis
    # on the dispatcher
416 5eedb0e4 Vangelis Koukis
    rapi.ModifyInstance(vm.backend_id,
417 5eedb0e4 Vangelis Koukis
                        os_name=settings.GANETI_CREATEINSTANCE_KWARGS['os'])
418 5eedb0e4 Vangelis Koukis
419 41303ed0 Vangelis Koukis
420 17852fe9 Giorgos Verigakis
def get_ganeti_instances():
421 17852fe9 Giorgos Verigakis
    return rapi.GetInstances()
422 17852fe9 Giorgos Verigakis
423 41303ed0 Vangelis Koukis
424 17852fe9 Giorgos Verigakis
def get_ganeti_nodes():
425 17852fe9 Giorgos Verigakis
    return rapi.GetNodes()
426 17852fe9 Giorgos Verigakis
427 41303ed0 Vangelis Koukis
428 17852fe9 Giorgos Verigakis
def get_ganeti_jobs():
429 17852fe9 Giorgos Verigakis
    return rapi.GetJobs()