PageRenderTime 58ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/xCAT-server/lib/xcat/plugins/makentp.pm

https://gitlab.com/qisback/xcat-core
Perl | 449 lines | 346 code | 59 blank | 44 comment | 82 complexity | f75d5ec47b43075935b94c4bcc5c1266 MD5 | raw file
Possible License(s): EPL-1.0
  1. #!/usr/bin/env perl
  2. # IBM(c) 2015 EPL license http://www.eclipse.org/legal/epl-v10.html
  3. package xCAT_plugin::makentp;
  4. BEGIN
  5. {
  6. $::XCATROOT = $ENV{'XCATROOT'} ? $ENV{'XCATROOT'} : '/opt/xcat';
  7. }
  8. use lib "$::XCATROOT/lib/perl";
  9. use Getopt::Long;
  10. use xCAT::Usage;
  11. use xCAT::NetworkUtils;
  12. use xCAT::TableUtils;
  13. use xCAT::Utils;
  14. use XML::Simple;
  15. no strict;
  16. use Data::Dumper;
  17. use Socket;
  18. my %globalopt;
  19. #-------------------------------------------------------------------------------
  20. =head1 xCAT_plugin:makentp
  21. =head2 Package Description
  22. Handles ntp server setup on a xCAT management node.
  23. =cut
  24. #-------------------------------------------------------------------------------
  25. #--------------------------------------------------------------------------------
  26. =head3 send_msg
  27. Invokes the callback with the specified message
  28. Arguments:
  29. request: request structure for plguin calls
  30. ecode: error code. 0 for succeful.
  31. msg: messages to be displayed.
  32. Returns:
  33. none
  34. =cut
  35. #--------------------------------------------------------------------------------
  36. sub send_msg {
  37. my $request = shift;
  38. my $ecode = shift;
  39. my $msg = shift;
  40. my %output;
  41. # Called from child process - send to parent
  42. if ( exists( $request->{pipe} )) {
  43. my $out = $request->{pipe};
  44. $output{errorcode} = $ecode;
  45. $output{data} = \@_;
  46. print $out freeze( [\%output] );
  47. print $out "\nENDOFFREEZE6sK4ci\n";
  48. }
  49. # Called from parent - invoke callback directly
  50. elsif ( exists( $request->{callback} )) {
  51. my $callback = $request->{callback};
  52. $output{errorcode} = $ecode;
  53. $output{data}->[0] = $msg;
  54. $callback->( \%output );
  55. }
  56. }
  57. #--------------------------------------------------------------------------------
  58. =head3 handled_commands
  59. It returns a list of commands handled by this plugin.
  60. Arguments:
  61. none
  62. Returns:
  63. a list of commands.
  64. =cut
  65. #--------------------------------------------------------------------------------
  66. sub handled_commands {
  67. return( {makentp=>"makentp"} );
  68. }
  69. #--------------------------------------------------------------------------------
  70. =head3 parse_args
  71. Parse the command line options and operands.
  72. Arguments:
  73. request: the request structure for plugin
  74. Returns:
  75. Usage string or error message.
  76. 0 if no user promp needed.
  77. =cut
  78. #--------------------------------------------------------------------------------
  79. sub parse_args {
  80. my $request = shift;
  81. my $args = $request->{arg};
  82. my $cmd = $request->{command};
  83. my %opt;
  84. # Responds with usage statement
  85. local *usage = sub {
  86. my $usage_string = xCAT::Usage->getUsage($cmd);
  87. return( [$_[0], $usage_string] );
  88. };
  89. # No command-line arguments - use defaults
  90. if ( !defined( $args )) {
  91. return(0);
  92. }
  93. # Checks case in GetOptions, allows opts
  94. # to be grouped (e.g. -vx), and terminates
  95. # at the first unrecognized option.
  96. @ARGV = @$args;
  97. $Getopt::Long::ignorecase = 0;
  98. Getopt::Long::Configure( "bundling" );
  99. # Process command-line flags
  100. if (!GetOptions( \%opt,
  101. qw(h|help V|Verbose v|version a|all))) {
  102. return( usage() );
  103. }
  104. # Option -V for verbose output
  105. if ( exists( $opt{V} )) {
  106. $globalopt{verbose} = 1;
  107. }
  108. if ( exists( $opt{a} )) {
  109. $globalopt{a} = 1;
  110. }
  111. return;
  112. }
  113. #--------------------------------------------------------------------------------
  114. =head3 preprocess_request
  115. Parse the arguments and display the usage or the version string.
  116. =cut
  117. #--------------------------------------------------------------------------------
  118. sub preprocess_request {
  119. my $req = shift;
  120. if ($req->{_xcatpreprocessed}->[0] == 1) { return [$req]; }
  121. my $callback=shift;
  122. my $command = $req->{command}->[0];
  123. my $extrargs = $req->{arg};
  124. my @exargs=($req->{arg});
  125. if (ref($extrargs)) {
  126. @exargs=@$extrargs;
  127. }
  128. # Build hash to pass around
  129. my %request;
  130. $request{arg} = $extrargs;
  131. $request{callback} = $callback;
  132. $request{command} = $command;
  133. my $usage_string=xCAT::Usage->parseCommand($command, @exargs);
  134. if ($usage_string) {
  135. $callback->({data=>[$usage_string]});
  136. $req = {};
  137. return;
  138. }
  139. my $result = parse_args( \%request );
  140. if ( ref($result) eq 'ARRAY' ) {
  141. send_msg( \%request, 1, @$result );
  142. return(1);
  143. }
  144. # add current request
  145. my @result = ();
  146. my $reqcopy = {%$req};
  147. $reqcopy->{_xcatpreprocessed}->[0] = 1;
  148. if (xCAT::Utils->isMN() && exists($globalopt{a})) {
  149. $reqcopy->{_all}->[0] = 1;
  150. }
  151. if (exists($globalopt{verbose})) {
  152. $reqcopy->{_verbose}->[0] = 1;
  153. }
  154. push @result, $reqcopy;
  155. return \@result;
  156. }
  157. #--------------------------------------------------------------------------------
  158. =head3 process_request
  159. Pasrse the arguments and call the correspondent functions
  160. to do switch discovery.
  161. =cut
  162. #--------------------------------------------------------------------------------
  163. sub process_request {
  164. my $req = shift;
  165. my $callback = shift;
  166. my $sub_req = shift;
  167. # Build hash to pass around
  168. my %request;
  169. $request{arg} = $req->{arg};
  170. $request{callback} = $callback;
  171. $request{command} = $req->{command}->[0];
  172. my $verbose;
  173. if ($req->{_verbose}->[0] == 1) {
  174. $verbose = 1;
  175. }
  176. my @nodeinfo = xCAT::NetworkUtils->determinehostname();
  177. my $nodename = pop @nodeinfo;
  178. if (xCAT::Utils->isMN()) {
  179. send_msg(\%request, 0, "configuring management node: $nodename." );
  180. } else {
  181. send_msg(\%request, 0, "configuring service node: $nodename." );
  182. }
  183. #check if ntp is installed or not
  184. if ($verbose) {
  185. send_msg(\%request, 0, " ...checking if nptd is installed." );
  186. }
  187. if (!-f "/usr/sbin/ntpd") {
  188. send_msg(\%request, 1, "Please make sure ntpd is installed on $nodename.");
  189. return 1;
  190. }
  191. #configure the ntp configuration file
  192. if ($verbose) {
  193. send_msg(\%request, 0, " ...backing up the ntp configuration file /etc/ntp.conf." );
  194. }
  195. my $ntpcfg = "/etc/ntp.conf";
  196. my $ntpcfgbackup = "/etc/ntp.conf.orig";
  197. my $ntpxcatcfgbackup = "/etc/ntp.conf.xcatbackup";
  198. if (-e $ntpcfg) {
  199. if (!-e $ntpcfgbackup) {
  200. # if original backup does not already exist
  201. my $cmd = "mv $ntpcfg $ntpcfgbackup";
  202. my $result = xCAT::Utils->runcmd($cmd, 0);
  203. if ($::RUNCMD_RC != 0) {
  204. send_msg(\%request, 1, "Error from command:$cmd\n $result");
  205. return 1;
  206. }
  207. }
  208. else {
  209. # backup xcat cfg
  210. my $cmd = "rm $ntpxcatcfgbackup;mv $ntpcfg $ntpxcatcfgbackup";
  211. my $result = xCAT::Utils->runcmd($cmd, 0);
  212. if ($::RUNCMD_RC != 0) {
  213. send_msg(\%request, 1, "Error from command:$cmd\n $result.");
  214. return 1;
  215. }
  216. }
  217. }
  218. # get site.extntpservers for mn, for sn use mn as the server
  219. my $ntp_servers;
  220. my $ntp_master;
  221. my $ntp_attrib;
  222. if (xCAT::Utils->isMN()) {
  223. $ntp_attrib = "extntpservers";
  224. } else {
  225. $ntp_attrib = "ntpservers";
  226. }
  227. my @entries = xCAT::TableUtils->get_site_attribute($ntp_attrib);
  228. my $ntp_servers = $entries[0];
  229. if (!xCAT::Utils->isMN() && ((!$ntp_servers) || (($ntp_servers) && ($ntp_servers =~ /<xcatmaster>/)))) {
  230. my $retdata = xCAT::ServiceNodeUtils->readSNInfo($nodename);
  231. $ntp_servers = $retdata->{'master'};
  232. }
  233. if ($verbose) {
  234. send_msg(\%request, 0, " ...changing the ntpp configuration file /etc/ntp.conf.\n ntp servers are: $ntp_servers" );
  235. }
  236. # create ntp server config file
  237. open(CFGFILE, ">$ntpcfg")
  238. or xCAT::MsgUtils->message('SE',
  239. "Cannot open $ntpcfg for NTP update. \n");
  240. if (defined($ntp_servers) && $ntp_servers) {
  241. my @npt_server_array = split(',', $ntp_servers);
  242. # add ntp servers one by one
  243. foreach my $ntps (@npt_server_array) {
  244. if (!$ntp_master) { $ntp_master = $ntps; }
  245. print CFGFILE "server ";
  246. print CFGFILE "$ntps\n";
  247. }
  248. }
  249. if (xCAT::Utils->isAIX()) {
  250. print CFGFILE "driftfile /etc/ntp.drift\n";
  251. print CFGFILE "tracefile /etc/ntp.trace\n";
  252. print CFGFILE "disable auth\n";
  253. print CFGFILE "broadcastclient\n";
  254. } else {
  255. print CFGFILE "driftfile /var/lib/ntp/drift\n";
  256. print CFGFILE "disable auth\n";
  257. }
  258. #add xCAT mn/sn itself as a server
  259. print CFGFILE "server 127.127.1.0\n";
  260. print CFGFILE "fudge 127.127.1.0 stratum 10\n";
  261. close CFGFILE;
  262. my $os = xCAT::Utils->osver("all");
  263. my $ntp_service = "ntpserver";
  264. #stop ntpd
  265. if ($verbose) {
  266. send_msg(\%request, 0, " ...stopping $ntp_service" );
  267. }
  268. my $rc=xCAT::Utils->stopservice($ntp_service);
  269. if ($rc != 0) {
  270. send_msg(\%request, 1, "Failed to stop nptd on $nodename.");
  271. return 1;
  272. }
  273. #update the time now
  274. if ($ntp_master) {
  275. my $cmd;
  276. if ($os =~ /sles/) {
  277. if (-f "/usr/sbin/rcntpd") {
  278. $cmd = "/usr/sbin/rcntpd ntptimeset";
  279. } elsif (-f "/usr/sbin/rcntp") {
  280. $cmd = "/usr/sbin/rcntp ntptimeset";
  281. } else {
  282. $cmd = "sntp -P no -r $ntp_master";
  283. }
  284. } else {
  285. $cmd = "ntpdate -t5 $ntp_master";
  286. }
  287. if ($verbose) {
  288. send_msg(\%request, 0, " ...updating the time now. $cmd");
  289. }
  290. my $result = xCAT::Utils->runcmd($cmd, 0);
  291. if ($verbose) {
  292. send_msg(\%request, 0, " $result");
  293. }
  294. if ($::RUNCMD_RC != 0) {
  295. send_msg(\%request, 1, "Error from command $cmd\n $result.");
  296. return 1;
  297. }
  298. }
  299. #setup the hardware clock
  300. my $hwcmd = "/sbin/hwclock --systohc --utc";
  301. if ($verbose) {
  302. send_msg(\%request, 0, " ...updating the hwclock now. $hwcmd");
  303. }
  304. my $hwresult = xCAT::Utils->runcmd($hwcmd, 0);
  305. if ($verbose) {
  306. send_msg(\%request, 0, " $hwresult");
  307. }
  308. if ($::RUNCMD_RC != 0) {
  309. send_msg(\%request, 1, "Error from command $hwcmd\n $hwresult.");
  310. return 1;
  311. }
  312. my $grep_cmd;
  313. my $rc;
  314. #setup the RTC is UTC format, which will be used by os
  315. if ($os =~ /sles/) {
  316. `sed -i 's/.*HWCLOCK.*/HWCLOCK="-u"/' /etc/sysconfig/clock`;
  317. } elsif ( -f "/etc/debian_version" ){
  318. `sed -i "s/.*UTC.*/UTC=yes/" /etc/default/rcS`;
  319. } else {
  320. if ( -f "/etc/sysconfig/clock" ) {
  321. $grep_cmd = "grep -i utc /etc/sysconfig/clock";
  322. $rc = xCAT::Utils->runcmd($grep_cmd, 0);
  323. if ($::RUNCMD_RC != 0){
  324. `sed -i 's/.*UTC.*/UTC=yes/' /etc/sysconfig/clock`;
  325. } else {
  326. `echo "UTC=yes" >> /etc/sysconfig/clock`;
  327. }
  328. } else {
  329. `type -P timedatectl >/dev/null 2>&1`;
  330. `timedatectl set-local-rtc 0`;
  331. }
  332. }
  333. #update the hardware clock automaticly
  334. if ( -f "/etc/sysconfig/ntpd" ) {
  335. $grep_cmd = "grep -i SYNC_HWCLOCK /etc/sysconfig/ntpd";
  336. $rc = xCAT::Utils->runcmd($grep_cmd, 0);
  337. if ($::RUNCMD_RC != 0) {
  338. `sed -i "s/.*SYNC_HWCLOCK.*/SYNC_HWCLOCK=yes/" /etc/sysconfig/ntpd`;
  339. } else {
  340. `echo "SYNC_HWCLOCK=yes" >> /etc/sysconfig/ntpd`;
  341. }
  342. } else {
  343. my $cron_file="/etc/cron.daily/xcatsethwclock";
  344. if ( ! -f "$cron_file" ) {
  345. `echo "#!/bin/sh" > $cron_file` ;
  346. `echo "/sbin/hwclock --systohc --utc" >> $cron_file`;
  347. `chmod a+x $cron_file`;
  348. #service cron restart
  349. xCAT::Utils->startservice("cron");
  350. }
  351. }
  352. #start ntpd
  353. if ($verbose) {
  354. send_msg(\%request, 0, " ...starting $ntp_service" );
  355. }
  356. my $rc=xCAT::Utils->startservice($ntp_service);
  357. if ($rc != 0) {
  358. send_msg(\%request, 1, "Failed to start nptd on $nodename.");
  359. return 1;
  360. }
  361. #enable ntpd for node reboot
  362. if ($verbose) {
  363. send_msg(\%request, 0, " ...enabling $ntp_service" );
  364. }
  365. xCAT::Utils->enableservice($ntp_service);
  366. #now handle sn that has ntpserver=1 set in servicenode table.
  367. # this part is called by makentp -a.
  368. if ($req->{_all}->[0] == 1) {
  369. my @servicenodes = xCAT::ServiceNodeUtils->getSNList('ntpserver');
  370. if (@servicenodes > 0) {
  371. send_msg(\%request, 0, "configuring service nodes: @servicenodes" );
  372. my $ret =
  373. xCAT::Utils->runxcmd(
  374. {
  375. command => ['updatenode'],
  376. node => \@servicenodes,
  377. arg => ["-P", "setupntp"],
  378. },
  379. $sub_req, -1, 1
  380. );
  381. my $msg;
  382. foreach my $line (@$ret) {
  383. $msg .= "$line\n";
  384. }
  385. send_msg(\%request, 1, "$msg");
  386. }
  387. }
  388. return;
  389. }
  390. 1;