summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorDouglas Bagnall <douglas.bagnall@catalyst.net.nz>2015-06-10 16:42:37 +1200
committerAndrew Bartlett <abartlet@samba.org>2015-06-12 06:57:13 +0200
commitb0e6a7436233c39f1ebf1a40e4c6cc495ed926f9 (patch)
tree2505791972c1b64cc9483164452bd6d86c81ad85 /python
parent8d6f256f381abf1d932bfecb6542590eae9a5f32 (diff)
downloadsamba-b0e6a7436233c39f1ebf1a40e4c6cc495ed926f9.tar.gz
KCC: split kcc_utils into samba.kcc.{kcc_utils,graph}
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>
Diffstat (limited to 'python')
-rw-r--r--python/samba/kcc/__init__.py8
-rw-r--r--python/samba/kcc/graph.py170
-rw-r--r--python/samba/kcc/kcc_utils.py (renamed from python/samba/kcc_utils.py)152
3 files changed, 184 insertions, 146 deletions
diff --git a/python/samba/kcc/__init__.py b/python/samba/kcc/__init__.py
index 31f7c34ca4f..897baa6b7e7 100644
--- a/python/samba/kcc/__init__.py
+++ b/python/samba/kcc/__init__.py
@@ -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
index 00000000000..66fe45ae23d
--- /dev/null
+++ b/python/samba/kcc/graph.py
@@ -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
diff --git a/python/samba/kcc_utils.py b/python/samba/kcc/kcc_utils.py
index 2e0be7f287c..4325510209c 100644
--- a/python/samba/kcc_utils.py
+++ b/python/samba/kcc/kcc_utils.py
@@ -23,14 +23,14 @@
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
##################################################