Statistics
| Branch: | Tag: | Revision:

root / logic / backend.py @ 41303ed0

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 529178b1 Giorgos Verigakis
from django.conf import settings
37 207b70d5 Giorgos Verigakis
from django.db import transaction
38 207b70d5 Giorgos Verigakis
39 adee02b8 Giorgos Verigakis
from synnefo.db.models import (VirtualMachine, Network, NetworkInterface,
40 adee02b8 Giorgos Verigakis
                                NetworkLink)
41 234f8b07 Vangelis Koukis
from synnefo.logic import utils
42 529178b1 Giorgos Verigakis
from synnefo.util.rapi import GanetiRapiClient
43 9e98ba3c Giorgos Verigakis
from synnefo.util.log import getLogger
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 37ca953f Christodoulos Psaltis
222 64938cb0 Giorgos Verigakis
    nic = {'ip': 'pool', 'mode': 'routed', 'link': settings.GANETI_PUBLIC_LINK}
223 61868190 Vangelis Koukis
224 61868190 Vangelis Koukis
    if settings.IGNORE_FLAVOR_DISK_SIZES:
225 61868190 Vangelis Koukis
        if image.backend_id.find("windows") >= 0:
226 61868190 Vangelis Koukis
            sz = 14000
227 61868190 Vangelis Koukis
        else:
228 61868190 Vangelis Koukis
            sz = 4000
229 cf0e4232 Vangelis Koukis
    else:
230 61868190 Vangelis Koukis
        sz = flavor.disk * 1024
231 37ca953f Christodoulos Psaltis
232 1c382247 Vangelis Koukis
    # Handle arguments to CreateInstance() as a dictionary,
233 1c382247 Vangelis Koukis
    # initialize it based on a deployment-specific value.
234 1c382247 Vangelis Koukis
    # This enables the administrator to override deployment-specific
235 c25cc9ec Vangelis Koukis
    # arguments, such as the disk template to use, name of os provider
236 1c382247 Vangelis Koukis
    # and hypervisor-specific parameters at will (see Synnefo #785, #835).
237 1c382247 Vangelis Koukis
    #
238 1c382247 Vangelis Koukis
    kw = settings.GANETI_CREATEINSTANCE_KWARGS
239 1c382247 Vangelis Koukis
    kw['mode'] = 'create'
240 1c382247 Vangelis Koukis
    kw['name'] = vm.backend_id
241 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
242 1c382247 Vangelis Koukis
    # kw['disk_template'] = settings.GANETI_DISK_TEMPLATE
243 1c382247 Vangelis Koukis
    kw['disks'] = [{"size": sz}]
244 1c382247 Vangelis Koukis
    kw['nics'] = [nic]
245 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
246 1c382247 Vangelis Koukis
    # kw['os'] = settings.GANETI_OS_PROVIDER
247 1c382247 Vangelis Koukis
    kw['ip_check'] = False
248 1c382247 Vangelis Koukis
    kw['name_check'] = False
249 1c382247 Vangelis Koukis
    # Do not specific a node explicitly, have
250 1c382247 Vangelis Koukis
    # Ganeti use an iallocator instead
251 1c382247 Vangelis Koukis
    #
252 1c382247 Vangelis Koukis
    # kw['pnode']=rapi.GetNodes()[0]
253 1c382247 Vangelis Koukis
    kw['dry_run'] = settings.TEST
254 41303ed0 Vangelis Koukis
255 2b1db26f Giorgos Verigakis
    kw['beparams'] = {
256 2b1db26f Giorgos Verigakis
        'auto_balance': True,
257 2b1db26f Giorgos Verigakis
        'vcpus': flavor.cpu,
258 2b1db26f Giorgos Verigakis
        'memory': flavor.ram}
259 41303ed0 Vangelis Koukis
260 e3b5be49 Giorgos Verigakis
    kw['osparams'] = {
261 e3b5be49 Giorgos Verigakis
        'img_id': image.backend_id,
262 e3b5be49 Giorgos Verigakis
        'img_passwd': password,
263 e3b5be49 Giorgos Verigakis
        'img_format': image.format}
264 2b1db26f Giorgos Verigakis
    if personality:
265 e3b5be49 Giorgos Verigakis
        kw['osparams']['img_personality'] = json.dumps(personality)
266 41303ed0 Vangelis Koukis
267 5949b704 Vangelis Koukis
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
268 1c382247 Vangelis Koukis
    # kw['hvparams'] = dict(serial_console=False)
269 1c382247 Vangelis Koukis
270 1c382247 Vangelis Koukis
    return rapi.CreateInstance(**kw)
271 f533f224 Vangelis Koukis
272 529178b1 Giorgos Verigakis
273 529178b1 Giorgos Verigakis
def delete_instance(vm):
274 529178b1 Giorgos Verigakis
    start_action(vm, 'DESTROY')
275 64938cb0 Giorgos Verigakis
    rapi.DeleteInstance(vm.backend_id, dry_run=settings.TEST)
276 d44c236b Giorgos Verigakis
    vm.nics.all().delete()
277 529178b1 Giorgos Verigakis
278 ad2d6807 Vangelis Koukis
279 529178b1 Giorgos Verigakis
def reboot_instance(vm, reboot_type):
280 529178b1 Giorgos Verigakis
    assert reboot_type in ('soft', 'hard')
281 64938cb0 Giorgos Verigakis
    rapi.RebootInstance(vm.backend_id, reboot_type, dry_run=settings.TEST)
282 9e98ba3c Giorgos Verigakis
    log.info('Rebooting instance %s', vm.backend_id)
283 529178b1 Giorgos Verigakis
284 ad2d6807 Vangelis Koukis
285 529178b1 Giorgos Verigakis
def startup_instance(vm):
286 529178b1 Giorgos Verigakis
    start_action(vm, 'START')
287 64938cb0 Giorgos Verigakis
    rapi.StartupInstance(vm.backend_id, dry_run=settings.TEST)
288 529178b1 Giorgos Verigakis
289 ad2d6807 Vangelis Koukis
290 529178b1 Giorgos Verigakis
def shutdown_instance(vm):
291 529178b1 Giorgos Verigakis
    start_action(vm, 'STOP')
292 64938cb0 Giorgos Verigakis
    rapi.ShutdownInstance(vm.backend_id, dry_run=settings.TEST)
293 529178b1 Giorgos Verigakis
294 ad2d6807 Vangelis Koukis
295 529178b1 Giorgos Verigakis
def get_instance_console(vm):
296 71099804 Vangelis Koukis
    # RAPI GetInstanceConsole() returns endpoints to the vnc_bind_address,
297 71099804 Vangelis Koukis
    # which is a cluster-wide setting, either 0.0.0.0 or 127.0.0.1, and pretty
298 71099804 Vangelis Koukis
    # useless (see #783).
299 71099804 Vangelis Koukis
    #
300 71099804 Vangelis Koukis
    # Until this is fixed on the Ganeti side, construct a console info reply
301 71099804 Vangelis Koukis
    # directly.
302 9afeb669 Kostas Papadimitriou
    #
303 71099804 Vangelis Koukis
    # WARNING: This assumes that VNC runs on port network_port on
304 71099804 Vangelis Koukis
    #          the instance's primary node, and is probably
305 71099804 Vangelis Koukis
    #          hypervisor-specific.
306 71099804 Vangelis Koukis
    #
307 71099804 Vangelis Koukis
    console = {}
308 71099804 Vangelis Koukis
    console['kind'] = 'vnc'
309 71099804 Vangelis Koukis
    i = rapi.GetInstance(vm.backend_id)
310 71099804 Vangelis Koukis
    if i['hvparams']['serial_console']:
311 71099804 Vangelis Koukis
        raise Exception("hv parameter serial_console cannot be true")
312 71099804 Vangelis Koukis
    console['host'] = i['pnode']
313 71099804 Vangelis Koukis
    console['port'] = i['network_port']
314 9afeb669 Kostas Papadimitriou
315 71099804 Vangelis Koukis
    return console
316 71099804 Vangelis Koukis
    # return rapi.GetInstanceConsole(vm.backend_id)
317 64938cb0 Giorgos Verigakis
318 c25cc9ec Vangelis Koukis
319 604b2bf8 Georgios Gousios
def request_status_update(vm):
320 604b2bf8 Georgios Gousios
    return rapi.GetInstanceInfo(vm.backend_id)
321 604b2bf8 Georgios Gousios
322 604b2bf8 Georgios Gousios
323 604b2bf8 Georgios Gousios
def get_job_status(jobid):
324 604b2bf8 Georgios Gousios
    return rapi.GetJobStatus(jobid)
325 604b2bf8 Georgios Gousios
326 604b2bf8 Georgios Gousios
327 604b2bf8 Georgios Gousios
def update_status(vm, status):
328 db7a3230 Vangelis Koukis
    utils.update_state(vm, status)
329 f533f224 Vangelis Koukis
330 c25cc9ec Vangelis Koukis
331 64938cb0 Giorgos Verigakis
def create_network_link():
332 64938cb0 Giorgos Verigakis
    try:
333 64938cb0 Giorgos Verigakis
        last = NetworkLink.objects.order_by('-index')[0]
334 64938cb0 Giorgos Verigakis
        index = last.index + 1
335 64938cb0 Giorgos Verigakis
    except IndexError:
336 64938cb0 Giorgos Verigakis
        index = 1
337 37ca953f Christodoulos Psaltis
338 64938cb0 Giorgos Verigakis
    if index <= settings.GANETI_MAX_LINK_NUMBER:
339 64938cb0 Giorgos Verigakis
        name = '%s%d' % (settings.GANETI_LINK_PREFIX, index)
340 f533f224 Vangelis Koukis
        return NetworkLink.objects.create(index=index, name=name,
341 a191bd4d Giorgos Verigakis
                                            available=True)
342 64938cb0 Giorgos Verigakis
    return None     # All link slots are filled
343 64938cb0 Giorgos Verigakis
344 c25cc9ec Vangelis Koukis
345 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
346 a3992827 Giorgos Verigakis
def create_network(name, owner):
347 64938cb0 Giorgos Verigakis
    try:
348 64938cb0 Giorgos Verigakis
        link = NetworkLink.objects.filter(available=True)[0]
349 64938cb0 Giorgos Verigakis
    except IndexError:
350 64938cb0 Giorgos Verigakis
        link = create_network_link()
351 64938cb0 Giorgos Verigakis
        if not link:
352 a3992827 Giorgos Verigakis
            return None
353 37ca953f Christodoulos Psaltis
354 a3992827 Giorgos Verigakis
    network = Network.objects.create(
355 a3992827 Giorgos Verigakis
        name=name,
356 a3992827 Giorgos Verigakis
        owner=owner,
357 a3992827 Giorgos Verigakis
        state='ACTIVE',
358 a3992827 Giorgos Verigakis
        link=link)
359 37ca953f Christodoulos Psaltis
360 a3992827 Giorgos Verigakis
    link.network = network
361 64938cb0 Giorgos Verigakis
    link.available = False
362 64938cb0 Giorgos Verigakis
    link.save()
363 37ca953f Christodoulos Psaltis
364 a3992827 Giorgos Verigakis
    return network
365 64938cb0 Giorgos Verigakis
366 c25cc9ec Vangelis Koukis
367 207b70d5 Giorgos Verigakis
@transaction.commit_on_success
368 64938cb0 Giorgos Verigakis
def delete_network(net):
369 64938cb0 Giorgos Verigakis
    link = net.link
370 06a16b24 Giorgos Verigakis
    if link.name != settings.GANETI_NULL_LINK:
371 06a16b24 Giorgos Verigakis
        link.available = True
372 06a16b24 Giorgos Verigakis
        link.network = None
373 06a16b24 Giorgos Verigakis
        link.save()
374 37ca953f Christodoulos Psaltis
375 64938cb0 Giorgos Verigakis
    for vm in net.machines.all():
376 64938cb0 Giorgos Verigakis
        disconnect_from_network(vm, net)
377 64938cb0 Giorgos Verigakis
        vm.save()
378 64938cb0 Giorgos Verigakis
    net.state = 'DELETED'
379 64938cb0 Giorgos Verigakis
    net.save()
380 64938cb0 Giorgos Verigakis
381 c25cc9ec Vangelis Koukis
382 64938cb0 Giorgos Verigakis
def connect_to_network(vm, net):
383 64938cb0 Giorgos Verigakis
    nic = {'mode': 'bridged', 'link': net.link.name}
384 ca792e04 Giorgos Verigakis
    rapi.ModifyInstance(vm.backend_id,
385 ca792e04 Giorgos Verigakis
        nics=[('add', nic)],
386 ca792e04 Giorgos Verigakis
        dry_run=settings.TEST)
387 64938cb0 Giorgos Verigakis
388 c25cc9ec Vangelis Koukis
389 64938cb0 Giorgos Verigakis
def disconnect_from_network(vm, net):
390 ca792e04 Giorgos Verigakis
    nics = vm.nics.filter(network__public=False).order_by('index')
391 ca792e04 Giorgos Verigakis
    new_nics = [nic for nic in nics if nic.network != net]
392 ca792e04 Giorgos Verigakis
    if new_nics == nics:
393 ca792e04 Giorgos Verigakis
        return      # Nothing to remove
394 ca792e04 Giorgos Verigakis
    ops = [('remove', {})]
395 ca792e04 Giorgos Verigakis
    for i, nic in enumerate(new_nics):
396 ca792e04 Giorgos Verigakis
        ops.append((i + 1, {
397 64938cb0 Giorgos Verigakis
            'mode': 'bridged',
398 ca792e04 Giorgos Verigakis
            'link': nic.network.link.name}))
399 ca792e04 Giorgos Verigakis
    rapi.ModifyInstance(vm.backend_id, nics=ops, 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()