- get person_ids when querying site information
[plcapi.git] / PLC / Methods / AdmAddNode.py
1 from PLC.Faults import *
2 from PLC.Method import Method
3 from PLC.Parameter import Parameter, Mixed
4 from PLC.Nodes import Node, Nodes
5 from PLC.NodeGroups import NodeGroup, NodeGroups
6 from PLC.Sites import Site, Sites
7 from PLC.Auth import PasswordAuth
8
9 class AdmAddNode(Method):
10     """
11     Adds a new node. Any values specified in optional_vals are used,
12     otherwise defaults are used.
13
14     PIs and techs may only add nodes to their own sites. Admins may
15     add nodes to any site.
16
17     Returns the new node_id (> 0) if successful, faults otherwise.
18     """
19
20     roles = ['admin', 'pi', 'tech']
21
22     can_update = lambda (field, value): field in \
23                  ['model', 'version']
24     update_fields = dict(filter(can_update, Node.fields.items()))
25
26     accepts = [
27         PasswordAuth(),
28         Mixed(Site.fields['site_id'],
29               Site.fields['login_base']),
30         Node.fields['hostname'],
31         Node.fields['boot_state'],
32         update_fields
33         ]
34
35     returns = Parameter(int, '1 if successful')
36
37     def call(self, auth, site_id_or_login_base, hostname, boot_state, optional_vals = {}):
38         if filter(lambda field: field not in self.update_fields, optional_vals):
39             raise PLCInvalidArgument, "Invalid fields specified"
40
41         # Get site information
42         sites = Sites(self.api, [site_id_or_login_base], ['person_ids'])
43         if not sites:
44             raise PLCInvalidArgument, "No such site"
45
46         site = sites.values()[0]
47
48         # Get site node group information
49         nodegroups = NodeGroups(self.api, [site['nodegroup_id']])
50         if not nodegroups:
51             raise PLCAPIError, "Site %d does not have a nodegroup" % site['site_id']
52
53         nodegroup = nodegroups.values()[0]
54
55         # Authenticated function
56         assert self.caller is not None
57
58         # If we are not an admin, make sure that the caller is a
59         # member of the site.
60         if 'admin' not in self.caller['roles']:
61             if site['site_id'] not in self.caller['site_ids']:
62                 assert self.caller['person_id'] not in site['person_ids']
63                 raise PLCPermissionDenied, "Not allowed to add nodes to specified site"
64             else:
65                 assert self.caller['person_id'] in site['person_ids']
66
67         node = Node(self.api, optional_vals)
68         node['hostname'] = hostname
69         node['boot_state'] = boot_state
70         node.flush(commit = False)
71
72         # Now associate the node with the site
73         nodegroup.add_node(node, commit = True)
74
75         return node['node_id']