windows-nt/Source/XPSP1/NT/ds/netapi/svcimgs/ntrepl/mkdsx/mkhubbchtop.cmd

472 lines
16 KiB
Batchfile
Raw Normal View History

2020-09-26 03:20:57 -05:00
@rem = '
@goto endofperl
';
#
# Created: 8/2000 David A. Orbits
# Revised: 9/4/2000 Add $hourslot to offset calc.
#
$USAGE = "
Usage: $0 datafile
mkhubbchtop makes a hub and spoke topology data file for input to mkdsx.cmd.
An input file specifies the replication schedule parameters to use, the list
of hub servers and the list of branch servers. Using this data a connection
data file is created containing records that describe each connection object
to create. See the help info for mkdsx for info on the format of this file.
Input command file contains three types of data records, parameters, hub server
records, and branch server records.
/dc <dcname> # the DC to bind to when mkdsx is run on the result file.
# This should be one of the well connected hub DCs.
/auto_cleanup # automatically delete all old connection objects under
# each branch or hub site\\server before the first new
# connection is created. See mkdsx.cmd for details.
/debug # this is propagated to the connection data file and will
# cause mkdsx to process the file but suppress any writes
# to the DC.
/avglinkbw nnn # An estimate of the average link bandwidth in KB/Sec units
# available for replication. E.g. If the raw link speed is
# 64k bits/sec and you estimate that only 50% of this is
# available for use then avglinkbw = 0.5 * (64kb / 8 bits/byte).
# From this and the number of hubs, number of branches and the
# replication interval we calculate the maximum bandwidth-limited
# data payload that can be shipped from the branch to the hub. If
# this is exceeded replication will run over into the next scheduled hour.
/repinterval nnn # the replication interval in hours between the Hub and branch
/schedmask # file with 7x24 string of ascii hex digit pairs to turn off the schedule
/schedoverride # file with 7x24 string of ascii hex digit pairs to turn on the schedule
/hubredundancy nnn # the number of redundant connections into the hub machines from the branches
/bchredundancy nnn # the number of redundant connections into the branch machines from the hubs
# 1 means no redundancy, only create a single connection.
# 0 means create no connections for either the hub or branch side.
/output <filename for connection output> # default is mkdsx.dat
/rem remark text that will go to the output file as a comment.
hub: site\\server # the site location and server computer name of a hub server
bch: site\\server # the site location and server computer name of a branch server
There are no optional paramenters and no embedded blanks are allowed within parameters.
Error handling -
Error messages are written to standard out. The entire input file is processed
but if any errors are detected no connection data file is produced.
Connection object creation in the DS -
Since replication connectivity to the branch machines may not be present all
connection objects hosted by a branch server are created on that branch server.
But since the hub server topology is expected to be in place and they are assumed
to be well connected, all the connection objects hosted by the hub servers are
created on the single hub server specified by the DC name in the \"/dc <dcname>\"
parameter. Once a connection object is present on both the hub server and
a branch server of a give hub-branch pair, the DS will replicate these connection
objects across the link. This is necessary for FRS to replicate since both
ends of the link must have a given connection object in its local DC for FRS to
replicate between the two machines. If a given branch machine is not accessible
when mkdsx is run to create the connection then mkdsx will insert the create
command into the redo file so you can retry the create later.
Schedule parameter and load sharing -
The schedule parameter provides a means for setting a repeating replication schedule.
Connection schedules are an attribute associated with each NTDS-Connection object
in the DC. They contain a 7x24 array of bytes, one byte for each hour in a
7 day week (UTC time zone). You can use the schedule paramter to spread the
replication load among multiple inbound source servers.
The paramter is of the form s-iii-ccc-ppp where the i, c and p fields are decimal
numbers. The i field describes the desired interval (in hours) between inbound
replication events on the host server. The c field describes the number of
connections objects present that will import data to this host server. Or, put
another way, it is the number of other servers that will be providing data to
this server. The p field is offset parameter that ranges from 0 to c-1. It
is used to stagger the schedule relative to the schedules on the other connection
objects.
For example, lets assume you have two connection objects that refer to two servers
SA and SB which will supply replication updates to the host server. We would
like to arrange the schedules of these two connection objects so that our host
server is updated every 4 hours. To do this, the schedule parameter for the
connection object referring to server SA would be 's-4-2-0' and the parameter
for the connection to server SB is 's-4-2-1'.
Source H o u r
Server 0 4 8 12 16 20
SA s-4-2-0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ...
SB s-4-2-1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 ...
Repl Events ^ ^ ^ ^ ^ ^
With these two connection objects the net interval between replication events
will be every 4 hours. The schedule for server B is offset by 4 hours as a result
of the p field being 1. Both of the above schedule patterns continue to repeat
over the course of the 7x24 array comprising the schedule attribute.
As a second example, assume you want to replicate every 2 hours and you establish
connections with three other servers to provide the data. The schedule paramter
values and the schedule array are then:
Source H o u r
Server 0 4 8 12 16 20
SA s-2-3-0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 ...
SB s-2-3-1 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 ...
SC s-2-3-2 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 ...
Repl Events ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
Schedmask and Schedoverride parameters -
Schedmask and schedoverride data are formatted as a pair of ascii hex digits
for each byte in the 7x24 schedule array with byte 0 corresponding to day 1 hour 0.
For each connection the 7x24 result schedule is formed using the schedule parameter (see
below) and then the schedule mask is applied (each bit set in the schedule mask
clears the corresponding bit in the result schedule). Finally the schedule override
is applied with a logical OR of the override schedule to the result schedule.
Schedmask and schedoverride can have embedded whitespace chars (including cr/lf)
which are deleted or be a single string of 336 (7*24*2) hex digits. For example:
FF0000000000 000000000000 000000000000 000000000000
FF0000000000 FFFFFFFFFF00 000000000000 000000000000
FF0000000000 FFFFFFFFFF00 000000000000 000000000000
FF0000000000 FFFFFFFFFF00 000000000000 000000000000
FF0000000000 FFFFFFFFFF00 000000000000 000000000000
FF0000000000 000000000000 000000000000 000000000000
FF0000000000 000000000000 000000000000 000000000000
Sample Input File -
#
# A sample input file might look as follows:
#
/dc ntdev-dc-01
/repinterval 4 # replicate every 4 hours
/hubredundancy 2 # Create connection objects in 2 different hubs that pull data from the same branch.
/bchredundancy 2 # create 2 connection objects in a branch that pull data from different hub machines.
/auto_cleanup # delete any old connections before the first new connection is created.
#
# list of hub servers for a domain zona2
#
hub: Credit1\C0ZONA21
hub: Credit2\C0ZONA22
hub: Credit3\C0ZONA26
#
# list of branches for zona2 domain
#
bch: 0100Site\C0010000
bch: 0200Site\C0020200
bch: 0270Site\C0027000
bch: 0340Site\C0034000
#End of file
";
die $USAGE unless @ARGV;
printf("\n\n");
$linenumber = 0;
$InFile = "";
$bx = 0;
$hx = 0;
$remx = 0;
$cmdtab{"/dc"} = 1;
$cmdtab{"hub:"} = 1;
$cmdtab{"bch:"} = 1;
$cmdtab{"/debug"} = 0;
$cmdtab{"/output"} = 1;
$cmdtab{"/repinterval"} = 1;
$cmdtab{"/schedmask"} = 1;
$cmdtab{"/schedoverride"} = 1;
$cmdtab{"/auto_cleanup"} = 0;
$cmdtab{"/hubredundancy"} = 1;
$cmdtab{"/bchredundancy"} = 1;
$cmdtab{"/avglinkbw"} = 1;
$dccmd = "";
$repinterval = 1;
$hubredundancy = 1;
$bchredundancy = 1;
$outfile = "mkdsx.dat";
$errorcount = 0;
$avglinkbw = 0;
while (<>) {
if ($InFile ne $ARGV) {
$InFile = $ARGV;
printf("Processing file %s \n\n", $InFile);
$infilelist = $infilelist . " " . $InFile;
$linenumber = 0;
}
$linenumber++;
chop;
($func, @a) = split;
if (($func eq "") || ($func =~ m/^#/)) {next;}
#
# /rem <text>
#
if ($func =~ m/\/rem/i) {
$rem[$remx] = $_;
$rem[$remx] =~ s/\/rem//i;
$remx += 1;
next;
}
#
# check for valid command and for missing or extraneous parameters.
#
$func = lc($func);
if (!exists($cmdtab{$func})) {
printf("Line %d: Error: %s unrecognized command.\n%s\n\n", $linenumber, $func, $_);
$errorcount += 1;
next;
}
$numargs = $cmdtab{$func};
if (($a[$numargs] ne "") && !($a[$numargs] =~ m/^#/)) {
printf("Line %d: Error: %s has extraneous or missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
$errorcount += 1;
next;
}
$i = $numargs;
while ($i-- > 0) {
if (($a[i] eq "") || ($a[$i] =~ m/^#/)) {
printf("Line %d: Error: %s missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
$errorcount += 1;
goto NEXT_CMD;
}
}
#
# /dc <dcname>
# /auto_cleanup
# /debug
# /schedmask
# /schedoverride
#
if (($func =~ m/\/dc/i) ||
($func =~ m/\/debug/i) ||
($func =~ m/\/schedmask/i) ||
($func =~ m/\/schedoverride/i) ||
($func =~ m/\/auto_cleanup/i)) {$prop_cmd[$prop++] = $_; next; }
#
# /output <file>
#
if ($func =~ m/\/output/i) {$outfile = $a[0]; next; }
#
# /repinterval nnn
#
if (($func =~ m/\/repinterval/i) && ($a[0] <= 0)) {
printf("Line %d: Error: %s parameter is <= 0 \n%s\n\n", $linenumber, $func, $_);
$errorcount += 1;
next;
}
#
# /avglinkbw nnn
# /hubredundancy nnn
# /bchredundancy nnn
#
if (($func =~ m/\/hubredundancy|\/bchredundancy|\/avglinkbw/i) && ($a[0] < 0)) {
printf("Line %d: Error: %s parameter is < 0 \n%s\n\n", $linenumber, $func, $_);
$errorcount += 1;
next;
}
if ($func =~ m/\/repinterval/i) {$repinterval = $a[0]; next;}
if ($func =~ m/\/hubredundancy/i) {$hubredundancy = $a[0]; next;}
if ($func =~ m/\/bchredundancy/i) {$bchredundancy = $a[0]; next;}
if ($func =~ m/\/avglinkbw/i) {$avglinkbw = $a[0]; next;}
#
# hub: site\\server
# bch: site\\server
#
if (m/hub:|bch:/i) {
$sitesrv = $a[0];
($site, $srv) = split(/\\/, $sitesrv);
if (($site eq "") || ($srv eq "")) {
printf("Line %d: Error: Site or Server is null - skipping\n%s\n\n", $linenumber, $_);
$errorcount += 1;
next;
}
if (m/hub:/i) {$hubs[$hx++] = $sitesrv; next;}
if (m/bch:/i) {$bchs[$bx++] = $sitesrv; next;}
}
NEXT_CMD:
}
#
# We have all the data. Generate the topology.
#
$nbch = $bx;
$nhub = $hx;
if ($nbch == 0) {
printf("Error: No branches found in input file.\n");
$errorcount += 1;
}
if ($nhub == 0) {
printf("Error: No hub servers found in input file.\n");
$errorcount += 1;
}
printf("Number hub servers: %d\n", $nhub);
printf("Number branch servers: %d\n", $nbch);
printf("Replication Interval: %d hours\n", $repinterval);
printf("Hub redundancy: %d\n", $hubredundancy);
printf("Branch redundancy: %d\n", $bchredundancy);
if ($nbch * $nhub * $repinterval * $avglinkbw > 0) {
printf("Average available link bandwidth: %d KB/Sec\n", $avglinkbw);
printf("Estimated data payload max from each branch: %d KB\n", ($avglinkbw * 3600) / (($nbch / $nhub) / $repinterval));
printf(" The total amount of data replicated from each branch \n");
printf(" during a replication cycle should be less than this number.\n");
printf(" Otherwise replication from the branches scheduled in one hour\n may run over into the next hour.\n");
}
#
# The connection redundancy can't be greater than the number of hub servers.
#
if ($nhub < $hubredundancy) {
printf("Error: Number of hubs (%d) is less than the requested hub connection redundancy (%d)\n",
$nhub, $hubredundancy);
$errorcount += 1;
}
if ($nhub < $bchredundancy) {
printf("Error: Number of hubs (%d) is less than the requested branch connection redundancy (%d)\n",
$nhub, $bchredundancy);
$errorcount += 1;
}
if ($errorcount > 0) {
printf("%d error(s) were found in the input file. No topology generated\n", $errorcount);
exit $errorcount;
}
printf("\nWriting new topology to %s\n", $outfile);
$DAT = ">$outfile";
open DAT or die "Can't write to $outfile. No topology generated.\n";
for ($i = 0; $i < $remx; $i++) {printf DAT ("# %s\n", $rem[$i]);}
$time = scalar localtime;
printf DAT ("#Time generated: %s\n", $time);
printf DAT ("#Input files: %s\n", $infilelist);
printf DAT ("#Number hub servers: %d\n", $nhub);
printf DAT ("#Number branch servers: %d\n", $nbch);
printf DAT ("#Replication Interval: %d hours\n", $repinterval);
printf DAT ("#Hub redundancy: %d\n", $hubredundancy);
printf DAT ("#Branch redundancy: %d\n", $bchredundancy);
printf DAT ("#\n");
#
# output any propagated commands.
#
while ($prop-- > 0) {
printf DAT ("%s\n", $prop_cmd[$prop]);
}
printf DAT ("#\n");
$bchleft = $nbch;
$bx = 0;
#
# Process until all branches have been consumed.
#
while ($bx < $nbch) {
#
# For each hour slot in the replication interval assign a hub server to perform
# replication with a branch.
#
for ($hourslot=0; $hourslot < $repinterval; $hourslot++) {
#
# For each hub server in the list assign it a branch to replicate with.
#
for ($hx=0; $hx < $nhub; $hx++) {
#
# get the next branch in the list.
#
$bchname = $bchs[$bx];
printf DAT ("#\n# Branch: %s\n", $bchname);
#
# Make 1 or more inbound hub connections for this branch.
#
for ($rhx=0; $rhx < $hubredundancy; $rhx++) {
$selecthub = ($hx + $rhx) % $nhub;
$schedule = "s-1-" . $repinterval*$hubredundancy . "-" . ($repinterval*$rhx + $hourslot);
printf DAT ("create %25s %25s on %-12s\n",
$hubs[$selecthub], $bchname, $schedule);
}
#
# Make 1 or more inbound branch connections from the hub servers.
#
for ($rbx=0; $rbx < $bchredundancy; $rbx++) {
$selecthub = ($hx + $rbx) % $nhub;
($host_site, $host_srv) = split(/\\/, $bchname);
$schedule = "s-1-" . $repinterval*$bchredundancy . "-" . ($repinterval*$rbx + $hourslot);
printf DAT ("create %25s %25s on %-12s /dc %s\n",
$bchname, $hubs[$selecthub], $schedule, $host_srv);
}
#
# on to the next branch server.
#
$bx += 1;
last if $bx >= $nbch;
} #end of for $hx
last if $bx >= $nbch;
} # end for $hourslot
} # end for $bx
close(DAT);
__END__
:endofperl
@perl %~dpn0.cmd %*