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.Table import Row
7 from PLC.Nodes import Node, Nodes
8 from PLC.Interfaces import Interface, Interfaces
9 from PLC.IpAddresses import IpAddress, IpAddresses
10 from PLC.Routes import Route, Routes
11 from PLC.TagTypes import TagTypes
12 from PLC.InterfaceTags import InterfaceTags
13 from PLC.Methods.AddInterfaceTag import AddInterfaceTag
14 from PLC.Methods.UpdateInterfaceTag import UpdateInterfaceTag
15 from PLC.Methods.UpdateNode import UpdateNode
17 cannot_update = ['interface_id', 'node_id']
19 legacy_interface_fields = {
20 'interface_id': Parameter(int, "Node interface identifier"),
21 'method': Parameter(str, "Addressing method (e.g., 'static' or 'dhcp')"),
22 'type': Parameter(str, "Address type (e.g., 'ipv4')"),
23 'ip': Parameter(str, "IP address", nullok = True),
24 'mac': Parameter(str, "MAC address", nullok = True),
25 'gateway': Parameter(str, "IP address of primary gateway", nullok = True),
26 'network': Parameter(str, "Subnet address", nullok = True),
27 'broadcast': Parameter(str, "Network broadcast address", nullok = True),
28 'netmask': Parameter(str, "Subnet mask", nullok = True),
29 'dns1': Parameter(str, "IP address of primary DNS server", nullok = True),
30 'dns2': Parameter(str, "IP address of secondary DNS server", nullok = True),
31 'bwlimit': Parameter(int, "Bandwidth limit", min = 0, nullok = True),
32 'hostname': Parameter(str, "(Optional) Hostname", nullok = True),
33 'node_id': Parameter(int, "Node associated with this interface"),
34 'is_primary': Parameter(bool, "Is the primary interface for this node"),
35 'interface_tag_ids' : Parameter([int], "List of interface settings"),
36 'last_updated': Parameter(int, "Date and time when the interface entry was last updated"),
39 class AddInterface(Method):
42 Adds a new network for a node. Any values specified in
43 interface_fields are used, otherwise defaults are
46 If type is static, then ip, gateway, network, broadcast, netmask,
47 and dns1 must all be specified in interface_fields. If type is
48 dhcp, these parameters, even if specified, are ignored.
50 PIs and techs may only add interfaces to their own nodes. Admins may
51 add interfaces to any node.
53 Returns the new interface_id (> 0) if successful, faults otherwise.
56 roles = ['admin', 'pi', 'tech']
58 accepted_fields = Row.accepted_fields(cannot_update, legacy_interface_fields, exclude=True)
59 accepted_fields.update(Interface.tags)
63 Mixed(Node.fields['node_id'],
64 Node.fields['hostname']),
68 returns = Parameter(int, 'New interface_id (> 0) if successful')
71 def call(self, auth, node_id_or_hostname, interface_fields):
73 [native,tags,rejected]=Row.split_fields(interface_fields,[legacy_interface_fields,Interface.tags])
76 native = Row.check_fields (native, self.accepted_fields)
78 raise PLCInvalidArgument, "Cannot add Interface with column(s) %r"%rejected
80 # Check if node exists
81 nodes = Nodes(self.api, [node_id_or_hostname])
83 raise PLCInvalidArgument, "No such node %r"%node_id_or_hostname
86 # Authenticated function
87 assert self.caller is not None
89 # If we are not an admin, make sure that the caller is a
90 # member of the site where the node exists.
91 if 'admin' not in self.caller['roles']:
92 if node['site_id'] not in self.caller['site_ids']:
93 raise PLCPermissionDenied, "Not allowed to add an interface to the specified node"
96 interface = Interface(self.api, native)
97 interface['node_id'] = node['node_id']
98 # if this is the first interface, make it primary
99 if not node['interface_ids']:
100 interface['is_primary'] = True
103 # Add IpAddress to conform with the new object model
104 if native['method'] == 'static':
106 address_fields['interface_id'] = interface['interface_id']
107 address_fields['ip_addr'] = native['ip']
108 address_fields['netmask'] = native['netmask']
109 address_fields['type'] = native['type']
110 ip_address = IpAddress(self.api, address_fields)
113 # ADD DNS and ROUTES if this is a primary interface
114 if native['is_primary']:
116 route_fields['node_id'] = interface['node_id']
117 route_fields['interface_id'] = interface['interface_id']
118 route_fields['subnet'] = '0.0.0.0/0'
119 route_fields['next_hop'] = interface['gateway']
120 route = Route(self.api, route_fields)
124 if native.has_key('dns1'):
125 dns += native['dns1']
126 if native.has_key('dns2'):
127 dns += ",%s" % native['dns2']
130 UpdateNode(self.api).__call__(auth, interface['node_id'], {'dns':dns})
134 self.event_objects = { 'Node': [node['node_id']],
135 'Interface' : [interface['interface_id']] }
136 self.message = "Interface %d added" % interface['interface_id']
138 for (tagname,value) in tags.iteritems():
139 # the tagtype instance is assumed to exist, just check that
140 if not TagTypes(self.api,{'tagname':tagname}):
141 raise PLCInvalidArgument,"No such TagType %s"%tagname
142 interface_tags=InterfaceTags(self.api,{'tagname':tagname,'interface_id':interface['interface_id']})
143 if not interface_tags:
144 AddInterfaceTag(self.api).__call__(auth,interface['interface_id'],tagname,value)
146 UpdateInterfaceTag(self.api).__call__(auth,interface_tags[0]['interface_tag_id'],value)
148 return interface['interface_id']