Statistics
| Branch: | Tag: | Revision:

root / logic / backend.py @ ac63eb4f

History | View | Annotate | Download (4.2 kB)

1 234f8b07 Vangelis Koukis
#
2 234f8b07 Vangelis Koukis
# Business Logic for communication with the Ganeti backend
3 234f8b07 Vangelis Koukis
#
4 234f8b07 Vangelis Koukis
# Copyright 2010 Greek Research and Technology Network
5 234f8b07 Vangelis Koukis
#
6 02feca11 Vassilios Karakoidas
7 529178b1 Giorgos Verigakis
from django.conf import settings
8 234f8b07 Vangelis Koukis
from synnefo.db.models import VirtualMachine
9 234f8b07 Vangelis Koukis
from synnefo.logic import utils
10 529178b1 Giorgos Verigakis
from synnefo.util.rapi import GanetiRapiClient
11 529178b1 Giorgos Verigakis
12 529178b1 Giorgos Verigakis
13 529178b1 Giorgos Verigakis
rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
14 529178b1 Giorgos Verigakis
15 02feca11 Vassilios Karakoidas
16 ad2d6807 Vangelis Koukis
def process_op_status(vm, jobid, opcode, status, logmsg):
17 ad2d6807 Vangelis Koukis
    """Process a job progress notification from the backend
18 02feca11 Vassilios Karakoidas

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

23 02feca11 Vassilios Karakoidas
    """
24 02feca11 Vassilios Karakoidas
    if (opcode not in [x[0] for x in VirtualMachine.BACKEND_OPCODES] or
25 02feca11 Vassilios Karakoidas
       status not in [x[0] for x in VirtualMachine.BACKEND_STATUSES]):
26 02feca11 Vassilios Karakoidas
        raise VirtualMachine.InvalidBackendMsgError(opcode, status)
27 02feca11 Vassilios Karakoidas
28 dfd19c2d Vassilios Karakoidas
    vm.backendjobid = jobid
29 dfd19c2d Vassilios Karakoidas
    vm.backendjobstatus = status
30 dfd19c2d Vassilios Karakoidas
    vm.backendopcode = opcode
31 dfd19c2d Vassilios Karakoidas
    vm.backendlogmsg = logmsg
32 02feca11 Vassilios Karakoidas
33 02feca11 Vassilios Karakoidas
    # Notifications of success change the operating state
34 ac63eb4f Vangelis Koukis
    if status == 'success' and VirtualMachine.OPER_STATE_FROM_OPCODE[opcode] is not None:
35 234f8b07 Vangelis Koukis
        utils.update_state(vm, VirtualMachine.OPER_STATE_FROM_OPCODE[opcode])
36 685b219e Vangelis Koukis
        # Set the deleted flag explicitly, to cater for admin-initiated removals
37 685b219e Vangelis Koukis
        if opcode == 'OP_INSTANCE_REMOVE':
38 685b219e Vangelis Koukis
            vm.deleted = True
39 685b219e Vangelis Koukis
40 685b219e Vangelis Koukis
    # Special case: if OP_INSTANCE_CREATE fails --> ERROR
41 02feca11 Vassilios Karakoidas
    if status in ('canceled', 'error') and opcode == 'OP_INSTANCE_CREATE':
42 234f8b07 Vangelis Koukis
        utils.update_state(vm, 'ERROR')
43 02feca11 Vassilios Karakoidas
    # Any other notification of failure leaves the operating state unchanged
44 02feca11 Vassilios Karakoidas
45 02feca11 Vassilios Karakoidas
    vm.save()
46 22e52ede Vassilios Karakoidas
47 ad2d6807 Vangelis Koukis
48 ad2d6807 Vangelis Koukis
def process_net_status(vm, nics):
49 ad2d6807 Vangelis Koukis
    """Process a net status notification from the backend
50 ad2d6807 Vangelis Koukis

51 ad2d6807 Vangelis Koukis
    Process an incoming message from the Ganeti backend,
52 ad2d6807 Vangelis Koukis
    detailing the NIC configuration of a VM instance.
53 ad2d6807 Vangelis Koukis

54 ad2d6807 Vangelis Koukis
    Update the state of the VM in the DB accordingly.
55 ad2d6807 Vangelis Koukis

56 ad2d6807 Vangelis Koukis
    """
57 ad2d6807 Vangelis Koukis
58 ad2d6807 Vangelis Koukis
    # For the time being, we can only update the ipfour field,
59 ad2d6807 Vangelis Koukis
    # based on the IPv4 address of the first NIC
60 03805fc8 Vangelis Koukis
    if len(nics) > 0:
61 03805fc8 Vangelis Koukis
        ipv4 = nics[0]['ip']
62 03805fc8 Vangelis Koukis
        if ipv4 == '':
63 03805fc8 Vangelis Koukis
            ipv4 = '0.0.0.0'
64 03805fc8 Vangelis Koukis
        vm.ipfour = ipv4
65 ad2d6807 Vangelis Koukis
    vm.save()
66 ad2d6807 Vangelis Koukis
67 ad2d6807 Vangelis Koukis
68 22e52ede Vassilios Karakoidas
def start_action(vm, action):
69 22e52ede Vassilios Karakoidas
    """Update the state of a VM when a new action is initiated."""
70 22e52ede Vassilios Karakoidas
    if not action in [x[0] for x in VirtualMachine.ACTIONS]:
71 22e52ede Vassilios Karakoidas
        raise VirtualMachine.InvalidActionError(action)
72 22e52ede Vassilios Karakoidas
73 22e52ede Vassilios Karakoidas
    # No actions to deleted and no actions beside destroy to suspended VMs
74 22e52ede Vassilios Karakoidas
    if vm.deleted:
75 5231a38a Giorgos Verigakis
        raise VirtualMachine.DeletedError
76 30f3b5e5 Vangelis Koukis
   
77 30f3b5e5 Vangelis Koukis
    # No actions to machines being built. They may be destroyed, however.
78 30f3b5e5 Vangelis Koukis
    if vm.operstate == 'BUILD' and action != 'DESTROY':
79 5231a38a Giorgos Verigakis
        raise VirtualMachine.BuildingError
80 5231a38a Giorgos Verigakis
    
81 dfd19c2d Vassilios Karakoidas
    vm.action = action
82 dfd19c2d Vassilios Karakoidas
    vm.backendjobid = None
83 dfd19c2d Vassilios Karakoidas
    vm.backendopcode = None
84 dfd19c2d Vassilios Karakoidas
    vm.backendjobstatus = None
85 dfd19c2d Vassilios Karakoidas
    vm.backendlogmsg = None
86 22e52ede Vassilios Karakoidas
87 22e52ede Vassilios Karakoidas
    # Update the relevant flags if the VM is being suspended or destroyed
88 22e52ede Vassilios Karakoidas
    if action == "DESTROY":
89 22e52ede Vassilios Karakoidas
        vm.deleted = True
90 22e52ede Vassilios Karakoidas
    elif action == "SUSPEND":
91 22e52ede Vassilios Karakoidas
        vm.suspended = True
92 22e52ede Vassilios Karakoidas
    elif action == "START":
93 22e52ede Vassilios Karakoidas
        vm.suspended = False
94 22e52ede Vassilios Karakoidas
    vm.save()
95 529178b1 Giorgos Verigakis
96 ad2d6807 Vangelis Koukis
97 529178b1 Giorgos Verigakis
def create_instance(vm, flavor, password):
98 529178b1 Giorgos Verigakis
    # FIXME: `password` must be passed to the Ganeti OS provider via CreateInstance()
99 529178b1 Giorgos Verigakis
    return rapi.CreateInstance(
100 529178b1 Giorgos Verigakis
        mode='create',
101 12fd6446 Giorgos Verigakis
        name=vm.backend_id,
102 529178b1 Giorgos Verigakis
        disk_template='plain',
103 529178b1 Giorgos Verigakis
        disks=[{"size": 2000}],         #FIXME: Always ask for a 2GB disk for now
104 529178b1 Giorgos Verigakis
        nics=[{}],
105 529178b1 Giorgos Verigakis
        os='debootstrap+default',       #TODO: select OS from imageRef
106 529178b1 Giorgos Verigakis
        ip_check=False,
107 529178b1 Giorgos Verigakis
        name_check=False,
108 529178b1 Giorgos Verigakis
        pnode=rapi.GetNodes()[0],       #TODO: verify if this is necessary
109 529178b1 Giorgos Verigakis
        dry_run=settings.TEST,
110 529178b1 Giorgos Verigakis
        beparams=dict(auto_balance=True, vcpus=flavor.cpu, memory=flavor.ram))
111 529178b1 Giorgos Verigakis
112 529178b1 Giorgos Verigakis
def delete_instance(vm):
113 529178b1 Giorgos Verigakis
    start_action(vm, 'DESTROY')
114 529178b1 Giorgos Verigakis
    rapi.DeleteInstance(vm.backend_id)
115 529178b1 Giorgos Verigakis
116 ad2d6807 Vangelis Koukis
117 529178b1 Giorgos Verigakis
def reboot_instance(vm, reboot_type):
118 529178b1 Giorgos Verigakis
    assert reboot_type in ('soft', 'hard')
119 529178b1 Giorgos Verigakis
    rapi.RebootInstance(vm.backend_id, reboot_type)
120 529178b1 Giorgos Verigakis
121 ad2d6807 Vangelis Koukis
122 529178b1 Giorgos Verigakis
def startup_instance(vm):
123 529178b1 Giorgos Verigakis
    start_action(vm, 'START')
124 529178b1 Giorgos Verigakis
    rapi.StartupInstance(vm.backend_id)
125 529178b1 Giorgos Verigakis
126 ad2d6807 Vangelis Koukis
127 529178b1 Giorgos Verigakis
def shutdown_instance(vm):
128 529178b1 Giorgos Verigakis
    start_action(vm, 'STOP')
129 529178b1 Giorgos Verigakis
    rapi.ShutdownInstance(vm.backend_id)
130 529178b1 Giorgos Verigakis
131 ad2d6807 Vangelis Koukis
132 529178b1 Giorgos Verigakis
def get_instance_console(vm):
133 529178b1 Giorgos Verigakis
    return rapi.GetInstanceConsole(vm.backend_id)