(most) all functions now take SessionAuth in addition to PasswordAuth
[plcapi.git] / PLC / Methods / AdmGenerateNodeConfFile.py
1 import random
2 import base64
3
4 from PLC.Faults import *
5 from PLC.Method import Method
6 from PLC.Parameter import Parameter, Mixed
7 from PLC.Nodes import Node, Nodes
8 from PLC.NodeNetworks import NodeNetwork, NodeNetworks
9 from PLC.Auth import Auth
10
11 class AdmGenerateNodeConfFile(Method):
12     """
13     Deprecated. Functionality can be implemented with GetNodes,
14     GetNodeNetworks, and UpdateNode.
15
16     Creates a new node configuration file if all network settings are
17     present. This function will generate a new node key for the
18     specified node, effectively invalidating any old configuration
19     files.
20
21     Non-admins can only generate files for nodes at their sites.
22
23     Returns the contents of the file if successful, faults otherwise.
24     """
25
26     status = "deprecated"
27
28     roles = ['admin', 'pi', 'tech']
29
30     accepts = [
31         Auth(),
32         Mixed(Node.fields['node_id'],
33               Node.fields['hostname'])
34         ]
35
36     returns = Parameter(str, "Node configuration file")
37
38     def call(self, auth, node_id_or_hostname):
39         # Get node information
40         nodes = Nodes(self.api, [node_id_or_hostname]).values()
41         if not nodes:
42             raise PLCInvalidArgument, "No such node"
43         node = nodes[0]
44
45         # If we are not an admin, make sure that the caller is a
46         # member of the site at which the node is located.
47         if 'admin' not in self.caller['roles']:
48             if node['site_id'] not in self.caller['site_ids']:
49                 raise PLCPermissionDenied, "Not allowed to generate a configuration file for that node"
50
51         # Get node networks for this node
52         primary = None
53         nodenetworks = NodeNetworks(self.api, node['nodenetwork_ids']).values()
54         for nodenetwork in nodenetworks:
55             if nodenetwork['is_primary']:
56                 primary = nodenetwork
57                 break
58         if primary is None:
59             raise PLCInvalidArgument, "No primary network configured"
60
61         # Split hostname into host and domain parts
62         parts = node['hostname'].split(".", 1)
63         if len(parts) < 2:
64             raise PLCInvalidArgument, "Node hostname is invalid"
65         host = parts[0]
66         domain = parts[1]
67
68         # Generate 32 random bytes
69         bytes = random.sample(xrange(0, 256), 32)
70         # Base64 encode their string representation
71         node['key'] = base64.b64encode("".join(map(chr, bytes)))
72         # Save it
73         node.sync()
74
75         # Generate node configuration file suitable for BootCD
76         file = ""
77
78         file += 'NODE_ID="%d"\n' % node['node_id']
79         file += 'NODE_KEY="%s"\n' % node['key']
80
81         if primary['mac']:
82             file += 'NET_DEVICE="%s"\n' % primary['mac'].lower()
83
84         file += 'IP_METHOD="%s"\n' % primary['method']
85
86         if primary['method'] == 'static':
87             file += 'IP_ADDRESS="%s"\n' % primary['ip']
88             file += 'IP_GATEWAY="%s"\n' % primary['gateway']
89             file += 'IP_NETMASK="%s"\n' % primary['netmask']
90             file += 'IP_NETADDR="%s"\n' % primary['network']
91             file += 'IP_BROADCASTADDR="%s"\n' % primary['broadcast']
92             file += 'IP_DNS1="%s"\n' % primary['dns1']
93             file += 'IP_DNS2="%s"\n' % primary['dns2']
94
95         file += 'HOST_NAME="%s"\n' % host
96         file += 'DOMAIN_NAME="%s"\n' % domain
97
98         for nodenetwork in nodenetworks:
99             if nodenetwork['method'] == 'ipmi':
100                 file += 'IPMI_ADDRESS="%s"\n' % nodenetwork['ip']
101                 if nodenetwork['mac']:
102                     file += 'IPMI_MAC="%s"\n' % nodenetwork['mac'].lower()
103                 break
104
105         return file