bring over newinterface branch from Verivue
[plcapi.git] / PLC / Interfaces.py
index f4ddcc8..42e35e5 100644 (file)
@@ -18,49 +18,25 @@ from PLC.NetworkTypes import NetworkType, NetworkTypes
 from PLC.NetworkMethods import NetworkMethod, NetworkMethods
 import PLC.Nodes
 
-def valid_ipv4(ip):
+def valid_ip(ip):
     try:
         ip = socket.inet_ntoa(socket.inet_aton(ip))
         return True
     except socket.error:
         return False
 
-def valid_ipv6(ip):
-    try:
-        ip = socket.inet_ntop(socket.AF_INET6, socket.inet_pton(socket.AF_INET6, ip))
-        return True
-    except socket.error:
-        return False   
-
-def valid_ip(ip):
-    return valid_ipv4(ip) or valid_ipv6(ip)
-
-def in_same_network_ipv4(address1, address2, netmask):
+def in_same_network(address1, address2, netmask):
     """
     Returns True if two IPv4 addresses are in the same network. Faults
     if an address is invalid.
     """
+
     address1 = struct.unpack('>L', socket.inet_aton(address1))[0]
     address2 = struct.unpack('>L', socket.inet_aton(address2))[0]
     netmask = struct.unpack('>L', socket.inet_aton(netmask))[0]
 
     return (address1 & netmask) == (address2 & netmask)
 
-def in_same_network_ipv6(address1, address2, netmask):
-    """
-    Returns True if two IPv6 addresses are in the same network. Faults
-    if an address is invalid.
-    """
-    address1 = struct.unpack('>2Q', socket.inet_pton(socket.AF_INET6, address1))[0]
-    address2 = struct.unpack('>2Q', socket.inet_pton(socket.AF_INET6, address2))[0]
-    netmask = struct.unpack('>2Q', socket.inet_pton(socket.AF_INET6, netmask))[0]
-
-    return (address1 & netmask) == (address2 & netmask)
-
-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):
     """
     Representation of a row in the interfaces table. To use, optionally
@@ -70,24 +46,18 @@ class Interface(Row):
 
     table_name = 'interfaces'
     primary_key = 'interface_id'
-    join_tables = ['interface_tag']
+    join_tables = ['interface_tag', 'ip_addresses', 'routes']
     fields = {
         'interface_id': Parameter(int, "Node interface identifier"),
         '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),
         'mac': Parameter(str, "MAC address", nullok = True),
-        'gateway': Parameter(str, "IP address of primary gateway", nullok = True),
-        'network': Parameter(str, "Subnet address", nullok = True),
-        'broadcast': Parameter(str, "Network broadcast address", nullok = True),
-        'netmask': Parameter(str, "Subnet mask", nullok = True),
-        'dns1': Parameter(str, "IP address of primary DNS server", nullok = True),
-        'dns2': Parameter(str, "IP address of secondary DNS server", nullok = True),
         'bwlimit': Parameter(int, "Bandwidth limit", min = 0, nullok = True),
         '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"),
+        'if_name': Parameter(str, "Interface name", nullok = True),
         'interface_tag_ids' : Parameter([int], "List of interface settings"),
+        'ip_address_ids': Parameter([int], "List of addresses"),
         'last_updated': Parameter(int, "Date and time when node entry was created", ro = True),
         }
 
@@ -100,17 +70,6 @@ class Interface(Row):
             raise PLCInvalidArgument, "Invalid addressing method %s"%method
         return method
 
-    def validate_type(self, type):
-        network_types = [row['type'] for row in NetworkTypes(self.api)]
-        if type not in network_types:
-            raise PLCInvalidArgument, "Invalid address type %s"%type
-        return type
-
-    def validate_ip(self, ip):
-        if ip and not valid_ip(ip):
-            raise PLCInvalidArgument, "Invalid IP address %s"%ip
-        return ip
-
     def validate_mac(self, mac):
         if not mac:
             return mac
@@ -130,19 +89,15 @@ class Interface(Row):
 
         return mac
 
-    validate_gateway = validate_ip
-    validate_network = validate_ip
-    validate_broadcast = validate_ip
-    validate_netmask = validate_ip
-    validate_dns1 = validate_ip
-    validate_dns2 = validate_ip
-
     def validate_bwlimit(self, bwlimit):
         if not bwlimit:
             return bwlimit
 
-        if bwlimit < 500000:
-            raise PLCInvalidArgument, 'Minimum bw is 500 kbs'
+        if bwlimit < 1:
+            raise PLCInvalidArgument, 'Minimum bw is 1 Mbps'
+
+        if bwlimit >= 1000000:
+            raise PLCInvalidArgument, 'Maximum bw must be less than 1000000'
 
         return bwlimit
 
@@ -195,43 +150,6 @@ class Interface(Row):
         assert 'method' in self
         method = self['method']
 
-        if method == "proxy" or method == "tap":
-            if 'mac' in self and self['mac']:
-                raise PLCInvalidArgument, "For %s method, mac should not be specified" % method
-            if 'ip' not in self or not self['ip']:
-                raise PLCInvalidArgument, "For %s method, ip is required" % method
-            if method == "tap" and ('gateway' not in self or not self['gateway']):
-                raise PLCInvalidArgument, "For tap method, gateway is required and should be " \
-                      "the IP address of the node that proxies for this address"
-            # Should check that the proxy address is reachable, but
-            # there's no way to tell if the only primary interface is
-            # DHCP!
-
-        elif method == "static":
-            for key in ['gateway', 'dns1']:
-                if key not in self or not self[key]:
-                   if 'is_primary' in self and self['is_primary'] is True:
-                        raise PLCInvalidArgument, "For static method primary network, %s is required" % key
-                else:
-                    globals()[key] = self[key]
-            for key in ['ip', 'network', 'broadcast', 'netmask']:
-                if key not in self or not self[key]:
-                    raise PLCInvalidArgument, "For static method, %s is required" % key
-                globals()[key] = self[key]
-            if not in_same_network(ip, network, netmask):
-                raise PLCInvalidArgument, "IP address %s is inconsistent with network %s/%s" % \
-                      (ip, network, netmask)
-            if not in_same_network(broadcast, network, netmask):
-                raise PLCInvalidArgument, "Broadcast address %s is inconsistent with network %s/%s" % \
-                      (broadcast, network, netmask)
-            if 'gateway' in globals() and not in_same_network(ip, gateway, netmask):
-                raise PLCInvalidArgument, "Gateway %s is not reachable from %s/%s" % \
-                      (gateway, ip, netmask)
-
-        elif method == "ipmi":
-            if 'ip' not in self or not self['ip']:
-                raise PLCInvalidArgument, "For ipmi method, ip is required"
-
     validate_last_updated = Row.validate_timestamp
 
     def update_timestamp(self, col_name, commit = True):
@@ -276,11 +194,12 @@ class Interfaces(Table):
             (", ".join(self.columns.keys()+self.tag_columns.keys()),view)
 
         if interface_filter is not None:
+            # TODO: Deleted the ability here to filter by ipaddress; Need to make
+            #   sure that wasn't used anywhere.
             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})
+                interface_filter = Filter(Interface.fields, {'interface_id': ints})
                 sql += " AND (%s) %s" % interface_filter.sql(api, "OR")
             elif isinstance(interface_filter, dict):
                 allowed_fields=dict(Interface.fields.items()+Interface.tags.items())
@@ -289,9 +208,6 @@ class Interfaces(Table):
             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