diff options
author | Douglas Bagnall <douglas.bagnall@catalyst.net.nz> | 2015-06-10 16:42:37 +1200 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2015-06-12 06:57:13 +0200 |
commit | b0e6a7436233c39f1ebf1a40e4c6cc495ed926f9 (patch) | |
tree | 2505791972c1b64cc9483164452bd6d86c81ad85 /python | |
parent | 8d6f256f381abf1d932bfecb6542590eae9a5f32 (diff) | |
download | samba-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__.py | 8 | ||||
-rw-r--r-- | python/samba/kcc/graph.py | 170 | ||||
-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 ################################################## |