Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (14 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 9c21a2e2 Christos Stavrakakis
            vm.nics.all().delete()
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 9c21a2e2 Christos Stavrakakis
        vm.nics.all().delete()
98 093f9c53 Vangelis Koukis
99 02feca11 Vassilios Karakoidas
    # Any other notification of failure leaves the operating state unchanged
100 02feca11 Vassilios Karakoidas
101 02feca11 Vassilios Karakoidas
    vm.save()
102 22e52ede Vassilios Karakoidas
103 ad2d6807 Vangelis Koukis
104 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
105 ad2d6807 Vangelis Koukis
def process_net_status(vm, nics):
106 ad2d6807 Vangelis Koukis
    """Process a net status notification from the backend
107 ad2d6807 Vangelis Koukis

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

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

226 3a9b3cde Giorgos Verigakis
        metadata value should be a dictionary.
227 3a9b3cde Giorgos Verigakis
    """
228 7f691719 Christos Stavrakakis
    nic = {'ip': 'pool', 'network': settings.GANETI_PUBLIC_NETWORK}
229 61868190 Vangelis Koukis
230 61868190 Vangelis Koukis
    if settings.IGNORE_FLAVOR_DISK_SIZES:
231 3a9b3cde Giorgos Verigakis
        if image['backend_id'].find("windows") >= 0:
232 61868190 Vangelis Koukis
            sz = 14000
233 61868190 Vangelis Koukis
        else:
234 61868190 Vangelis Koukis
            sz = 4000
235 cf0e4232 Vangelis Koukis
    else:
236 61868190 Vangelis Koukis
        sz = flavor.disk * 1024
237 37ca953f Christodoulos Psaltis
238 1c382247 Vangelis Koukis
    # Handle arguments to CreateInstance() as a dictionary,
239 1c382247 Vangelis Koukis
    # initialize it based on a deployment-specific value.
240 1c382247 Vangelis Koukis
    # This enables the administrator to override deployment-specific
241 c25cc9ec Vangelis Koukis
    # arguments, such as the disk template to use, name of os provider
242 1c382247 Vangelis Koukis
    # and hypervisor-specific parameters at will (see Synnefo #785, #835).
243 1c382247 Vangelis Koukis
    #
244 1c382247 Vangelis Koukis
    kw = settings.GANETI_CREATEINSTANCE_KWARGS
245 1c382247 Vangelis Koukis
    kw['mode'] = 'create'
246 1c382247 Vangelis Koukis
    kw['name'] = vm.backend_id
247 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
248 805c79ae Giorgos Verigakis
    kw['disk_template'] = flavor.disk_template
249 1c382247 Vangelis Koukis
    kw['disks'] = [{"size": sz}]
250 1c382247 Vangelis Koukis
    kw['nics'] = [nic]
251 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
252 1c382247 Vangelis Koukis
    # kw['os'] = settings.GANETI_OS_PROVIDER
253 1c382247 Vangelis Koukis
    kw['ip_check'] = False
254 1c382247 Vangelis Koukis
    kw['name_check'] = False
255 1c382247 Vangelis Koukis
    # Do not specific a node explicitly, have
256 1c382247 Vangelis Koukis
    # Ganeti use an iallocator instead
257 1c382247 Vangelis Koukis
    #
258 1c382247 Vangelis Koukis
    # kw['pnode']=rapi.GetNodes()[0]
259 1c382247 Vangelis Koukis
    kw['dry_run'] = settings.TEST
260 41303ed0 Vangelis Koukis
261 2b1db26f Giorgos Verigakis
    kw['beparams'] = {
262 2b1db26f Giorgos Verigakis
        'auto_balance': True,
263 2b1db26f Giorgos Verigakis
        'vcpus': flavor.cpu,
264 2b1db26f Giorgos Verigakis
        'memory': flavor.ram}
265 41303ed0 Vangelis Koukis
266 e3b5be49 Giorgos Verigakis
    kw['osparams'] = {
267 3a9b3cde Giorgos Verigakis
        'img_id': image['backend_id'],
268 e3b5be49 Giorgos Verigakis
        'img_passwd': password,
269 3a9b3cde Giorgos Verigakis
        'img_format': image['format']}
270 2b1db26f Giorgos Verigakis
    if personality:
271 e3b5be49 Giorgos Verigakis
        kw['osparams']['img_personality'] = json.dumps(personality)
272 d1eaa651 Christos Stavrakakis
273 3a9b3cde Giorgos Verigakis
    kw['osparams']['img_properties'] = json.dumps(image['metadata'])
274 d1eaa651 Christos Stavrakakis
275 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
276 1c382247 Vangelis Koukis
    # kw['hvparams'] = dict(serial_console=False)
277 1c382247 Vangelis Koukis
278 1c382247 Vangelis Koukis
    return rapi.CreateInstance(**kw)
279 f533f224 Vangelis Koukis
280 529178b1 Giorgos Verigakis
281 529178b1 Giorgos Verigakis
def delete_instance(vm):
282 529178b1 Giorgos Verigakis
    start_action(vm, 'DESTROY')
283 64938cb0 Giorgos Verigakis
    rapi.DeleteInstance(vm.backend_id, dry_run=settings.TEST)
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 d1eaa651 Christos Stavrakakis
    rapi.ModifyInstance(vm.backend_id, nics=[('add', nic)],
392 3c755209 Dimitris Aragiorgis
                        hotplug=True, dry_run=settings.TEST)
393 64938cb0 Giorgos Verigakis
394 c25cc9ec Vangelis Koukis
395 64938cb0 Giorgos Verigakis
def disconnect_from_network(vm, net):
396 ca792e04 Giorgos Verigakis
    nics = vm.nics.filter(network__public=False).order_by('index')
397 d1eaa651 Christos Stavrakakis
    ops = [('remove', nic.index, {}) for nic in nics if nic.network == net]
398 d1eaa651 Christos Stavrakakis
    if not ops: # Vm not connected to network
399 d1eaa651 Christos Stavrakakis
        return
400 3c755209 Dimitris Aragiorgis
    rapi.ModifyInstance(vm.backend_id, nics=ops[::-1],
401 3c755209 Dimitris Aragiorgis
                        hotplug=True, dry_run=settings.TEST)
402 91826390 Giorgos Verigakis
403 c25cc9ec Vangelis Koukis
404 91826390 Giorgos Verigakis
def set_firewall_profile(vm, profile):
405 26563957 Giorgos Verigakis
    try:
406 26563957 Giorgos Verigakis
        tag = _firewall_tags[profile]
407 26563957 Giorgos Verigakis
    except KeyError:
408 91826390 Giorgos Verigakis
        raise ValueError("Unsopported Firewall Profile: %s" % profile)
409 37ca953f Christodoulos Psaltis
410 26563957 Giorgos Verigakis
    # Delete all firewall tags
411 efff6193 Giorgos Verigakis
    for t in _firewall_tags.values():
412 efff6193 Giorgos Verigakis
        rapi.DeleteInstanceTags(vm.backend_id, [t], dry_run=settings.TEST)
413 37ca953f Christodoulos Psaltis
414 26563957 Giorgos Verigakis
    rapi.AddInstanceTags(vm.backend_id, [tag], dry_run=settings.TEST)
415 9afeb669 Kostas Papadimitriou
416 2da5f785 Giorgos Verigakis
    # XXX NOP ModifyInstance call to force process_net_status to run
417 2da5f785 Giorgos Verigakis
    # on the dispatcher
418 5eedb0e4 Vangelis Koukis
    rapi.ModifyInstance(vm.backend_id,
419 5eedb0e4 Vangelis Koukis
                        os_name=settings.GANETI_CREATEINSTANCE_KWARGS['os'])
420 5eedb0e4 Vangelis Koukis
421 41303ed0 Vangelis Koukis
422 17852fe9 Giorgos Verigakis
def get_ganeti_instances():
423 17852fe9 Giorgos Verigakis
    return rapi.GetInstances()
424 17852fe9 Giorgos Verigakis
425 41303ed0 Vangelis Koukis
426 17852fe9 Giorgos Verigakis
def get_ganeti_nodes():
427 17852fe9 Giorgos Verigakis
    return rapi.GetNodes()
428 17852fe9 Giorgos Verigakis
429 41303ed0 Vangelis Koukis
430 17852fe9 Giorgos Verigakis
def get_ganeti_jobs():
431 17852fe9 Giorgos Verigakis
    return rapi.GetJobs()