mirror of
https://github.com/samba-team/samba.git
synced 2025-08-03 04:22:09 +03:00
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>
This commit is contained in:
committed by
Andrew Bartlett
parent
8d6f256f38
commit
b0e6a74362
@ -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
|
||||
|
||||
|
170
python/samba/kcc/graph.py
Normal file
170
python/samba/kcc/graph.py
Normal file
@ -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
|
@ -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
|
||||
##################################################
|
@ -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.
|
||||
|
Reference in New Issue
Block a user