# xxx - don't expose yet in api interface and slices dont know how to use that yet
define_accessors(current_module, Interface, "Ifname", "ifname",
"interface/config", "linux name",
- get_roles=all_roles, set_roles=tech_roles, expose_in_api=False)
+ get_roles=all_roles, set_roles=tech_roles, expose_in_api=True)
define_accessors(current_module, Interface, "Driver", "driver",
"interface/config", "driver name",
get_roles=all_roles, set_roles=tech_roles)
'secondary_key': 'hostname'},
Interface : {'table_class' : Interfaces,
'joins_class': InterfaceTags, 'join_class': InterfaceTag,
- },
+ 'secondary_key' : 'ip'},
Slice: {'table_class' : Slices,
'joins_class': SliceTags, 'join_class': SliceTag,
'secondary_key':'login_base'},
from PLC.Filter import Filter
from PLC.Table import Row, Table
from PLC.TagTypes import TagType, TagTypes
+from PLC.Interfaces import Interface
class InterfaceTag(Row):
"""
primary_key = 'interface_tag_id'
fields = {
'interface_tag_id': Parameter(int, "Interface setting identifier"),
- 'interface_id': Parameter(int, "Interface identifier"),
+ 'interface_id': Interface.fields['interface_id'],
+ 'ip': Interface.fields['ip'],
'tag_type_id': TagType.fields['tag_type_id'],
'tagname': TagType.fields['tagname'],
'description': TagType.fields['description'],
'interface_tag_ids' : Parameter([int], "List of interface settings"),
}
+ view_tags_name = "view_interface_tags"
+ tags = {}
+
def validate_method(self, method):
network_methods = [row['method'] for row in NetworkMethods(self.api)]
if method not in network_methods:
def __init__(self, api, interface_filter = None, columns = None):
Table.__init__(self, api, Interface, columns)
- sql = "SELECT %s FROM view_interfaces WHERE True" % \
- ", ".join(self.columns)
+ # the view that we're selecting upon: start with view_nodes
+ view = "view_interfaces"
+ # as many left joins as requested tags
+ for tagname in self.tag_columns:
+ view= "%s left join %s using (%s)"%(view,Interface.tagvalue_view_name(tagname),
+ Interface.primary_key)
+
+ sql = "SELECT %s FROM %s WHERE True" % \
+ (", ".join(self.columns.keys()+self.tag_columns.keys()),view)
if interface_filter is not None:
if isinstance(interface_filter, (list, tuple, set)):
- interface_filter = Filter(Interface.fields, {'interface_id': interface_filter})
+ # Separate the list into integers and strings
+ ints = filter(lambda x: isinstance(x, (int, long)), interface_filter)
+ strs = filter(lambda x: isinstance(x, StringTypes), interface_filter)
+ interface_filter = Filter(Interface.fields, {'interface_id': ints, 'ip': strs})
+ sql += " AND (%s) %s" % interface_filter.sql(api, "OR")
elif isinstance(interface_filter, dict):
- interface_filter = Filter(Interface.fields, interface_filter)
+ allowed_fields=dict(Interface.fields.items()+Interface.tags.items())
+ interface_filter = Filter(allowed_fields, interface_filter)
+ sql += " AND (%s) %s" % interface_filter.sql(api)
elif isinstance(interface_filter, int):
interface_filter = Filter(Interface.fields, {'interface_id': [interface_filter]})
+ sql += " AND (%s) %s" % interface_filter.sql(api)
+ elif isinstance (interface_filter, StringTypes):
+ interface_filter = Filter(Interface.fields, {'ip':[interface_filter]})
+ sql += " AND (%s) %s" % interface_filter.sql(api, "AND")
else:
- raise PLCInvalidArgument, "Wrong node network filter %r"%interface_filter
- sql += " AND (%s) %s" % interface_filter.sql(api)
+ raise PLCInvalidArgument, "Wrong interface filter %r"%interface_filter
self.selectall(sql)
# $Id$
from PLC.Faults import *
+from PLC.Auth import Auth
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
+from PLC.Table import Row
+
from PLC.Nodes import Node, Nodes
from PLC.Interfaces import Interface, Interfaces
-from PLC.Auth import Auth
+from PLC.TagTypes import TagTypes
+from PLC.InterfaceTags import InterfaceTags
+from PLC.Methods.AddInterfaceTag import AddInterfaceTag
+from PLC.Methods.UpdateInterfaceTag import UpdateInterfaceTag
-can_update = lambda (field, value): field not in ['interface_id', 'node_id']
+can_update = ['interface_id', 'node_id']
class AddInterface(Method):
"""
roles = ['admin', 'pi', 'tech']
- interface_fields = dict(filter(can_update, Interface.fields.items()))
+ accepted_fields = Row.accepted_fields(can_update, [Interface.fields,Interface.tags])
accepts = [
Auth(),
Mixed(Node.fields['node_id'],
Node.fields['hostname']),
- interface_fields
+ accepted_fields
]
returns = Parameter(int, 'New interface_id (> 0) if successful')
def call(self, auth, node_id_or_hostname, interface_fields):
- interface_fields = dict(filter(can_update, interface_fields.items()))
+
+ [native,tags,rejected]=Row.split_fields(interface_fields,[Interface.fields,Interface.tags])
+ if rejected:
+ raise PLCInvalidArgument, "Cannot add Interface with column(s) %r"%rejected
# Check if node exists
nodes = Nodes(self.api, [node_id_or_hostname])
if not nodes:
- raise PLCInvalidArgument, "No such node"
+ raise PLCInvalidArgument, "No such node %r"%node_id_or_hostname
node = nodes[0]
# Authenticated function
# member of the site where the node exists.
if 'admin' not in self.caller['roles']:
if node['site_id'] not in self.caller['site_ids']:
- raise PLCPermissionDenied, "Not allowed to add node network for specified node"
+ raise PLCPermissionDenied, "Not allowed to add an interface to the specified node"
- # Add node network
- interface = Interface(self.api, interface_fields)
+ # Add interface
+ interface = Interface(self.api, native)
interface['node_id'] = node['node_id']
- # if this is the first node network, make it primary
+ # if this is the first interface, make it primary
if not node['interface_ids']:
interface['is_primary'] = True
interface.sync()
# Logging variables
- self.object_ids = [node['node_id'], interface['interface_id']]
- self.messgage = "Node network %d added" % interface['interface_id']
+ self.object_objects = { 'Node': [node['node_id']],
+ 'Interface' : [interface['interface_id']] }
+ self.message = "Interface %d added" % interface['interface_id']
+
+ for (tagname,value) in tags.iteritems():
+ # the tagtype instance is assumed to exist, just check that
+ if not TagTypes(self.api,{'tagname':tagname}):
+ raise PLCInvalidArgument,"No such TagType %s"%tagname
+ interface_tags=InterfaceTags(self.api,{'tagname':tagname,'interface_id':interface['interface_id']})
+ if not interface_tags:
+ AddInterfaceTag(self.api).__call__(auth,interface['interface_id'],tagname,value)
+ else:
+ UpdateInterfaceTag(self.api).__call__(auth,interface_tags[0]['interface_tag_id'],value)
return interface['interface_id']
# $Id$
from PLC.Faults import *
+from PLC.Auth import Auth
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
from PLC.Table import Row
-from PLC.Nodes import Node, Nodes
-from PLC.NodeGroups import NodeGroup, NodeGroups
+
from PLC.Sites import Site, Sites
-from PLC.Auth import Auth
+from PLC.Nodes import Node, Nodes
from PLC.TagTypes import TagTypes
from PLC.NodeTags import NodeTags
from PLC.Methods.AddNodeTag import AddNodeTag
if node_fields.has_key('ssh_host_key'):
self.caller['ssh_rsa_key'] = node_fields['ssh_host_key']
- # Update primary node network state
+ # Update primary interface state
if node_fields.has_key('primary_network'):
primary_network = node_fields['primary_network']
if 'interface_id' not in primary_network:
- raise PLCInvalidArgument, "Node network not specified"
+ raise PLCInvalidArgument, "Interface not specified"
if primary_network['interface_id'] not in self.caller['interface_ids']:
- raise PLCInvalidArgument, "Node network not associated with calling node"
+ raise PLCInvalidArgument, "Interface not associated with calling node"
interfaces = Interfaces(self.api, [primary_network['interface_id']])
if not interfaces:
- raise PLCInvalidArgument, "No such node network"
+ raise PLCInvalidArgument, "No such interface %r"%interface_id
interface = interfaces[0]
if not interface['is_primary']:
- raise PLCInvalidArgument, "Not the primary node network on record"
+ raise PLCInvalidArgument, "Not the primary interface on record"
interface_fields = dict(filter(can_update, primary_network.items()))
interface.update(interface_fields)
class DeleteInterface(Method):
"""
- Deletes an existing node network interface.
+ Deletes an existing interface.
- Admins may delete any node network. PIs and techs may only delete
- node network interfaces associated with nodes at their sites.
+ Admins may delete any interface. PIs and techs may only delete
+ interface interfaces associated with nodes at their sites.
Returns 1 if successful, faults otherwise.
"""
def call(self, auth, interface_id):
- # Get node network information
+ # Get interface information
interfaces = Interfaces(self.api, [interface_id])
if not interfaces:
- raise PLCInvalidArgument, "No such node network"
+ raise PLCInvalidArgument, "No such interface %r"%interface_id
interface = interfaces[0]
# Get node information
nodes = Nodes(self.api, [interface['node_id']])
if not nodes:
- raise PLCInvalidArgument, "No such node"
+ raise PLCInvalidArgument, "No such node %r"%node_id
node = nodes[0]
# Authenticated functino
# member of the site at which the node is located.
if 'admin' not in self.caller['roles']:
if node['site_id'] not in self.caller['site_ids']:
- raise PLCPermissionDenied, "Not allowed to delete this node network"
+ raise PLCPermissionDenied, "Not allowed to delete this interface"
interface.delete()
# Logging variables
self.event_objects = {'Interface': [interface['interface_id']]}
- self.message = "Node network %d deleted" % interface['interface_id']
+ self.message = "Interface %d deleted" % interface['interface_id']
return 1
if node['site_id'] not in self.caller['site_ids']:
raise PLCPermissionDenied, "Not allowed to generate a configuration file for that node"
- # Get node networks for this node
+ # Get interfaces for this node
primary = None
interfaces = Interfaces(self.api, node['interface_ids'])
for interface in interfaces:
if node['site_id'] not in self.caller['site_ids']:
raise PLCPermissionDenied, "Not allowed to generate a configuration file for %s"%node['hostname']
- # Get node networks for this node
+ # Get interface for this node
primary = None
interfaces = Interfaces(self.api, node['interface_ids'])
for interface in interfaces:
class GetInterfaces(Method):
"""
- Returns an array of structs containing details about node network
- interfacess. If interfaces_filter is specified and is an array
- of node network identifiers, or a struct of node network
- fields and values, only node network interfaces matching the filter
- will be returned.
+ Returns an array of structs containing details about network
+ interfaces. If interfaces_filter is specified and is an array of
+ interface identifiers, or a struct of interface fields and
+ values, only interfaces matching the filter will be
+ returned.
If return_fields is given, only the specified details will be returned.
"""
accepts = [
Auth(),
- Mixed([Interface.fields['interface_id']],
+ Mixed([Mixed(Interface.fields['interface_id'],
+ Interface.fields['ip'])],
Parameter (int, "interface id"),
+ Parameter (str, "ip address"),
Filter(Interface.fields)),
Parameter([str], "List of fields to return", nullok = True)
]
from PLC.Faults import *
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
+from PLC.Table import Row
+from PLC.Auth import Auth
+
from PLC.Nodes import Node, Nodes
+from PLC.TagTypes import TagTypes
+from PLC.InterfaceTags import InterfaceTags
from PLC.Interfaces import Interface, Interfaces
-from PLC.Auth import Auth
+from PLC.Methods.AddInterfaceTag import AddInterfaceTag
+from PLC.Methods.UpdateInterfaceTag import UpdateInterfaceTag
-can_update = lambda (field, value): field not in \
- ['interface_id','node_id']
+can_update = ['interface_id','node_id']
class UpdateInterface(Method):
"""
- Updates an existing node network. Any values specified in
+ Updates an existing interface network. Any values specified in
interface_fields are used, otherwise defaults are
used. Acceptable values for method are dhcp and static. If type is
static, then ip, gateway, network, broadcast, netmask, and dns1
must all be specified in interface_fields. If type is dhcp,
these parameters, even if specified, are ignored.
- PIs and techs may only update networks associated with their own
- nodes. Admins may update any node network.
+ PIs and techs may only update interfaces associated with their own
+ nodes. Admins may update any interface network.
Returns 1 if successful, faults otherwise.
"""
roles = ['admin', 'pi', 'tech']
- interface_fields = dict(filter(can_update, Interface.fields.items()))
+ accepted_fields = Row.accepted_fields(can_update, [Interface.fields,Interface.tags])
accepts = [
Auth(),
Interface.fields['interface_id'],
- interface_fields
+ accepted_fields
]
returns = Parameter(int, '1 if successful')
def call(self, auth, interface_id, interface_fields):
- interface_fields = dict(filter(can_update, interface_fields.items()))
- # Get node network information
+ [native,tags,rejected] = Row.split_fields(interface_fields,[Interface.fields,Interface.tags])
+
+ if rejected:
+ raise PLCInvalidArgument, "Cannot update Interface column(s) %r"%rejected
+
+ # Get interface information
interfaces = Interfaces(self.api, [interface_id])
if not interfaces:
- raise PLCInvalidArgument, "No such node network"
+ raise PLCInvalidArgument, "No such interface"
interface = interfaces[0]
if 'admin' not in self.caller['roles']:
nodes = Nodes(self.api, [interface['node_id']])
if not nodes:
- raise PLCPermissionDenied, "Node network is not associated with a node"
+ raise PLCPermissionDenied, "Interface is not associated with a node"
node = nodes[0]
if node['site_id'] not in self.caller['site_ids']:
- raise PLCPermissionDenied, "Not allowed to update node network"
+ raise PLCPermissionDenied, "Not allowed to update interface"
- # Update node network
- interface.update(interface_fields)
+ interface.update(native)
interface.sync()
+ for (tagname,value) in tags.iteritems():
+ # the tagtype instance is assumed to exist, just check that
+ if not TagTypes(self.api,{'tagname':tagname}):
+ raise PLCInvalidArgument,"No such TagType %s"%tagname
+ interface_tags=InterfaceTags(self.api,{'tagname':tagname,'interface_id':interface['interface_id']})
+ if not interface_tags:
+ AddInterfaceTag(self.api).__call__(auth,interface['interface_id'],tagname,value)
+ else:
+ UpdateInterfaceTag(self.api).__call__(auth,interface_tags[0]['interface_tag_id'],value)
+
self.event_objects = {'Interface': [interface['interface_id']]}
- self.message = "Node network %d updated: %s " % \
+ self.message = "Interface %d updated: %s " % \
(interface['interface_id'], ", ".join(interface_fields.keys()))
return 1
from PLC.Method import Method
from PLC.Parameter import Parameter, Mixed
from PLC.Table import Row
-from PLC.Nodes import Node, Nodes
from PLC.Auth import Auth
+
+from PLC.Nodes import Node, Nodes
from PLC.TagTypes import TagTypes
from PLC.NodeTags import NodeTags
from PLC.Methods.AddNodeTag import AddNodeTag
[native,related,tags,rejected] = Row.split_fields(node_fields,[Node.fields,Node.related_fields,Node.tags])
if rejected:
- raise PLCInvalidArgument, "Cannot update column(s) %r"%rejected
+ raise PLCInvalidArgument, "Cannot update Node column(s) %r"%rejected
# Remove admin only fields
if 'admin' not in self.caller['roles']:
node.update_last_updated(commit=False)
node.sync(commit=True)
- # Logging variables
- self.event_objects = {'Node': [node['node_id']]}
- self.message = 'Node %d updated: %s.' % \
- (node['node_id'], ", ".join(node_fields.keys()))
- if 'boot_state' in node_fields.keys():
- self.message += ' boot_state updated to %s' % node_fields['boot_state']
-
for (tagname,value) in tags.iteritems():
# the tagtype instance is assumed to exist, just check that
if not TagTypes(self.api,{'tagname':tagname}):
else:
UpdateNodeTag(self.api).__call__(auth,node_tags[0]['node_tag_id'],value)
+ # Logging variables
+ self.event_objects = {'Node': [node['node_id']]}
+ self.message = 'Node %d updated: %s.' % \
+ (node['node_id'], ", ".join(node_fields.keys()))
+ if 'boot_state' in node_fields.keys():
+ self.message += ' boot_state updated to %s' % node_fields['boot_state']
+
return 1
view = "view_nodes"
# as many left joins as requested tags
for tagname in self.tag_columns:
- view= "%s left join %s using (%s)"%(view,Node.tagvalue_view_name(tagname),Node.primary_key)
+ view= "%s left join %s using (%s)"%(view,Node.tagvalue_view_name(tagname),
+ Node.primary_key)
sql = "SELECT %s FROM %s WHERE deleted IS False" % \
(", ".join(self.columns.keys()+self.tag_columns.keys()),view)
def __init__(self, api):
self.api = api
self.debug = False
+# self.debug = True
self.connection = None
def cursor(self):
Parameter(str, "Fully qualified hostname"))]
}
+ view_tags_name="view_slice_tags"
+ tags = {}
+
def validate_name(self, name):
# N.B.: Responsibility of the caller to ensure that login_base
# portion of the slice name corresponds to a valid site, if
(*) column 2: actual tag value, renamed into tagname
"""
- if not cls.view_tags_name: return ""
+ if not cls.view_tags_name:
+ raise Exception, 'WARNING: class %s needs to set view_tags_name'%cls.__name__
table_name=cls.table_name
primary_key=cls.primary_key
INSERT INTO network_methods (method) VALUES ('ipmi');
INSERT INTO network_methods (method) VALUES ('unknown');
--- Node network interfaces
+-- Network interfaces
CREATE TABLE interfaces (
-- Mandatory
interface_id serial PRIMARY KEY, -- Network interface identifier
SELECT
interface_tag.interface_tag_id,
interface_tag.interface_id,
+interfaces.ip,
tag_types.tag_type_id,
tag_types.tagname,
tag_types.description,
tag_types.min_role_id,
interface_tag.value
FROM interface_tag
-INNER JOIN tag_types USING (tag_type_id);
+INNER JOIN tag_types USING (tag_type_id)
+INNER JOIN interfaces USING (interface_id);
CREATE OR REPLACE VIEW view_interfaces AS
SELECT