Statistics
| Branch: | Tag: | Revision:

root / logic / backend.py @ 5231a38a

History | View | Annotate | Download (3.5 kB)

1
#
2
# Business Logic for communication with the Ganeti backend
3
#
4
# Copyright 2010 Greek Research and Technology Network
5
#
6

    
7
from django.conf import settings
8
from synnefo.db.models import VirtualMachine
9
from synnefo.logic import utils
10
from synnefo.util.rapi import GanetiRapiClient
11

    
12

    
13
rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO)
14

    
15

    
16
def process_backend_msg(vm, jobid, opcode, status, logmsg):
17
    """Process a job progress notification from the backend.
18

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

23
    """
24
    if (opcode not in [x[0] for x in VirtualMachine.BACKEND_OPCODES] or
25
       status not in [x[0] for x in VirtualMachine.BACKEND_STATUSES]):
26
        raise VirtualMachine.InvalidBackendMsgError(opcode, status)
27

    
28
    vm.backendjobid = jobid
29
    vm.backendjobstatus = status
30
    vm.backendopcode = opcode
31
    vm.backendlogmsg = logmsg
32

    
33
    # Notifications of success change the operating state
34
    if status == 'success':
35
        utils.update_state(vm, VirtualMachine.OPER_STATE_FROM_OPCODE[opcode])
36
        # Set the deleted flag explicitly, to cater for admin-initiated removals
37
        if opcode == 'OP_INSTANCE_REMOVE':
38
            vm.deleted = True
39

    
40
    # Special case: if OP_INSTANCE_CREATE fails --> ERROR
41
    if status in ('canceled', 'error') and opcode == 'OP_INSTANCE_CREATE':
42
        utils.update_state(vm, 'ERROR')
43
    # Any other notification of failure leaves the operating state unchanged
44

    
45
    vm.save()
46

    
47
def start_action(vm, action):
48
    """Update the state of a VM when a new action is initiated."""
49
    if not action in [x[0] for x in VirtualMachine.ACTIONS]:
50
        raise VirtualMachine.InvalidActionError(action)
51

    
52
    # No actions to deleted and no actions beside destroy to suspended VMs
53
    if vm.deleted:
54
        raise VirtualMachine.DeletedError
55
    
56
    if vm.operstate == 'BUILD':
57
        raise VirtualMachine.BuildingError
58
    
59
    vm.action = action
60
    vm.backendjobid = None
61
    vm.backendopcode = None
62
    vm.backendjobstatus = None
63
    vm.backendlogmsg = None
64

    
65
    # Update the relevant flags if the VM is being suspended or destroyed
66
    if action == "DESTROY":
67
        vm.deleted = True
68
    elif action == "SUSPEND":
69
        vm.suspended = True
70
    elif action == "START":
71
        vm.suspended = False
72
    vm.save()
73

    
74
def create_instance(vm, flavor, password):
75
    # FIXME: `password` must be passed to the Ganeti OS provider via CreateInstance()
76
    return rapi.CreateInstance(
77
        mode='create',
78
        name=vm.backend_id,
79
        disk_template='plain',
80
        disks=[{"size": 2000}],         #FIXME: Always ask for a 2GB disk for now
81
        nics=[{}],
82
        os='debootstrap+default',       #TODO: select OS from imageRef
83
        ip_check=False,
84
        name_check=False,
85
        pnode=rapi.GetNodes()[0],       #TODO: verify if this is necessary
86
        dry_run=settings.TEST,
87
        beparams=dict(auto_balance=True, vcpus=flavor.cpu, memory=flavor.ram))
88

    
89
def delete_instance(vm):
90
    start_action(vm, 'DESTROY')
91
    rapi.DeleteInstance(vm.backend_id)
92

    
93
def reboot_instance(vm, reboot_type):
94
    assert reboot_type in ('soft', 'hard')
95
    rapi.RebootInstance(vm.backend_id, reboot_type)
96

    
97
def startup_instance(vm):
98
    start_action(vm, 'START')
99
    rapi.StartupInstance(vm.backend_id)
100

    
101
def shutdown_instance(vm):
102
    start_action(vm, 'STOP')
103
    rapi.ShutdownInstance(vm.backend_id)
104

    
105
def get_instance_console(vm):
106
    return rapi.GetInstanceConsole(vm.backend_id)