Statistics
| Branch: | Tag: | Revision:

root / logic / callbacks.py @ 960c15e0

History | View | Annotate | Download (8.1 kB)

1 cb409cfd Georgios Gousios
# Copyright 2011 GRNET S.A. All rights reserved.
2 ad2d6807 Vangelis Koukis
#
3 cb409cfd Georgios Gousios
# Redistribution and use in source and binary forms, with or without
4 cb409cfd Georgios Gousios
# modification, are permitted provided that the following conditions
5 cb409cfd Georgios Gousios
# are met:
6 ad2d6807 Vangelis Koukis
#
7 cb409cfd Georgios Gousios
#   1. Redistributions of source code must retain the above copyright
8 cb409cfd Georgios Gousios
#      notice, this list of conditions and the following disclaimer.
9 ad2d6807 Vangelis Koukis
#
10 cb409cfd Georgios Gousios
#  2. Redistributions in binary form must reproduce the above copyright
11 cb409cfd Georgios Gousios
#     notice, this list of conditions and the following disclaimer in the
12 cb409cfd Georgios Gousios
#     documentation and/or other materials provided with the distribution.
13 cb409cfd Georgios Gousios
#
14 cb409cfd Georgios Gousios
# THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
15 cb409cfd Georgios Gousios
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 cb409cfd Georgios Gousios
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 cb409cfd Georgios Gousios
# ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
18 cb409cfd Georgios Gousios
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 cb409cfd Georgios Gousios
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 cb409cfd Georgios Gousios
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 cb409cfd Georgios Gousios
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 cb409cfd Georgios Gousios
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 cb409cfd Georgios Gousios
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 cb409cfd Georgios Gousios
# SUCH DAMAGE.
25 cb409cfd Georgios Gousios
#
26 cb409cfd Georgios Gousios
# The views and conclusions contained in the software and documentation are
27 cb409cfd Georgios Gousios
# those of the authors and should not be interpreted as representing official
28 cb409cfd Georgios Gousios
# policies, either expressed or implied, of GRNET S.A.
29 cb409cfd Georgios Gousios
30 cb409cfd Georgios Gousios
# Callback functions used by the dispatcher to process incoming notifications
31 cb409cfd Georgios Gousios
# from AMQP queues.
32 cb409cfd Georgios Gousios
33 35079ab2 Georgios Gousios
import socket
34 23c84263 Georgios Gousios
import traceback
35 23c84263 Georgios Gousios
import json
36 23c84263 Georgios Gousios
import sys
37 23c84263 Georgios Gousios
38 23c84263 Georgios Gousios
from synnefo.db.models import VirtualMachine
39 c718de42 Georgios Gousios
from synnefo.logic import utils, backend, email_send, log
40 23c84263 Georgios Gousios
41 c718de42 Georgios Gousios
_logger = log.get_logger("synnefo.dispatcher")
42 23c84263 Georgios Gousios
43 23c84263 Georgios Gousios
def update_db(message):
44 76343e61 Georgios Gousios
    """Process the status of a VM based on a ganeti status message"""
45 ad2d6807 Vangelis Koukis
    _logger.debug("Processing ganeti-op-status msg: %s", message.body)
46 23c84263 Georgios Gousios
    try:
47 9b4a18b9 Georgios Gousios
        msg = _parse_json(message.body)
48 23c84263 Georgios Gousios
49 23c84263 Georgios Gousios
        if msg["type"] != "ganeti-op-status":
50 ad2d6807 Vangelis Koukis
            _logger.error("Message is of unknown type %s.", msg["type"])
51 23c84263 Georgios Gousios
            return
52 23c84263 Georgios Gousios
53 0d0aa87d Georgios Gousios
        if msg["operation"] == "OP_INSTANCE_QUERY_DATA":
54 0d0aa87d Georgios Gousios
            return status_job_finished(message)
55 0d0aa87d Georgios Gousios
56 23c84263 Georgios Gousios
        vmid = utils.id_from_instance_name(msg["instance"])
57 23c84263 Georgios Gousios
        vm = VirtualMachine.objects.get(id=vmid)
58 23c84263 Georgios Gousios
59 ad2d6807 Vangelis Koukis
        backend.process_op_status(vm, msg["jobId"], msg["operation"],
60 ad2d6807 Vangelis Koukis
                                  msg["status"], msg["logmsg"])
61 ad2d6807 Vangelis Koukis
        _logger.debug("Done processing ganeti-op-status msg for vm %s.",
62 ad2d6807 Vangelis Koukis
                      msg["instance"])
63 23c84263 Georgios Gousios
        message.channel.basic_ack(message.delivery_tag)
64 23c84263 Georgios Gousios
    except KeyError:
65 ad2d6807 Vangelis Koukis
        _logger.error("Malformed incoming JSON, missing attributes: %s",
66 ad2d6807 Vangelis Koukis
                      message.body)
67 23c84263 Georgios Gousios
    except VirtualMachine.InvalidBackendIdError:
68 ad2d6807 Vangelis Koukis
        _logger.debug("Ignoring msg for unknown instance %s.",
69 ad2d6807 Vangelis Koukis
                      msg["instance"])
70 23c84263 Georgios Gousios
    except VirtualMachine.DoesNotExist:
71 ad2d6807 Vangelis Koukis
        _logger.error("VM for instance %s with id %d not found in DB.",
72 ad2d6807 Vangelis Koukis
                      msg["instance"], vmid)
73 23c84263 Georgios Gousios
    except Exception as e:
74 f2bdb9ab Georgios Gousios
        _logger.exception("Unexpected error")
75 23c84263 Georgios Gousios
76 7ca9e930 Vangelis Koukis
77 7ca9e930 Vangelis Koukis
def update_net(message):
78 7ca9e930 Vangelis Koukis
    """Process a network status update notification from Ganeti"""
79 ad2d6807 Vangelis Koukis
    _logger.debug("Processing ganeti-net-status msg: %s", message.body)
80 ad2d6807 Vangelis Koukis
    try:
81 9b4a18b9 Georgios Gousios
        msg = _parse_json(message.body)
82 ad2d6807 Vangelis Koukis
83 ad2d6807 Vangelis Koukis
        if msg["type"] != "ganeti-net-status":
84 ad2d6807 Vangelis Koukis
            _logger.error("Message is of unknown type %s", msg["type"])
85 ad2d6807 Vangelis Koukis
            return
86 ad2d6807 Vangelis Koukis
87 ad2d6807 Vangelis Koukis
        vmid = utils.id_from_instance_name(msg["instance"])
88 ad2d6807 Vangelis Koukis
        vm = VirtualMachine.objects.get(id=vmid)
89 ad2d6807 Vangelis Koukis
90 ad2d6807 Vangelis Koukis
        backend.process_net_status(vm, msg["nics"])
91 ad2d6807 Vangelis Koukis
        _logger.debug("Done processing ganeti-net-status msg for vm %s.",
92 ad2d6807 Vangelis Koukis
                      msg["instance"])
93 ad2d6807 Vangelis Koukis
        message.channel.basic_ack(message.delivery_tag)
94 ad2d6807 Vangelis Koukis
    except KeyError:
95 ad2d6807 Vangelis Koukis
        _logger.error("Malformed incoming JSON, missing attributes: %s",
96 ad2d6807 Vangelis Koukis
                      message.body)
97 ad2d6807 Vangelis Koukis
    except VirtualMachine.InvalidBackendIdError:
98 ad2d6807 Vangelis Koukis
        _logger.debug("Ignoring msg for unknown instance %s.",
99 ad2d6807 Vangelis Koukis
                      msg["instance"])
100 ad2d6807 Vangelis Koukis
    except VirtualMachine.DoesNotExist:
101 ad2d6807 Vangelis Koukis
        _logger.error("VM for instance %s with id %d not found in DB.",
102 ad2d6807 Vangelis Koukis
                      msg["instance"], vmid)
103 ad2d6807 Vangelis Koukis
    except Exception as e:
104 f2bdb9ab Georgios Gousios
        _logger.exception("Unexpected error")
105 7ca9e930 Vangelis Koukis
106 7ca9e930 Vangelis Koukis
107 23c84263 Georgios Gousios
def send_email(message):
108 f8fd9e7b Georgios Gousios
    """Process an email submission request"""
109 f8fd9e7b Georgios Gousios
110 f8fd9e7b Georgios Gousios
    try:
111 f8fd9e7b Georgios Gousios
        msg = json.loads(message.body)
112 f8fd9e7b Georgios Gousios
113 583bfaa0 Georgios Gousios
        sent = email_send.send(sender=msg['frm'], recipient = msg['to'],
114 44837d17 Georgios Gousios
                        body=msg['body'], subject=msg['subject'])
115 583bfaa0 Georgios Gousios
116 583bfaa0 Georgios Gousios
        if not sent:
117 583bfaa0 Georgios Gousios
            _logger.warn("Failed to send email to %s", msg['to'])
118 583bfaa0 Georgios Gousios
        else:
119 583bfaa0 Georgios Gousios
            message.channel.basic_ack(message.delivery_tag)
120 f8fd9e7b Georgios Gousios
    except KeyError:
121 f8fd9e7b Georgios Gousios
        _logger.error("Malformed incoming JSON, missing attributes: %s",
122 f8fd9e7b Georgios Gousios
                      message.body)
123 35079ab2 Georgios Gousios
    except socket.error as e:
124 35079ab2 Georgios Gousios
        _logger.error("Cannot connect to SMTP server:%s\n", e)
125 f8fd9e7b Georgios Gousios
    except Exception as e:
126 f2bdb9ab Georgios Gousios
        _logger.exception("Unexpected error")
127 35079ab2 Georgios Gousios
        raise
128 23c84263 Georgios Gousios
129 23c84263 Georgios Gousios
130 23c84263 Georgios Gousios
def update_credits(message):
131 23c84263 Georgios Gousios
    _logger.debug("Request to update credits")
132 23c84263 Georgios Gousios
    message.channel.basic_ack(message.delivery_tag)
133 23c84263 Georgios Gousios
134 604b2bf8 Georgios Gousios
def trigger_status_update(message):
135 882c0c1f Georgios Gousios
    """
136 882c0c1f Georgios Gousios
        Triggers a status update job for a specific VM id.
137 882c0c1f Georgios Gousios
    """
138 0d0aa87d Georgios Gousios
    _logger.debug("Request to trigger status update: %s", message.body)
139 604b2bf8 Georgios Gousios
140 604b2bf8 Georgios Gousios
    try:
141 9b4a18b9 Georgios Gousios
        msg = _parse_json(message.body)
142 604b2bf8 Georgios Gousios
143 c4367587 Vangelis Koukis
        if msg["type"] != "reconcile":
144 604b2bf8 Georgios Gousios
             _logger.error("Message is of unknown type %s", msg["type"])
145 604b2bf8 Georgios Gousios
             return
146 604b2bf8 Georgios Gousios
147 c4367587 Vangelis Koukis
        if msg["vmid"] == "":
148 0d0aa87d Georgios Gousios
            _logger.error("Reconciliate message does not specify a VM id")
149 604b2bf8 Georgios Gousios
            return
150 604b2bf8 Georgios Gousios
151 0d0aa87d Georgios Gousios
        vm = VirtualMachine.objects.get(id=msg["vmid"])
152 604b2bf8 Georgios Gousios
        backend.request_status_update(vm)
153 604b2bf8 Georgios Gousios
154 604b2bf8 Georgios Gousios
        message.channel.basic_ack(message.delivery_tag)
155 0d0aa87d Georgios Gousios
    except KeyError as k:
156 0d0aa87d Georgios Gousios
        _logger.error("Malformed incoming JSON, missing attributes: %s", k)
157 604b2bf8 Georgios Gousios
    except Exception as e:
158 f2bdb9ab Georgios Gousios
        _logger.exception("Unexpected error")
159 604b2bf8 Georgios Gousios
160 c4367587 Vangelis Koukis
def status_job_finished (message):
161 882c0c1f Georgios Gousios
    """
162 882c0c1f Georgios Gousios
        Updates VM status based on a previously sent status update request
163 882c0c1f Georgios Gousios
    """
164 604b2bf8 Georgios Gousios
    try:
165 9b4a18b9 Georgios Gousios
        msg = _parse_json(message.body)
166 604b2bf8 Georgios Gousios
167 0d0aa87d Georgios Gousios
        if msg["operation"] != 'OP_INSTANCE_QUERY_DATA':
168 604b2bf8 Georgios Gousios
            _logger.error("Message is of unknown type %s", msg["operation"])
169 604b2bf8 Georgios Gousios
            return
170 604b2bf8 Georgios Gousios
171 c4367587 Vangelis Koukis
        if msg["status"] != "success":
172 0d0aa87d Georgios Gousios
            _logger.warn("Ignoring non-success status update from job %d on VM %s",
173 604b2bf8 Georgios Gousios
                          msg['jobId'], msg['instance'])
174 2f355fb5 Georgios Gousios
            message.channel.basic_ack(message.delivery_tag)
175 604b2bf8 Georgios Gousios
            return
176 604b2bf8 Georgios Gousios
177 0d0aa87d Georgios Gousios
        status = backend.get_job_status(msg['jobId'])
178 604b2bf8 Georgios Gousios
179 0d0aa87d Georgios Gousios
        _logger.debug("Node status job result: %s" % status)
180 0d0aa87d Georgios Gousios
181 c4367587 Vangelis Koukis
        if status['summary'][0] != u'INSTANCE_QUERY_DATA':
182 2f355fb5 Georgios Gousios
             _logger.error("Status update is of unknown type %s", status['summary'])
183 604b2bf8 Georgios Gousios
             return
184 604b2bf8 Georgios Gousios
185 2f355fb5 Georgios Gousios
        conf_state = status['opresult'][0][msg['instance']]['config_state']
186 2f355fb5 Georgios Gousios
        run_state = status['opresult'][0][msg['instance']]['run_state']
187 2f355fb5 Georgios Gousios
188 2f355fb5 Georgios Gousios
        # XXX: The following assumes names like snf-12
189 2f355fb5 Georgios Gousios
        instid = msg['instance'].split('-')[1]
190 2f355fb5 Georgios Gousios
191 2f355fb5 Georgios Gousios
        vm = VirtualMachine.objects.get(id = instid)
192 2f355fb5 Georgios Gousios
193 2f355fb5 Georgios Gousios
        if run_state == "up":
194 2f355fb5 Georgios Gousios
            opcode = "OP_INSTANCE_REBOOT"
195 c4367587 Vangelis Koukis
        else:
196 2f355fb5 Georgios Gousios
            opcode = "OP_INSTANCE_SHUTDOWN"
197 2f355fb5 Georgios Gousios
198 2f355fb5 Georgios Gousios
        backend.process_op_status(vm=vm, jobid=msg['jobId'],opcode=opcode,
199 2f355fb5 Georgios Gousios
                                  status="success",
200 2f355fb5 Georgios Gousios
                                  logmsg="Reconciliation: simulated event")
201 2f355fb5 Georgios Gousios
202 604b2bf8 Georgios Gousios
        message.channel.basic_ack(message.delivery_tag)
203 0d0aa87d Georgios Gousios
    except KeyError as k:
204 0d0aa87d Georgios Gousios
        _logger.error("Malformed incoming JSON, missing attributes: %s", k)
205 604b2bf8 Georgios Gousios
    except Exception as e:
206 f2bdb9ab Georgios Gousios
        _logger.exception("Unexpected error")
207 23c84263 Georgios Gousios
208 23c84263 Georgios Gousios
def dummy_proc(message):
209 23c84263 Georgios Gousios
    try:
210 960c15e0 Georgios Gousios
        _logger.debug("Msg: %s" %(message.body))
211 23c84263 Georgios Gousios
        message.channel.basic_ack(message.delivery_tag)
212 23c84263 Georgios Gousios
    except Exception as e:
213 960c15e0 Georgios Gousios
        _logger.exception("Could not receive message")
214 23c84263 Georgios Gousios
        pass
215 9b4a18b9 Georgios Gousios
216 9b4a18b9 Georgios Gousios
def _parse_json(data):
217 9b4a18b9 Georgios Gousios
    try:
218 9b4a18b9 Georgios Gousios
        return json.loads(data)
219 9b4a18b9 Georgios Gousios
    except Exception as e:
220 9b4a18b9 Georgios Gousios
        _logger.error("Could not parse JSON file: %s", e)
221 9b4a18b9 Georgios Gousios
        raise