KCC: split kcc_utils into samba.kcc.{kcc_utils,graph}
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>
Wed, 10 Jun 2015 04:42:37 +0000 (16:42 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Fri, 12 Jun 2015 04:57:13 +0000 (06:57 +0200)
graph.py has the intersite graph stuff.
kcc_utils does intrasite, namespace, &cetera.

The wildcard imports are tidied up, so samba_kcc imports unix2nttime
directly rather than letting it fall out of kcc_utils.

Intersite graph functions samba/kcc/__init__.py are also shifted into
graph.py.

Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Garming Sam <garming@catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
python/samba/kcc/__init__.py
python/samba/kcc/graph.py [new file with mode: 0644]
python/samba/kcc/kcc_utils.py [moved from python/samba/kcc_utils.py with 94% similarity]
source4/scripting/bin/samba_kcc

index 31f7c34ca4ff8a6039954089509bfb1bd24aa4ab..897baa6b7e78057eaa79d7543d0518b8c33025c9 100644 (file)
@@ -53,10 +53,16 @@ from samba import (
 from samba.auth import system_session
 from samba.samdb import SamDB
 from samba.dcerpc import drsuapi
-from samba.kcc_utils import *
+
+from samba.kcc.kcc_utils import Site, Partition, Transport, SiteLink
+from samba.kcc.kcc_utils import NCReplica, NCType, nctype_lut, GraphNode
+from samba.kcc.kcc_utils import RepsFromTo, KCCError, KCCFailedObject
+from samba.kcc.kcc_utils import convert_schedule_to_repltimes
 from samba.kcc.graph_utils import verify_and_dot
 from samba import ldif_utils
 
+from samba.kcc.graph import Vertex
+
 from samba.kcc.debug import DEBUG, DEBUG_FN, logger
 from samba.kcc import debug
 
diff --git a/python/samba/kcc/graph.py b/python/samba/kcc/graph.py
new file mode 100644 (file)
index 0000000..66fe45a
--- /dev/null
@@ -0,0 +1,170 @@
+# Graph functions used by KCC intersite
+#
+# Copyright (C) Dave Craft 2011
+# Copyright (C) Andrew Bartlett 2015
+#
+# Andrew Bartlett's alleged work performed by his underlings Douglas
+# Bagnall and Garming Sam.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import itertools
+import heapq
+
+from samba.kcc.graph_utils import write_dot_file, verify_and_dot, verify_graph
+from samba.ndr import ndr_pack
+from samba.dcerpc import misc
+
+from samba.kcc.debug import DEBUG, DEBUG_FN
+
+from samba.kcc.kcc_utils import MAX_DWORD
+from samba.kcc.kcc_utils import ReplInfo, combine_repl_info, total_schedule
+from samba.kcc.kcc_utils import convert_schedule_to_repltimes
+
+
+class VertexColor(object):
+    (red, black, white, unknown) = range(0, 4)
+
+
+class Vertex(object):
+    """Class encapsulation of a Site Vertex in the
+    intersite topology replication algorithm
+    """
+    def __init__(self, site, part):
+        self.site = site
+        self.part = part
+        self.color = VertexColor.unknown
+        self.edges = []
+        self.accept_red_red = []
+        self.accept_black = []
+        self.repl_info = ReplInfo()
+        self.root = self
+        self.guid = None
+        self.component_id = self
+        self.demoted = False
+        self.options = 0
+        self.interval = 0
+
+    def color_vertex(self):
+        """Color each vertex to indicate which kind of NC
+        replica it contains
+        """
+        # IF s contains one or more DCs with full replicas of the
+        # NC cr!nCName
+        #    SET v.Color to COLOR.RED
+        # ELSEIF s contains one or more partial replicas of the NC
+        #    SET v.Color to COLOR.BLACK
+        #ELSE
+        #    SET v.Color to COLOR.WHITE
+
+        # set to minimum (no replica)
+        self.color = VertexColor.white
+
+        for dnstr, dsa in self.site.dsa_table.items():
+            rep = dsa.get_current_replica(self.part.nc_dnstr)
+            if rep is None:
+                continue
+
+            # We have a full replica which is the largest
+            # value so exit
+            if not rep.is_partial():
+                self.color = VertexColor.red
+                break
+            else:
+                self.color = VertexColor.black
+
+    def is_red(self):
+        assert(self.color != VertexColor.unknown)
+        return (self.color == VertexColor.red)
+
+    def is_black(self):
+        assert(self.color != VertexColor.unknown)
+        return (self.color == VertexColor.black)
+
+    def is_white(self):
+        assert(self.color != VertexColor.unknown)
+        return (self.color == VertexColor.white)
+
+
+class IntersiteGraph(object):
+    """Graph for representing the intersite"""
+    def __init__(self):
+        self.vertices = set()
+        self.edges = set()
+        self.edge_set = set()
+        # All vertices that are endpoints of edges
+        self.connected_vertices = None
+
+
+class MultiEdgeSet(object):
+    """Defines a multi edge set"""
+    def __init__(self):
+        self.guid = 0  # objectGuid siteLinkBridge
+        self.edges = []
+
+
+class MultiEdge(object):
+    def __init__(self):
+        self.site_link = None  # object siteLink
+        self.vertices = []
+        self.con_type = None  # interSiteTransport GUID
+        self.repl_info = ReplInfo()
+        self.directed = True
+
+
+class InternalEdge(object):
+    def __init__(self, v1, v2, redred, repl, eType, site_link):
+        self.v1 = v1
+        self.v2 = v2
+        self.red_red = redred
+        self.repl_info = repl
+        self.e_type = eType
+        self.site_link = site_link
+
+    def __eq__(self, other):
+        return not self < other and not other < self
+
+    def __ne__(self, other):
+        return self < other or other < self
+
+    def __gt__(self, other):
+        return other < self
+
+    def __ge__(self, other):
+        return not self < other
+
+    def __le__(self, other):
+        return not other < self
+
+    # TODO compare options and interval
+    def __lt__(self, other):
+        if self.red_red != other.red_red:
+            return self.red_red
+
+        if self.repl_info.cost != other.repl_info.cost:
+            return self.repl_info.cost < other.repl_info.cost
+
+        self_time = total_schedule(self.repl_info.schedule)
+        other_time = total_schedule(other.repl_info.schedule)
+        if self_time != other_time:
+            return self_time > other_time
+
+        #XXX guid comparison using ndr_pack
+        if self.v1.guid != other.v1.guid:
+            return self.v1.ndrpacked_guid < other.v1.ndrpacked_guid
+
+        if self.v2.guid != other.v2.guid:
+            return self.v2.ndrpacked_guid < other.v2.ndrpacked_guid
+
+        return self.e_type < other.e_type
similarity index 94%
rename from python/samba/kcc_utils.py
rename to python/samba/kcc/kcc_utils.py
index 2e0be7f287c025b945bd0030d908a7b3fe2d3ab2..4325510209cb2d62b16f6083a46c4e737a16f387 100644 (file)
 import ldb
 import uuid
 
-from samba import dsdb, unix2nttime
+from samba import dsdb
 from samba.dcerpc import (
     drsblobs,
     drsuapi,
     misc,
     )
 from samba.common import dsdb_Dn
-from samba.ndr import (ndr_unpack, ndr_pack)
+from samba.ndr import ndr_unpack, ndr_pack
 
 
 class KCCError(Exception):
@@ -1363,7 +1363,7 @@ class Site(object):
     """An individual site object discovered thru the configuration
     naming context.  Contains all DSAs that exist within the site
     """
-    def __init__(self, site_dnstr, unix_now):
+    def __init__(self, site_dnstr, nt_now):
         self.site_dnstr = site_dnstr
         self.site_guid = None
         self.site_options = 0
@@ -1371,7 +1371,7 @@ class Site(object):
         self.site_topo_failover = 0  # appears to be in minutes
         self.dsa_table = {}
         self.rw_dsa_table = {}
-        self.unix_now = unix_now
+        self.nt_now = nt_now
 
     def load_site(self, samdb):
         """Loads the NTDS Site Settions options attribute for the site
@@ -1492,7 +1492,6 @@ class Site(object):
         D_sort = sorted(self.rw_dsa_table.values(), cmp=sort_dsa_by_guid)
 
         # double word number of 100 nanosecond intervals since 1600s
-        ntnow = unix2nttime(self.unix_now)
 
         # Let f be the duration o!interSiteTopologyFailover seconds, or 2 hours
         # if o!interSiteTopologyFailover is 0 or has no value.
@@ -1555,7 +1554,7 @@ class Site(object):
             #XXX doc says current time < c.timeLastSyncSuccess - f
             # which is true only if f is negative or clocks are wrong.
             # f is not negative in the default case (2 hours).
-            elif ntnow - cursor.last_sync_success > f:
+            elif self.nt_now - cursor.last_sync_success > f:
                 i_idx = 0
                 t_time = 0
             else:
@@ -1568,7 +1567,7 @@ class Site(object):
         #     Let t = the current time.
         else:
             i_idx = D_sort.index(mydsa)
-            t_time = ntnow
+            t_time = self.nt_now
 
         # Compute a function that maintains the current ISTG if
         # it is alive, cycles through other candidates if not.
@@ -1578,7 +1577,7 @@ class Site(object):
         #
         # Note: We don't want to divide by zero here so they must
         #       have meant "f" instead of "o!interSiteTopologyFailover"
-        k_idx = (i_idx + ((ntnow - t_time) / f)) % len(D_sort)
+        k_idx = (i_idx + ((self.nt_now - t_time) / f)) % len(D_sort)
 
         # The local writable DC acts as an ISTG for its site if and
         # only if dk is the nTDSDSA object for the local DC. If the
@@ -2103,96 +2102,6 @@ class KCCFailedObject(object):
         self.dns_name = dns_name
 
 
-class VertexColor(object):
-    (red, black, white, unknown) = range(0, 4)
-
-
-class Vertex(object):
-    """Class encapsulation of a Site Vertex in the
-    intersite topology replication algorithm
-    """
-    def __init__(self, site, part):
-        self.site = site
-        self.part = part
-        self.color = VertexColor.unknown
-        self.edges = []
-        self.accept_red_red = []
-        self.accept_black = []
-        self.repl_info = ReplInfo()
-        self.root = self
-        self.guid = None
-        self.component_id = self
-        self.demoted = False
-        self.options = 0
-        self.interval = 0
-
-    def color_vertex(self):
-        """Color each vertex to indicate which kind of NC
-        replica it contains
-        """
-        # IF s contains one or more DCs with full replicas of the
-        # NC cr!nCName
-        #    SET v.Color to COLOR.RED
-        # ELSEIF s contains one or more partial replicas of the NC
-        #    SET v.Color to COLOR.BLACK
-        #ELSE
-        #    SET v.Color to COLOR.WHITE
-
-        # set to minimum (no replica)
-        self.color = VertexColor.white
-
-        for dnstr, dsa in self.site.dsa_table.items():
-            rep = dsa.get_current_replica(self.part.nc_dnstr)
-            if rep is None:
-                continue
-
-            # We have a full replica which is the largest
-            # value so exit
-            if not rep.is_partial():
-                self.color = VertexColor.red
-                break
-            else:
-                self.color = VertexColor.black
-
-    def is_red(self):
-        assert(self.color != VertexColor.unknown)
-        return (self.color == VertexColor.red)
-
-    def is_black(self):
-        assert(self.color != VertexColor.unknown)
-        return (self.color == VertexColor.black)
-
-    def is_white(self):
-        assert(self.color != VertexColor.unknown)
-        return (self.color == VertexColor.white)
-
-
-class IntersiteGraph(object):
-    """Graph for representing the intersite"""
-    def __init__(self):
-        self.vertices = set()
-        self.edges = set()
-        self.edge_set = set()
-        # All vertices that are endpoints of edges
-        self.connected_vertices = None
-
-
-class MultiEdgeSet(object):
-    """Defines a multi edge set"""
-    def __init__(self):
-        self.guid = 0  # objectGuid siteLinkBridge
-        self.edges = []
-
-
-class MultiEdge(object):
-    def __init__(self):
-        self.site_link = None  # object siteLink
-        self.vertices = []
-        self.con_type = None  # interSiteTransport GUID
-        self.repl_info = ReplInfo()
-        self.directed = True
-
-
 class ReplInfo(object):
     def __init__(self):
         self.cost = 0
@@ -2201,53 +2110,6 @@ class ReplInfo(object):
         self.schedule = None
 
 
-class InternalEdge(object):
-    def __init__(self, v1, v2, redred, repl, eType, site_link):
-        self.v1 = v1
-        self.v2 = v2
-        self.red_red = redred
-        self.repl_info = repl
-        self.e_type = eType
-        self.site_link = site_link
-
-    def __eq__(self, other):
-        return not self < other and not other < self
-
-    def __ne__(self, other):
-        return self < other or other < self
-
-    def __gt__(self, other):
-        return other < self
-
-    def __ge__(self, other):
-        return not self < other
-
-    def __le__(self, other):
-        return not other < self
-
-    # TODO compare options and interval
-    def __lt__(self, other):
-        if self.red_red != other.red_red:
-            return self.red_red
-
-        if self.repl_info.cost != other.repl_info.cost:
-            return self.repl_info.cost < other.repl_info.cost
-
-        self_time = total_schedule(self.repl_info.schedule)
-        other_time = total_schedule(other.repl_info.schedule)
-        if self_time != other_time:
-            return self_time > other_time
-
-        #XXX guid comparison using ndr_pack
-        if self.v1.guid != other.v1.guid:
-            return self.v1.ndrpacked_guid < other.v1.ndrpacked_guid
-
-        if self.v2.guid != other.v2.guid:
-            return self.v2.ndrpacked_guid < other.v2.ndrpacked_guid
-
-        return self.e_type < other.e_type
-
-
 ##################################################
 # Global Functions and Variables
 ##################################################
index a7a1953c89346100ecd65f5d7f401ccb9bd460fd..4abec6f3803efdb1063426b3fb06fe8b362f3d3e 100755 (executable)
@@ -51,14 +51,15 @@ from samba import (
     ldb,
     dsdb,
     drs_utils,
-    nttime2unix)
+    nttime2unix,
+    unix2nttime)
 from samba.auth import system_session
 from samba.samdb import SamDB
 from samba.dcerpc import drsuapi
-from samba.kcc_utils import *
-from samba.kcc.debug import *
 from samba import ldif_utils
-
+from samba.kcc.kcc_utils import *
+from samba.kcc.graph import *
+from samba.kcc.debug import *
 
 class KCC(object):
     """The Knowledge Consistency Checker class.