From c61e9aeffcf79a035dabeadbef29b11e8fd6276c Mon Sep 17 00:00:00 2001 From: Tony Mack Date: Mon, 1 Oct 2012 16:45:59 -0400 Subject: [PATCH] implemented Interfaces, InterfaceTags, Messages, NetworkMethods, NetworkTypes, NodeGroups --- PLC/InterfaceTags.py | 52 ++++++++++++++---------- PLC/Interfaces.py | 87 ++++++++++++++++------------------------ PLC/Messages.py | 54 ++++++++++++++----------- PLC/NetworkMethods.py | 41 +++++++++++-------- PLC/NetworkTypes.py | 35 +++++++--------- PLC/NodeGroups.py | 92 +++++++++++++++---------------------------- 6 files changed, 166 insertions(+), 195 deletions(-) diff --git a/PLC/InterfaceTags.py b/PLC/InterfaceTags.py index af1deb46..4ed6e96b 100644 --- a/PLC/InterfaceTags.py +++ b/PLC/InterfaceTags.py @@ -4,20 +4,19 @@ from PLC.Faults import * from PLC.Parameter import Parameter from PLC.Filter import Filter -from PLC.Table import Row, Table +from PLC.Storage.AlchemyObject import AlchemyObj from PLC.TagTypes import TagType, TagTypes from PLC.Interfaces import Interface -class InterfaceTag(Row): +class InterfaceTag(AlchemyObj): """ Representation of a row in the interface_tag. To use, instantiate with a dict of values. """ - table_name = 'interface_tag' - primary_key = 'interface_tag_id' + table_name = 'interface_tags' fields = { - 'interface_tag_id': Parameter(int, "Interface setting identifier"), + 'interface_tag_id': Parameter(int, "Interface setting identifier", primary_key=True), 'interface_id': Interface.fields['interface_id'], 'ip': Interface.fields['ip'], 'tag_type_id': TagType.fields['tag_type_id'], @@ -29,26 +28,37 @@ class InterfaceTag(Row): } -class InterfaceTags(Table): + def sync(self, commit = True, validate=True): + AlchemyObj.sync(self, commit, validate) + if 'interface_tag_id' not in self: + # Before a new slice is added, delete expired slices + #expired = Slices(self.api, expires = -int(time.time())) + #for slice in expired: + # slice.delete(commit) + AlchemyObj.insert(self, dict(self)) + else: + AlchemyObj.update(self, {'interface_tag_id': self['interface_tag_id']}, dict(self)) + + def delete(self, commit=True): + assert 'interface_tag_id' in self + AlchemyObj.delete(self, dict(self)) + + +class InterfaceTags(list): """ Representation of row(s) from the interface_tag table in the database. """ def __init__(self, api, interface_tag_filter = None, columns = None): - Table.__init__(self, api, InterfaceTag, columns) - - sql = "SELECT %s FROM view_interface_tags WHERE True" % \ - ", ".join(self.columns) - - if interface_tag_filter is not None: - if isinstance(interface_tag_filter, (list, tuple, set, int, long)): - interface_tag_filter = Filter(InterfaceTag.fields, {'interface_tag_id': interface_tag_filter}) - elif isinstance(interface_tag_filter, dict): - interface_tag_filter = Filter(InterfaceTag.fields, interface_tag_filter) - else: - raise PLCInvalidArgument, "Wrong interface setting filter %r"%interface_tag_filter - sql += " AND (%s) %s" % interface_tag_filter.sql(api) - + if not interface_tag_filter: + interface_tags = InterfaceTag().select() + if isinstance(interface_tag_filter, (list, tuple, set, int, long)): + interface_tags = InterfaceTag().select(filter={'interface_tag_id': interface_tag_filter}) + elif isinstance(interface_tag_filter, dict): + interface_tags = InterfaceTag().select(filter=interface_tag_filter}) + else: + raise PLCInvalidArgument, "Wrong interface setting filter %r"%interface_tag_filter - self.selectall(sql) + for interface_tag in interface_tags: + self.append(interface_tag) diff --git a/PLC/Interfaces.py b/PLC/Interfaces.py index 0e6c7287..6de99fe3 100644 --- a/PLC/Interfaces.py +++ b/PLC/Interfaces.py @@ -11,9 +11,8 @@ import struct from PLC.Faults import * from PLC.Parameter import Parameter -from PLC.Filter import Filter from PLC.Debug import profile -from PLC.Table import Row, Table +from PLC.Storage.AlchemyObject import AlchemyObj from PLC.NetworkTypes import NetworkType, NetworkTypes from PLC.NetworkMethods import NetworkMethod, NetworkMethods import PLC.Nodes @@ -61,18 +60,17 @@ def in_same_network(address1, address2, netmask): return in_same_network_ipv4(address1, address2, netmask) or \ in_same_network_ipv6(address1, address2, netmask) -class Interface(Row): +class Interface(AlchemyObj): """ Representation of a row in the interfaces table. To use, optionally instantiate with a dict of values. Update as you would a dict. Commit to the database with sync(). """ - table_name = 'interfaces' - primary_key = 'interface_id' + tablename = 'interfaces' join_tables = ['interface_tag'] fields = { - 'interface_id': Parameter(int, "Node interface identifier"), + 'interface_id': Parameter(int, "Node interface identifier", primary_key=True), 'method': Parameter(str, "Addressing method (e.g., 'static' or 'dhcp')"), 'type': Parameter(str, "Address type (e.g., 'ipv4')"), 'ip': Parameter(str, "IP address", nullok = True), @@ -87,11 +85,10 @@ class Interface(Row): 'hostname': Parameter(str, "(Optional) Hostname", nullok = True), 'node_id': Parameter(int, "Node associated with this interface"), 'is_primary': Parameter(bool, "Is the primary interface for this node"), - 'interface_tag_ids' : Parameter([int], "List of interface settings"), + 'interface_tag_ids' : Parameter([int], "List of interface settings", joined=True), 'last_updated': Parameter(int, "Date and time when node entry was created", ro = True), } - view_tags_name = "view_interface_tags" tags = {} def validate_method(self, method): @@ -190,7 +187,7 @@ class Interface(Row): """ # Basic validation - Row.validate(self) + AlchemyObj.validate(self) assert 'method' in self method = self['method'] @@ -244,60 +241,46 @@ class Interface(Row): Update col_name field with current time """ - assert 'interface_id' in self - assert self.table_name - - self.api.db.do("UPDATE %s SET %s = CURRENT_TIMESTAMP " % (self.table_name, col_name) + \ - " where interface_id = %d" % (self['interface_id']) ) - self.sync(commit) + pass def update_last_updated(self, commit = True): self.update_timestamp('last_updated', commit) + def sync(self, commit=True, validate=True): + AlchemyObj.sync(self, commit, validate) + if 'interface_id' not in self: + AlchemyObj.insert(self, dict(self)) + else: + AlchemyObj.update(self, {'interface_id': self['interface_id']}, dict(self)) + def delete(self,commit=True): ### need to cleanup ilinks - self.api.db.do("DELETE FROM ilink WHERE src_interface_id=%d OR dst_interface_id=%d" % \ - (self['interface_id'],self['interface_id'])) - - Row.delete(self) + AlchemyObj.delete(self, dict(self) -class Interfaces(Table): + +class Interfaces(list): """ Representation of row(s) from the interfaces table in the database. """ def __init__(self, api, interface_filter = None, columns = None): - Table.__init__(self, api, Interface, 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)): - # 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): - 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 interface filter %r"%interface_filter - - self.selectall(sql) + if not interface_filter: + interfaces = Interface().select() + elif isinstance(interface_filter, (list, tuple, set)): + # 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) + interfaces = Interface().select(filter={'interface_id': ints, 'ip': strs}) + elif isinstance(interface_filter, dict): + interfaces = Interface().select(filter=interface_filter}) + elif isinstance(interface_filter, int): + interfaces = Interface().select(filter={'interface_id': interface_filter}) + elif isinstance (interface_filter, StringTypes): + interfaces = Interface().select(filter={'ip': interface_filter}) + else: + raise PLCInvalidArgument, "Wrong interface filter %r"%interface_filter + + for interface in interfaces: + self.append(interface) diff --git a/PLC/Messages.py b/PLC/Messages.py index 36969267..09f93356 100644 --- a/PLC/Messages.py +++ b/PLC/Messages.py @@ -8,43 +8,49 @@ from PLC.Parameter import Parameter from PLC.Table import Row, Table from PLC.Filter import Filter +from PLC.Storage.AlchemyObject import AlchemyObj -class Message(Row): +class Message(AlchemyObj): """ Representation of a row in the messages table. """ - table_name = 'messages' - primary_key = 'message_id' + tablename = 'messages' fields = { - 'message_id': Parameter(str, "Message identifier"), + 'message_id': Parameter(str, "Message identifier", primary_key=True), 'subject': Parameter(str, "Message summary", nullok = True), 'template': Parameter(str, "Message template", nullok = True), 'enabled': Parameter(bool, "Message is enabled"), } -class Messages(Table): + def sync(self, commit=True, validate=True): + AlchemyObj.sync(self, commit, validate) + if 'message_id' not in self: + # Before a new slice is added, delete expired slices + #expired = Slices(self.api, expires = -int(time.time())) + #for slice in expired: + # slice.delete(commit) + AlchemyObj.insert(self, dict(self)) + else: + AlchemyObj.update(self, {'message_id': self['message_id']}, dict(self)) + + def delete(self, commit = True): + AlchemyObj.delete(self, dict(self)) + +class Messages(list): """ Representation of row(s) from the messages table in the database. """ def __init__(self, api, message_filter = None, columns = None, enabled = None): - Table.__init__(self, api, Message, columns) - - sql = "SELECT %s from messages WHERE True" % \ - ", ".join(self.columns) - - if enabled is not None: - sql += " AND enabled IS %s" % enabled - - if message_filter is not None: - if isinstance(message_filter, (list, tuple, set, int, long)): - message_filter = Filter(Message.fields, {'message_id': message_filter}) - sql += " AND (%s) %s" % message_filter.sql(api, "OR") - elif isinstance(message_filter, dict): - message_filter = Filter(Message.fields, message_filter) - sql += " AND (%s) %s" % message_filter.sql(api, "AND") - else: - raise PLCInvalidArgument, "Wrong message filter %r"%message_filter - - self.selectall(sql) + if not message_filter: + messages = Message().select() + if isinstance(message_filter, (list, tuple, set, int, long)): + messages = Message().select(filter={'message_id': message_filter}) + elif isinstance(message_filter, dict): + messages = Message().select(filter=message_filter) + else: + raise PLCInvalidArgument, "Wrong message filter %r"%message_filter + + for message in messages: + self.append(message) diff --git a/PLC/NetworkMethods.py b/PLC/NetworkMethods.py index a54934d4..97e2505f 100644 --- a/PLC/NetworkMethods.py +++ b/PLC/NetworkMethods.py @@ -1,25 +1,22 @@ # # Functions for interacting with the network_methods table in the database # -# Mark Huang -# Copyright (C) 2006 The Trustees of Princeton University # - +from types import StringTypes from PLC.Faults import * from PLC.Parameter import Parameter -from PLC.Table import Row, Table +from PLC.Storage.AlchemyObject import AlchemyObj -class NetworkMethod(Row): +class NetworkMethod(AlchemyObj): """ Representation of a row in the network_methods table. To use, instantiate with a dict of values. """ - table_name = 'network_methods' - primary_key = 'method' + tablename = 'network_methods' join_tables = ['interfaces'] fields = { - 'method': Parameter(str, "Network method", max = 20), + 'method': Parameter(str, "Network method", max = 20, primary_key=True), } def validate_method(self, name): @@ -28,24 +25,34 @@ class NetworkMethod(Row): raise PLCInvalidArgument, "Network method must be specified" # Make sure network method does not alredy exist - conflicts = NetworkMethods(self.api, [name]) + conflicts = NetworkMethods(self.api, name) if conflicts: raise PLCInvalidArgument, "Network method name already in use" return name -class NetworkMethods(Table): + def sync(self, commit = True, validate=True): + AlchemyObj.sync(self, commit, validate) + AlchemyObj.insert(self, dict(self)) + + def delete(self, commit=True): + assert method in self + AlchemyObj.delete(self, dict(self)) + + +class NetworkMethods(list): """ Representation of the network_methods table in the database. """ def __init__(self, api, methods = None): - Table.__init__(self, api, NetworkMethod) - - sql = "SELECT %s FROM network_methods" % \ - ", ".join(NetworkMethod.fields) - if methods: - sql += " WHERE method IN (%s)" % ", ".join( [ api.db.quote (m) for m in methods ] ) + if not methods: + network_methods = NetworkMethod().select() + elif isinstance(methods, StringTypes): + network_methods = NetworkMethod().select(filter={'method': methods}) + else: + raise PLCInvalidArgument, "Wrong network method filter %r"%methods - self.selectall(sql) + self.extend(network_methods) + diff --git a/PLC/NetworkTypes.py b/PLC/NetworkTypes.py index eb34e7c9..e94b10b1 100644 --- a/PLC/NetworkTypes.py +++ b/PLC/NetworkTypes.py @@ -1,25 +1,21 @@ # # Functions for interacting with the network_types table in the database # -# Mark Huang -# Copyright (C) 2006 The Trustees of Princeton University # - +from types import StringTypes from PLC.Faults import * from PLC.Parameter import Parameter -from PLC.Table import Row, Table +from PLC.Storage.AlchemyObject import AlchemyObj -class NetworkType(Row): +class NetworkType(AlchemyObj): """ Representation of a row in the network_types table. To use, instantiate with a dict of values. """ - table_name = 'network_types' - primary_key = 'type' - join_tables = ['interfaces'] + tablename = 'network_types' fields = { - 'type': Parameter(str, "Network type", max = 20), + 'type': Parameter(str, "Network type", max = 20, primary_key=True), } def validate_type(self, name): @@ -28,24 +24,23 @@ class NetworkType(Row): raise PLCInvalidArgument, "Network type must be specified" # Make sure network type does not alredy exist - conflicts = NetworkTypes(self.api, [name]) + conflicts = NetworkTypes(self.api, name) if conflicts: raise PLCInvalidArgument, "Network type name already in use" return name -class NetworkTypes(Table): +class NetworkTypes(list): """ Representation of the network_types table in the database. """ def __init__(self, api, types = None): - Table.__init__(self, api, NetworkType) - - sql = "SELECT %s FROM network_types" % \ - ", ".join(NetworkType.fields) - - if types: - sql += " WHERE type IN (%s)" % ", ".join( [ api.db.quote (t) for t in types ] ) - - self.selectall(sql) + if not types: + network_types = NetworkType().select() + elif isinstance(types, StringTypes): + network_types = NetworkType().select({'type': types}) + else: + raise PLCInvalidArgument, "Wrong network type filter %r"%types + + self.extend(network_types) diff --git a/PLC/NodeGroups.py b/PLC/NodeGroups.py index bbbb6b30..1cccc286 100644 --- a/PLC/NodeGroups.py +++ b/PLC/NodeGroups.py @@ -1,17 +1,14 @@ # # Functions for interacting with the nodegroups table in the database # -# Mark Huang -# Copyright (C) 2006 The Trustees of Princeton University # from types import StringTypes from PLC.Faults import * from PLC.Parameter import Parameter, Mixed -from PLC.Filter import Filter from PLC.Debug import profile -from PLC.Table import Row, Table +from PLC.Storage.AlchemyObject import AlchemyObj from PLC.Nodes import Node, Nodes class NodeGroup(Row): @@ -21,18 +18,16 @@ class NodeGroup(Row): dict. Commit to the database with sync(). """ - table_name = 'nodegroups' - primary_key = 'nodegroup_id' + tablename = 'nodegroups' join_tables = ['conf_file_nodegroup'] - primary_field = 'nodegroup_id' fields = { - 'nodegroup_id': Parameter(int, "Node group identifier"), + 'nodegroup_id': Parameter(int, "Node group identifier", primary_key), 'groupname': Parameter(str, "Node group name", max = 50), 'tag_type_id': Parameter (int, "Node tag type id"), 'value' : Parameter(str, "value that the nodegroup definition is based upon"), 'tagname' : Parameter(str, "Tag name that the nodegroup definition is based upon"), - 'conf_file_ids': Parameter([int], "List of configuration files specific to this node group"), - 'node_ids' : Parameter([int], "List of node_ids that belong to this nodegroup"), + 'conf_file_ids': Parameter([int], "List of configuration files specific to this node group", joined=True), + 'node_ids' : Parameter([int], "List of node_ids that belong to this nodegroup", joined=True), } related_fields = { } @@ -43,68 +38,43 @@ class NodeGroup(Row): raise PLCInvalidArgument, "Invalid node group name" # Make sure node group does not alredy exist - conflicts = NodeGroups(self.api, [name]) + conflicts = NodeGroups(self.api, name) for nodegroup in conflicts: if 'nodegroup_id' not in self or self['nodegroup_id'] != nodegroup['nodegroup_id']: raise PLCInvalidArgument, "Node group name already in use" return name - def associate_conf_files(self, auth, field, value): - """ - Add conf_files found in value list (AddConfFileToNodeGroup) - Delets conf_files not found in value list (DeleteConfFileFromNodeGroup) - """ + def sync(self, commit=True, validate=True): + AlchemyObj.sync(self, commit, validate) + if 'nodegroup_id' not in self: + AlchemyObj.insert(self, dict(self)) + else: + AlchemyObj.update(self, {'nodegroup_id': self['nodegroup_id']}, dict(self)) - assert 'conf_file_ids' in self - assert 'nodegroup_id' in self - assert isinstance(value, list) - - conf_file_ids = self.separate_types(value)[0] - - if self['conf_file_ids'] != conf_file_ids: - from PLC.Methods.AddConfFileToNodeGroup import AddConfFileToNodeGroup - from PLC.Methods.DeleteConfFileFromNodeGroup import DeleteConfFileFromNodeGroup - new_conf_files = set(conf_file_ids).difference(self['conf_file_ids']) - stale_conf_files = set(self['conf_file_ids']).difference(conf_file_ids) - - for new_conf_file in new_conf_files: - AddConfFileToNodeGroup.__call__(AddConfFileToNodeGroup(self.api), - auth, new_conf_file, self['nodegroup_id']) - for stale_conf_file in stale_conf_files: - DeleteConfFileFromNodeGroup.__call__(DeleteConfFileFromNodeGroup(self.api), - auth, stale_conf_file, self['nodegroup_id']) - - -class NodeGroups(Table): +class NodeGroups(list): """ Representation of row(s) from the nodegroups table in the database. """ def __init__(self, api, nodegroup_filter = None, columns = None): - Table.__init__(self, api, NodeGroup, columns) - - sql = "SELECT %s FROM view_nodegroups WHERE True" % \ - ", ".join(self.columns) - - if nodegroup_filter is not None: - if isinstance(nodegroup_filter, (list, tuple, set)): - # Separate the list into integers and strings - ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter) - strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter) - nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': ints, 'groupname': strs}) - sql += " AND (%s) %s" % nodegroup_filter.sql(api, "OR") - elif isinstance(nodegroup_filter, dict): - nodegroup_filter = Filter(NodeGroup.fields, nodegroup_filter) - sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND") - elif isinstance(nodegroup_filter, (int, long)): - nodegroup_filter = Filter(NodeGroup.fields, {'nodegroup_id': nodegroup_filter}) - sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND") - elif isinstance(nodegroup_filter, StringTypes): - nodegroup_filter = Filter(NodeGroup.fields, {'groupname': nodegroup_filter}) - sql += " AND (%s) %s" % nodegroup_filter.sql(api, "AND") - else: - raise PLCInvalidArgument, "Wrong node group filter %r"%nodegroup_filter - self.selectall(sql) + if not nodegroup_filter is not None: + nodegroups = NodeGroup().select() + if isinstance(nodegroup_filter, (list, tuple, set)): + # Separate the list into integers and strings + ints = filter(lambda x: isinstance(x, (int, long)), nodegroup_filter) + strs = filter(lambda x: isinstance(x, StringTypes), nodegroup_filter) + nodegroups = NodeGroup().select(filter={'nodegroup_id': ints, 'groupname': strs}) + elif isinstance(nodegroup_filter, dict): + nodegroups = NodeGroup().select(filter=nodegroup_filter) + elif isinstance(nodegroup_filter, (int, long)): + nodegroups = NodeGroup().select(filter={'nodegroup_id': nodegroup_filter}) + elif isinstance(nodegroup_filter, StringTypes): + nodegroups = NodeGroup().select(filter={'groupname': nodegroup_filter}) + else: + raise PLCInvalidArgument, "Wrong node group filter %r"%nodegroup_filter + + for nodegroup in nodegroups: + self.append(nodegroup) -- 2.47.0