1
0
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:
Douglas Bagnall
2015-06-10 16:42:37 +12:00
committed by Andrew Bartlett
parent 8d6f256f38
commit b0e6a74362
4 changed files with 189 additions and 150 deletions

View 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

170
python/samba/kcc/graph.py Normal file
View 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

View File

@ -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
##################################################

View File

@ -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.