956d342e7a5c815d3f73ad8d0fb3320c18cae3b1
[plcapi.git] / PLC / Methods / RebootNode.py
1 # $Id$
2 # $URL$
3 import socket
4
5 from PLC.Faults import *
6 from PLC.Method import Method
7 from PLC.Parameter import Parameter, Mixed
8 from PLC.Nodes import Node, Nodes
9 from PLC.Interfaces import Interface, Interfaces
10 from PLC.Auth import Auth
11 from PLC.POD import udp_pod
12
13 class RebootNode(Method):
14     """
15     Sends the specified node a specially formatted UDP packet which
16     should cause it to reboot immediately.
17
18     Admins can reboot any node. Techs and PIs can only reboot nodes at
19     their site.
20
21     Returns 1 if the packet was successfully sent (which only whether
22     the packet was sent, not whether the reboot was successful).
23     """
24
25     roles = ['admin', 'pi', 'tech']
26
27     accepts = [
28         Auth(),
29         Mixed(Node.fields['node_id'],
30               Node.fields['hostname'])
31         ]
32
33     returns = Parameter(int, '1 if successful')
34
35     def call(self, auth, node_id_or_hostname):
36         # Get account information
37         nodes = Nodes(self.api, [node_id_or_hostname])
38         if not nodes:
39             raise PLCInvalidArgument, "No such node"
40
41         node = nodes[0]
42
43         # Authenticated function
44         assert self.caller is not None
45
46         # If we are not an admin, make sure that the caller is a
47         # member of the site at which the node is located.
48         if 'admin' not in self.caller['roles']:
49             if node['site_id'] not in self.caller['site_ids']:
50                 raise PLCPermissionDenied, "Not allowed to delete nodes from specified site"
51
52         session = node['session']
53         if not session:
54             raise PLCInvalidArgument, "No session key on record for that node (i.e., has never successfully booted)"
55         session = session.strip()
56
57         # Only use the hostname as a backup, try to use the primary ID
58         # address instead.
59         host = node['hostname']
60         interfaces = Interfaces(self.api, node['interface_ids'])
61         for interface in interfaces:
62             if interface['is_primary'] == 1:
63                 host = interface['ip']
64                 break
65
66         try:
67             udp_pod(host, session)
68         except socket.error, e:
69             # Ignore socket errors
70             pass
71
72         self.event_objects = {'Node': [node['node_id']]}
73         self.message = "RebootNode called"
74
75         return 1