Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

487 lines
17 KiB

  1. @rem = '
  2. @goto endofperl
  3. ';
  4. #
  5. # Created: 8/2000 David A. Orbits
  6. # Revised: 9/4/2000 Add $hourslot to offset calc.
  7. #
  8. $USAGE = "
  9. Usage: $0 datafile
  10. mkhubbchtop makes a hub and spoke topology data file for input to mkdsx.cmd.
  11. An input file specifies the replication schedule parameters to use, the list
  12. of hub servers and the list of branch servers. Using this data a connection
  13. data file is created containing records that describe each connection object
  14. to create. See the help info for mkdsx for info on the format of this file.
  15. Input command file contains three types of data records, parameters, hub server
  16. records, and branch server records.
  17. /dc <dcname> # the DC to bind to when mkdsx is run on the result file.
  18. # This should be one of the well connected hub DCs.
  19. /auto_cleanup [dcname ...]
  20. # automatically delete all old connection objects under
  21. # each branch or hub site\\server before the first new
  22. # connection is created. See mkdsx.cmd for details.
  23. /debug # this is propagated to the connection data file and will
  24. # cause mkdsx to process the file but suppress any writes
  25. # to the DC.
  26. /avglinkbw nnn # An estimate of the average link bandwidth in KB/Sec units
  27. # available for replication. E.g. If the raw link speed is
  28. # 64k bits/sec and you estimate that only 50% of this is
  29. # available for use then avglinkbw = 0.5 * (64kb / 8 bits/byte).
  30. # From this and the number of hubs, number of branches and the
  31. # replication interval we calculate the maximum bandwidth-limited
  32. # data payload that can be shipped from the branch to the hub. If
  33. # this is exceeded replication will run over into the next scheduled hour.
  34. /repinterval nnn # the replication interval in hours between the Hub and branch
  35. /schedmask # file with 7x24 string of ascii hex digit pairs to turn off the schedule
  36. /schedoverride # file with 7x24 string of ascii hex digit pairs to turn on the schedule
  37. /hubredundancy nnn # the number of redundant connections into the hub machines from the branches
  38. /bchredundancy nnn # the number of redundant connections into the branch machines from the hubs
  39. # 1 means no redundancy, only create a single connection.
  40. # 0 means create no connections for either the hub or branch side.
  41. /output <filename for connection output> # default is mkdsx.dat
  42. /rem remark text that will go to the output file as a comment.
  43. hub: site\\server # the site location and server computer name of a hub server
  44. bch: site\\server # the site location and server computer name of a branch server
  45. There are no optional paramenters and no embedded blanks are allowed within parameters.
  46. Error handling -
  47. Error messages are written to standard out. The entire input file is processed
  48. but if any errors are detected no connection data file is produced.
  49. Connection object creation in the DS -
  50. Since replication connectivity to the branch machines may not be present all
  51. connection objects hosted by a branch server are created on that branch server.
  52. But since the hub server topology is expected to be in place and they are assumed
  53. to be well connected, all the connection objects hosted by the hub servers are
  54. created on the single hub server specified by the DC name in the \"/dc <dcname>\"
  55. parameter. Once a connection object is present on both the hub server and
  56. a branch server of a give hub-branch pair, the DS will replicate these connection
  57. objects across the link. This is necessary for FRS to replicate since both
  58. ends of the link must have a given connection object in its local DC for FRS to
  59. replicate between the two machines. If a given branch machine is not accessible
  60. when mkdsx is run to create the connection then mkdsx will insert the create
  61. command into the redo file so you can retry the create later.
  62. Schedule parameter and load sharing -
  63. The schedule parameter provides a means for setting a repeating replication schedule.
  64. Connection schedules are an attribute associated with each NTDS-Connection object
  65. in the DC. They contain a 7x24 array of bytes, one byte for each hour in a
  66. 7 day week (UTC time zone). You can use the schedule paramter to spread the
  67. replication load among multiple inbound source servers.
  68. The paramter is of the form s-iii-ccc-ppp where the i, c and p fields are decimal
  69. numbers. The i field describes the desired interval (in hours) between inbound
  70. replication events on the host server. The c field describes the number of
  71. connections objects present that will import data to this host server. Or, put
  72. another way, it is the number of other servers that will be providing data to
  73. this server. The p field is offset parameter that ranges from 0 to c-1. It
  74. is used to stagger the schedule relative to the schedules on the other connection
  75. objects.
  76. For example, lets assume you have two connection objects that refer to two servers
  77. SA and SB which will supply replication updates to the host server. We would
  78. like to arrange the schedules of these two connection objects so that our host
  79. server is updated every 4 hours. To do this, the schedule parameter for the
  80. connection object referring to server SA would be 's-4-2-0' and the parameter
  81. for the connection to server SB is 's-4-2-1'.
  82. Source H o u r
  83. Server 0 4 8 12 16 20
  84. 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 ...
  85. 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 ...
  86. Repl Events ^ ^ ^ ^ ^ ^
  87. With these two connection objects the net interval between replication events
  88. will be every 4 hours. The schedule for server B is offset by 4 hours as a result
  89. of the p field being 1. Both of the above schedule patterns continue to repeat
  90. over the course of the 7x24 array comprising the schedule attribute.
  91. As a second example, assume you want to replicate every 2 hours and you establish
  92. connections with three other servers to provide the data. The schedule paramter
  93. values and the schedule array are then:
  94. Source H o u r
  95. Server 0 4 8 12 16 20
  96. 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 ...
  97. 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 ...
  98. 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 ...
  99. Repl Events ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
  100. Schedmask and Schedoverride parameters -
  101. Schedmask and schedoverride data are formatted as a pair of ascii hex digits
  102. for each byte in the 7x24 schedule array with byte 0 corresponding to day 1 hour 0.
  103. For each connection the 7x24 result schedule is formed using the schedule parameter (see
  104. below) and then the schedule mask is applied (each bit set in the schedule mask
  105. clears the corresponding bit in the result schedule). Finally the schedule override
  106. is applied with a logical OR of the override schedule to the result schedule.
  107. Schedmask and schedoverride can have embedded whitespace chars (including cr/lf)
  108. which are deleted or be a single string of 336 (7*24*2) hex digits. For example:
  109. FF0000000000 000000000000 000000000000 000000000000
  110. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  111. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  112. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  113. FF0000000000 FFFFFFFFFF00 000000000000 000000000000
  114. FF0000000000 000000000000 000000000000 000000000000
  115. FF0000000000 000000000000 000000000000 000000000000
  116. Sample Input File -
  117. #
  118. # A sample input file might look as follows:
  119. #
  120. /dc ntdev-dc-01
  121. /repinterval 4 # replicate every 4 hours
  122. /hubredundancy 2 # Create connection objects in 2 different hubs that pull data from the same branch.
  123. /bchredundancy 2 # create 2 connection objects in a branch that pull data from different hub machines.
  124. /auto_cleanup # delete any old connections before the first new connection is created.
  125. #
  126. # list of hub servers for a domain zona2
  127. #
  128. hub: Credit1\C0ZONA21
  129. hub: Credit2\C0ZONA22
  130. hub: Credit3\C0ZONA26
  131. #
  132. # list of branches for zona2 domain
  133. #
  134. bch: 0100Site\C0010000
  135. bch: 0200Site\C0020200
  136. bch: 0270Site\C0027000
  137. bch: 0340Site\C0034000
  138. #End of file
  139. ";
  140. die $USAGE unless @ARGV;
  141. printf("\n\n");
  142. $varnumargs = 99;
  143. $linenumber = 0;
  144. $InFile = "";
  145. $bx = 0;
  146. $hx = 0;
  147. $remx = 0;
  148. $cmdtab{"/dc"} = 1;
  149. $cmdtab{"hub:"} = 1;
  150. $cmdtab{"bch:"} = 1;
  151. $cmdtab{"/debug"} = 0;
  152. $cmdtab{"/output"} = 1;
  153. $cmdtab{"/repinterval"} = 1;
  154. $cmdtab{"/schedmask"} = 1;
  155. $cmdtab{"/schedoverride"} = 1;
  156. $cmdtab{"/auto_cleanup"} = $varnumargs;
  157. $cmdtab{"/hubredundancy"} = 1;
  158. $cmdtab{"/bchredundancy"} = 1;
  159. $cmdtab{"/avglinkbw"} = 1;
  160. $dccmd = "";
  161. $repinterval = 1;
  162. $hubredundancy = 1;
  163. $bchredundancy = 1;
  164. $outfile = "mkdsx.dat";
  165. $errorcount = 0;
  166. $avglinkbw = 0;
  167. while (<>) {
  168. if ($InFile ne $ARGV) {
  169. $InFile = $ARGV;
  170. printf("Processing file %s \n\n", $InFile);
  171. $infilelist = $infilelist . " " . $InFile;
  172. $linenumber = 0;
  173. }
  174. $linenumber++;
  175. chop;
  176. ($func, @a) = split;
  177. if (($func eq "") || ($func =~ m/^#/)) {next;}
  178. #
  179. # /rem <text>
  180. #
  181. if ($func =~ m/\/rem/i) {
  182. $rem[$remx] = $_;
  183. $rem[$remx] =~ s/\/rem//i;
  184. $remx += 1;
  185. next;
  186. }
  187. #
  188. # check for valid command and for missing or extraneous parameters.
  189. #
  190. $func = lc($func);
  191. if (!exists($cmdtab{$func})) {
  192. printf("Line %d: Error: %s unrecognized command.\n%s\n\n", $linenumber, $func, $_);
  193. $errorcount += 1;
  194. next;
  195. }
  196. $numargs = $cmdtab{$func};
  197. if ($numargs ne $varnumargs) {
  198. if (($a[$numargs] ne "") && !($a[$numargs] =~ m/^#/)) {
  199. printf("Line %d: Error: %s has extraneous or missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
  200. $errorcount += 1;
  201. next;
  202. }
  203. $i = $numargs;
  204. while ($i-- > 0) {
  205. if (($a[i] eq "") || ($a[$i] =~ m/^#/)) {
  206. printf("Line %d: Error: %s missing parameters - skipping\n%s\n\n", $linenumber, $func, $_);
  207. $errorcount += 1;
  208. goto NEXT_CMD;
  209. }
  210. }
  211. } else {
  212. #
  213. # This command has a variable number of args. Scan for the last one.
  214. #
  215. $numargs = 0;
  216. while ($numargs <= $#a) {
  217. if ($a[$numargs] =~ m/^#/) {
  218. last;
  219. }
  220. $numargs += 1;
  221. }
  222. }
  223. #
  224. # /dc <dcname>
  225. # /auto_cleanup [dcname1 ...]
  226. # /debug
  227. # /schedmask
  228. # /schedoverride
  229. #
  230. if (($func =~ m/\/dc/i) ||
  231. ($func =~ m/\/debug/i) ||
  232. ($func =~ m/\/schedmask/i) ||
  233. ($func =~ m/\/schedoverride/i) ||
  234. ($func =~ m/\/auto_cleanup/i)) {$prop_cmd[$prop++] = $_; next; }
  235. #
  236. # /output <file>
  237. #
  238. if ($func =~ m/\/output/i) {$outfile = $a[0]; next; }
  239. #
  240. # /repinterval nnn
  241. #
  242. if (($func =~ m/\/repinterval/i) && ($a[0] <= 0)) {
  243. printf("Line %d: Error: %s parameter is <= 0 \n%s\n\n", $linenumber, $func, $_);
  244. $errorcount += 1;
  245. next;
  246. }
  247. #
  248. # /avglinkbw nnn
  249. # /hubredundancy nnn
  250. # /bchredundancy nnn
  251. #
  252. if (($func =~ m/\/hubredundancy|\/bchredundancy|\/avglinkbw/i) && ($a[0] < 0)) {
  253. printf("Line %d: Error: %s parameter is < 0 \n%s\n\n", $linenumber, $func, $_);
  254. $errorcount += 1;
  255. next;
  256. }
  257. if ($func =~ m/\/repinterval/i) {$repinterval = $a[0]; next;}
  258. if ($func =~ m/\/hubredundancy/i) {$hubredundancy = $a[0]; next;}
  259. if ($func =~ m/\/bchredundancy/i) {$bchredundancy = $a[0]; next;}
  260. if ($func =~ m/\/avglinkbw/i) {$avglinkbw = $a[0]; next;}
  261. #
  262. # hub: site\\server
  263. # bch: site\\server
  264. #
  265. if (m/hub:|bch:/i) {
  266. $sitesrv = $a[0];
  267. ($site, $srv) = split(/\\/, $sitesrv);
  268. if (($site eq "") || ($srv eq "")) {
  269. printf("Line %d: Error: Site or Server is null - skipping\n%s\n\n", $linenumber, $_);
  270. $errorcount += 1;
  271. next;
  272. }
  273. if (m/hub:/i) {$hubs[$hx++] = $sitesrv; next;}
  274. if (m/bch:/i) {$bchs[$bx++] = $sitesrv; next;}
  275. }
  276. NEXT_CMD:
  277. }
  278. #
  279. # We have all the data. Generate the topology.
  280. #
  281. $nbch = $bx;
  282. $nhub = $hx;
  283. if ($nbch == 0) {
  284. printf("Error: No branches found in input file.\n");
  285. $errorcount += 1;
  286. }
  287. if ($nhub == 0) {
  288. printf("Error: No hub servers found in input file.\n");
  289. $errorcount += 1;
  290. }
  291. printf("Number hub servers: %d\n", $nhub);
  292. printf("Number branch servers: %d\n", $nbch);
  293. printf("Replication Interval: %d hours\n", $repinterval);
  294. printf("Hub redundancy: %d\n", $hubredundancy);
  295. printf("Branch redundancy: %d\n", $bchredundancy);
  296. if ($nbch * $nhub * $repinterval * $avglinkbw > 0) {
  297. printf("Average available link bandwidth: %d KB/Sec\n", $avglinkbw);
  298. printf("Estimated data payload max from each branch: %d KB\n", ($avglinkbw * 3600) / (($nbch / $nhub) / $repinterval));
  299. printf(" The total amount of data replicated from each branch \n");
  300. printf(" during a replication cycle should be less than this number.\n");
  301. printf(" Otherwise replication from the branches scheduled in one hour\n may run over into the next hour.\n");
  302. }
  303. #
  304. # The connection redundancy can't be greater than the number of hub servers.
  305. #
  306. if ($nhub < $hubredundancy) {
  307. printf("Error: Number of hubs (%d) is less than the requested hub connection redundancy (%d)\n",
  308. $nhub, $hubredundancy);
  309. $errorcount += 1;
  310. }
  311. if ($nhub < $bchredundancy) {
  312. printf("Error: Number of hubs (%d) is less than the requested branch connection redundancy (%d)\n",
  313. $nhub, $bchredundancy);
  314. $errorcount += 1;
  315. }
  316. if ($errorcount > 0) {
  317. printf("%d error(s) were found in the input file. No topology generated\n", $errorcount);
  318. exit $errorcount;
  319. }
  320. printf("\nWriting new topology to %s\n", $outfile);
  321. $DAT = ">$outfile";
  322. open DAT or die "Can't write to $outfile. No topology generated.\n";
  323. for ($i = 0; $i < $remx; $i++) {printf DAT ("# %s\n", $rem[$i]);}
  324. $time = scalar localtime;
  325. printf DAT ("#Time generated: %s\n", $time);
  326. printf DAT ("#Input files: %s\n", $infilelist);
  327. printf DAT ("#Number hub servers: %d\n", $nhub);
  328. printf DAT ("#Number branch servers: %d\n", $nbch);
  329. printf DAT ("#Replication Interval: %d hours\n", $repinterval);
  330. printf DAT ("#Hub redundancy: %d\n", $hubredundancy);
  331. printf DAT ("#Branch redundancy: %d\n", $bchredundancy);
  332. printf DAT ("#\n");
  333. #
  334. # output any propagated commands.
  335. #
  336. while ($prop-- > 0) {
  337. printf DAT ("%s\n", $prop_cmd[$prop]);
  338. }
  339. printf DAT ("#\n");
  340. $bchleft = $nbch;
  341. $bx = 0;
  342. #
  343. # Process until all branches have been consumed.
  344. #
  345. while ($bx < $nbch) {
  346. #
  347. # For each hour slot in the replication interval assign a hub server to perform
  348. # replication with a branch.
  349. #
  350. for ($hourslot=0; $hourslot < $repinterval; $hourslot++) {
  351. #
  352. # For each hub server in the list assign it a branch to replicate with.
  353. #
  354. for ($hx=0; $hx < $nhub; $hx++) {
  355. #
  356. # get the next branch in the list.
  357. #
  358. $bchname = $bchs[$bx];
  359. printf DAT ("#\n# Branch: %s\n", $bchname);
  360. #
  361. # Make 1 or more inbound hub connections for this branch.
  362. #
  363. for ($rhx=0; $rhx < $hubredundancy; $rhx++) {
  364. $selecthub = ($hx + $rhx) % $nhub;
  365. $schedule = "s-1-" . $repinterval*$hubredundancy . "-" . ($repinterval*$rhx + $hourslot);
  366. printf DAT ("create %25s %25s on %-12s\n",
  367. $hubs[$selecthub], $bchname, $schedule);
  368. }
  369. #
  370. # Make 1 or more inbound branch connections from the hub servers.
  371. #
  372. for ($rbx=0; $rbx < $bchredundancy; $rbx++) {
  373. $selecthub = ($hx + $rbx) % $nhub;
  374. ($host_site, $host_srv) = split(/\\/, $bchname);
  375. $schedule = "s-1-" . $repinterval*$bchredundancy . "-" . ($repinterval*$rbx + $hourslot);
  376. printf DAT ("create %25s %25s on %-12s /dc %s\n",
  377. $bchname, $hubs[$selecthub], $schedule, $host_srv);
  378. }
  379. #
  380. # on to the next branch server.
  381. #
  382. $bx += 1;
  383. last if $bx >= $nbch;
  384. } #end of for $hx
  385. last if $bx >= $nbch;
  386. } # end for $hourslot
  387. } # end for $bx
  388. close(DAT);
  389. __END__
  390. :endofperl
  391. @perl %~dpn0.cmd %*