Source code of Windows XP (NT5)
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.

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