svn keywords
[plcapi.git] / PLC / Methods / AddNode.py
1 # $Id$
2 # $URL$
3 from PLC.Faults import *
4 from PLC.Auth import Auth
5 from PLC.Method import Method
6 from PLC.Parameter import Parameter, Mixed
7 from PLC.Table import Row
8
9 from PLC.Sites import Site, Sites
10 from PLC.Nodes import Node, Nodes
11 from PLC.TagTypes import TagTypes
12 from PLC.NodeTags import NodeTags
13 from PLC.Methods.AddNodeTag import AddNodeTag
14 from PLC.Methods.UpdateNodeTag import UpdateNodeTag
15
16 can_update = ['hostname', 'node_type', 'boot_state', 'model', 'version']
17
18 class AddNode(Method):
19     """
20     Adds a new node. Any values specified in node_fields are used,
21     otherwise defaults are used.
22
23     PIs and techs may only add nodes to their own sites. Admins may
24     add nodes to any site.
25
26     Returns the new node_id (> 0) if successful, faults otherwise.
27     """
28
29     roles = ['admin', 'pi', 'tech']
30
31     accepted_fields = Row.accepted_fields(can_update,Node.fields)
32     accepted_fields.update(Node.tags)
33
34     accepts = [
35         Auth(),
36         Mixed(Site.fields['site_id'],
37               Site.fields['login_base']),
38         accepted_fields
39         ]
40
41     returns = Parameter(int, 'New node_id (> 0) if successful')
42
43     def call(self, auth, site_id_or_login_base, node_fields):
44
45         [native,tags,rejected]=Row.split_fields(node_fields,[Node.fields,Node.tags])
46
47         # type checking
48         native = Row.check_fields (native, self.accepted_fields)
49         if rejected:
50             raise PLCInvalidArgument, "Cannot add Node with column(s) %r"%rejected
51
52         # Get site information
53         sites = Sites(self.api, [site_id_or_login_base])
54         if not sites:
55             raise PLCInvalidArgument, "No such site"
56
57         site = sites[0]
58
59         # Authenticated function
60         assert self.caller is not None
61
62         # If we are not an admin, make sure that the caller is a
63         # member of the site.
64         if 'admin' not in self.caller['roles']:
65             if site['site_id'] not in self.caller['site_ids']:
66                 assert self.caller['person_id'] not in site['person_ids']
67                 raise PLCPermissionDenied, "Not allowed to add nodes to specified site"
68             else:
69                 assert self.caller['person_id'] in site['person_ids']
70
71         node = Node(self.api, native)
72         node['site_id'] = site['site_id']
73         node.sync()
74
75         for (tagname,value) in tags.iteritems():
76             # the tagtype instance is assumed to exist, just check that
77             if not TagTypes(self.api,{'tagname':tagname}):
78                 raise PLCInvalidArgument,"No such TagType %s"%tagname
79             node_tags=NodeTags(self.api,{'tagname':tagname,'node_id':node['node_id']})
80             if not node_tags:
81                 AddNodeTag(self.api).__call__(auth,node['node_id'],tagname,value)
82             else:
83                 UpdateNodeTag(self.api).__call__(auth,node_tags[0]['node_tag_id'],value)
84
85         self.event_objects = {'Site': [site['site_id']],
86                              'Node': [node['node_id']]} 
87         self.message = "Node %s created" % node['node_id']
88
89         return node['node_id']