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