remove PLC.Debug.log, use PLC.Logger.logger instead
[plcapi.git] / PLC / Peers.py
index 729fd71..c272a2a 100644 (file)
@@ -1,29 +1,31 @@
-# $Id$
 #
 # Thierry Parmentelat - INRIA
 #
 # Thierry Parmentelat - INRIA
-# 
+#
 
 import re
 from types import StringTypes
 
 import re
 from types import StringTypes
+import traceback
 from urlparse import urlparse
 
 from urlparse import urlparse
 
+import PLC.Auth
+from PLC.Logger import logger
 from PLC.Faults import *
 from PLC.Faults import *
+from PLC.Namespace import hostname_to_hrn
 from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Table import Row, Table
 from PLC.Parameter import Parameter, Mixed
 from PLC.Filter import Filter
 from PLC.Table import Row, Table
-import PLC.Auth
-
 from PLC.Sites import Site, Sites
 from PLC.Persons import Person, Persons
 from PLC.Keys import Key, Keys
 from PLC.Nodes import Node, Nodes
 from PLC.TagTypes import TagType, TagTypes
 from PLC.Sites import Site, Sites
 from PLC.Persons import Person, Persons
 from PLC.Keys import Key, Keys
 from PLC.Nodes import Node, Nodes
 from PLC.TagTypes import TagType, TagTypes
+from PLC.NodeTags import NodeTag, NodeTags
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Slices import Slice, Slices
 
 class Peer(Row):
     """
 from PLC.SliceTags import SliceTag, SliceTags
 from PLC.Slices import Slice, Slices
 
 class Peer(Row):
     """
-    Stores the list of peering PLCs in the peers table. 
+    Stores the list of peering PLCs in the peers table.
     See the Row class for more details
     """
 
     See the Row class for more details
     """
 
@@ -31,18 +33,20 @@ class Peer(Row):
     primary_key = 'peer_id'
     join_tables = ['peer_site', 'peer_person', 'peer_key', 'peer_node', 'peer_slice']
     fields = {
     primary_key = 'peer_id'
     join_tables = ['peer_site', 'peer_person', 'peer_key', 'peer_node', 'peer_slice']
     fields = {
-       'peer_id': Parameter (int, "Peer identifier"),
-       'peername': Parameter (str, "Peer name"),
-       'peer_url': Parameter (str, "Peer API URL"),
-       'key': Parameter(str, "Peer GPG public key"),
-       'cacert': Parameter(str, "Peer SSL public certificate"),
+        'peer_id': Parameter (int, "Peer identifier"),
+        'peername': Parameter (str, "Peer name"),
+        'peer_url': Parameter (str, "Peer API URL"),
+        'key': Parameter(str, "Peer GPG public key"),
+        'cacert': Parameter(str, "Peer SSL public certificate"),
+        'shortname' : Parameter(str, "Peer short name"),
+        'hrn_root' : Parameter(str, "Root of this peer in a hierarchical naming space"),
         ### cross refs
         'site_ids': Parameter([int], "List of sites for which this peer is authoritative"),
         'person_ids': Parameter([int], "List of users for which this peer is authoritative"),
         'key_ids': Parameter([int], "List of keys for which this peer is authoritative"),
         'node_ids': Parameter([int], "List of nodes for which this peer is authoritative"),
         'slice_ids': Parameter([int], "List of slices for which this peer is authoritative"),
         ### cross refs
         'site_ids': Parameter([int], "List of sites for which this peer is authoritative"),
         'person_ids': Parameter([int], "List of users for which this peer is authoritative"),
         'key_ids': Parameter([int], "List of keys for which this peer is authoritative"),
         'node_ids': Parameter([int], "List of nodes for which this peer is authoritative"),
         'slice_ids': Parameter([int], "List of slices for which this peer is authoritative"),
-       }
+        }
 
     def validate_peername(self, peername):
         if not len(peername):
 
     def validate_peername(self, peername):
         if not len(peername):
@@ -56,22 +60,24 @@ class Peer(Row):
         return peername
 
     def validate_peer_url(self, url):
         return peername
 
     def validate_peer_url(self, url):
-       """
-       Validate URL. Must be HTTPS.
-       """
+        """
+        Validate URL. Must be HTTPS.
+        """
 
         (scheme, netloc, path, params, query, fragment) = urlparse(url)
         if scheme != "https":
             raise PLCInvalidArgument, "Peer URL scheme must be https"
 
         (scheme, netloc, path, params, query, fragment) = urlparse(url)
         if scheme != "https":
             raise PLCInvalidArgument, "Peer URL scheme must be https"
+        if path[-1] != '/':
+            raise PLCInvalidArgument, "Peer URL should end with /"
 
 
-       return url
+        return url
 
     def delete(self, commit = True):
 
     def delete(self, commit = True):
-       """
-       Deletes this peer and all related entities.
-       """
+        """
+        Deletes this peer and all related entities.
+        """
 
 
-       assert 'peer_id' in self
+        assert 'peer_id' in self
 
         # Remove all related entities
         for obj in \
 
         # Remove all related entities
         for obj in \
@@ -84,8 +90,8 @@ class Peer(Row):
             obj.delete(commit = False)
 
         # Mark as deleted
             obj.delete(commit = False)
 
         # Mark as deleted
-       self['deleted'] = True
-       self.sync(commit)
+        self['deleted'] = True
+        self.sync(commit)
 
     def add_site(self, site, peer_site_id, commit = True):
         """
 
     def add_site(self, site, peer_site_id, commit = True):
         """
@@ -99,6 +105,14 @@ class Peer(Row):
              'peer_site_id': peer_site_id},
             commit = commit)
 
              'peer_site_id': peer_site_id},
             commit = commit)
 
+    def remove_site(self, site, commit = True):
+        """
+        Unassociate a site with this peer.
+        """
+
+        remove = Row.remove_object(Site, 'peer_site')
+        remove(self, site, commit)
+
     def add_person(self, person, peer_person_id, commit = True):
         """
         Associate a local user entry with this peer.
     def add_person(self, person, peer_person_id, commit = True):
         """
         Associate a local user entry with this peer.
@@ -111,6 +125,14 @@ class Peer(Row):
              'peer_person_id': peer_person_id},
             commit = commit)
 
              'peer_person_id': peer_person_id},
             commit = commit)
 
+    def remove_person(self, person, commit = True):
+        """
+        Unassociate a site with this peer.
+        """
+
+        remove = Row.remove_object(Person, 'peer_person')
+        remove(self, person, commit)
+
     def add_key(self, key, peer_key_id, commit = True):
         """
         Associate a local key entry with this peer.
     def add_key(self, key, peer_key_id, commit = True):
         """
         Associate a local key entry with this peer.
@@ -123,6 +145,14 @@ class Peer(Row):
              'peer_key_id': peer_key_id},
             commit = commit)
 
              'peer_key_id': peer_key_id},
             commit = commit)
 
+    def remove_key(self, key, commit = True):
+        """
+        Unassociate a key with this peer.
+        """
+
+        remove = Row.remove_object(Key, 'peer_key')
+        remove(self, key, commit)
+
     def add_node(self, node, peer_node_id, commit = True):
         """
         Associate a local node entry with this peer.
     def add_node(self, node, peer_node_id, commit = True):
         """
         Associate a local node entry with this peer.
@@ -135,6 +165,34 @@ class Peer(Row):
              'peer_node_id': peer_node_id},
             commit = commit)
 
              'peer_node_id': peer_node_id},
             commit = commit)
 
+        sites = Sites(self.api, node['site_id'], ['login_base'])
+        site = sites[0]
+        login_base = site['login_base']
+        try:
+            # attempt to manually update the 'hrn' tag with the remote prefix
+            hrn_root = self['hrn_root']
+            hrn = hostname_to_hrn(hrn_root, login_base, node['hostname'])
+            tags = {'hrn': hrn}
+            Node(self.api, node).update_tags(tags)
+        except:
+            logger.exception("Could not find out hrn on hostname=%s"%node['hostname'])
+
+    def remove_node(self, node, commit = True):
+        """
+        Unassociate a node with this peer.
+        """
+
+        remove = Row.remove_object(Node, 'peer_node')
+        remove(self, node, commit)
+        # attempt to manually update the 'hrn' tag now that the node is local
+        root_auth = self.api.config.PLC_HRN_ROOT
+        sites = Sites(self.api, node['site_id'], ['login_base'])
+        site = sites[0]
+        login_base = site['login_base']
+        hrn = hostname_to_hrn(root_auth, login_base, node['hostname'])
+        tags = {'hrn': hrn}
+        Node(self.api, node).update_tags(tags)
+
     def add_slice(self, slice, peer_slice_id, commit = True):
         """
         Associate a local slice entry with this peer.
     def add_slice(self, slice, peer_slice_id, commit = True):
         """
         Associate a local slice entry with this peer.
@@ -147,6 +205,14 @@ class Peer(Row):
              'peer_slice_id': peer_slice_id},
             commit = commit)
 
              'peer_slice_id': peer_slice_id},
             commit = commit)
 
+    def remove_slice(self, slice, commit = True):
+        """
+        Unassociate a slice with this peer.
+        """
+
+        remove = Row.remove_object(Slice, 'peer_slice')
+        remove(self, slice, commit)
+
     def connect(self, **kwds):
         """
         Connect to this peer via XML-RPC.
     def connect(self, **kwds):
         """
         Connect to this peer via XML-RPC.
@@ -211,14 +277,14 @@ class Peer(Row):
             raise AttributeError, "type object 'Peer' has no attribute '%s'" % attr
 
 class Peers (Table):
             raise AttributeError, "type object 'Peer' has no attribute '%s'" % attr
 
 class Peers (Table):
-    """ 
+    """
     Maps to the peers table in the database
     """
     Maps to the peers table in the database
     """
-    
+
     def __init__ (self, api, peer_filter = None, columns = None):
         Table.__init__(self, api, Peer, columns)
 
     def __init__ (self, api, peer_filter = None, columns = None):
         Table.__init__(self, api, Peer, columns)
 
-       sql = "SELECT %s FROM view_peers WHERE deleted IS False" % \
+        sql = "SELECT %s FROM view_peers WHERE deleted IS False" % \
               ", ".join(self.columns)
 
         if peer_filter is not None:
               ", ".join(self.columns)
 
         if peer_filter is not None:
@@ -231,5 +297,13 @@ class Peers (Table):
             elif isinstance(peer_filter, dict):
                 peer_filter = Filter(Peer.fields, peer_filter)
                 sql += " AND (%s) %s" % peer_filter.sql(api, "AND")
             elif isinstance(peer_filter, dict):
                 peer_filter = Filter(Peer.fields, peer_filter)
                 sql += " AND (%s) %s" % peer_filter.sql(api, "AND")
+            elif isinstance(peer_filter, (int, long)):
+                peer_filter = Filter(Peer.fields, {'peer_id': peer_filter})
+                sql += " AND (%s) %s" % peer_filter.sql(api, "AND")
+            elif isinstance(peer_filter, StringTypes):
+                peer_filter = Filter(Peer.fields, {'peername': peer_filter})
+                sql += " AND (%s) %s" % peer_filter.sql(api, "AND")
+            else:
+                raise PLCInvalidArgument, "Wrong peer filter %r"%peer_filter
 
 
-       self.selectall(sql)
+        self.selectall(sql)