You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by da...@apache.org on 2017/01/27 16:53:25 UTC
[04/36] incubator-trafficcontrol git commit: -Removed reconfigure
line -Removed trailing spaces in input.json -Renamed postinstall-new to
postinstall for easier diff
-Removed reconfigure line
-Removed trailing spaces in input.json
-Renamed postinstall-new to postinstall for easier diff
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/64f49e3f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/64f49e3f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/64f49e3f
Branch: refs/heads/master
Commit: 64f49e3f747d6d5d40926a5f4fcec9902fa70140
Parents: ed58286
Author: peryder <pe...@cisco.com>
Authored: Mon Jan 9 09:24:43 2017 -0500
Committer: Dan Kirkwood <da...@gmail.com>
Committed: Fri Jan 27 09:52:53 2017 -0700
----------------------------------------------------------------------
traffic_ops/build/traffic_ops.spec | 1 -
traffic_ops/install/bin/input.json | 142 +--
traffic_ops/install/bin/postinstall | 1385 ++++++++++++++------------
traffic_ops/install/bin/postinstall-new | 781 ---------------
4 files changed, 747 insertions(+), 1562 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/64f49e3f/traffic_ops/build/traffic_ops.spec
----------------------------------------------------------------------
diff --git a/traffic_ops/build/traffic_ops.spec b/traffic_ops/build/traffic_ops.spec
index 4483aa2..35cc608 100644
--- a/traffic_ops/build/traffic_ops.spec
+++ b/traffic_ops/build/traffic_ops.spec
@@ -109,7 +109,6 @@ Built: %(date) by %{getenv: USER}
# install
if [ "$1" = "1" ]; then
# see postinstall, the .reconfigure file triggers init().
- #/bin/touch %{PACKAGEDIR}/.reconfigure
echo -e "\nRun /opt/traffic_ops/install/bin/postinstall from the root home directory to complete the install.\n"
fi
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/64f49e3f/traffic_ops/install/bin/input.json
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/input.json b/traffic_ops/install/bin/input.json
index 76720f6..b1adce2 100644
--- a/traffic_ops/install/bin/input.json
+++ b/traffic_ops/install/bin/input.json
@@ -1,169 +1,71 @@
-{
- "/opt/traffic_ops/app/conf/production/database.conf":[
- {
+{
+ "/opt/traffic_ops/app/conf/production/database.conf":[
+ {
"Database type":"mysql",
"config_var":"type"
},
- {
+ {
"Database name":"traffic_ops_db",
"config_var":"dbname"
},
- {
+ {
"Database server hostname IP or FQDN":"localhost",
"config_var":"hostname"
},
- {
+ {
"Database port number":"3306",
"config_var":"port"
},
- {
+ {
"Traffic Ops database user":"traffic_ops",
"config_var":"user"
},
- {
+ {
"Traffic Ops database password":"default",
"config_var":"password",
"hidden":"1"
}
],
- "/opt/traffic_ops/app/db/dbconf.yml":[
- {
+ "/opt/traffic_ops/app/db/dbconf.yml":[
+ {
"Database server root (admin) username":"root",
"config_var":"dbAdminUser"
},
- {
+ {
"Database server admin password":"default",
"config_var":"dbAdminPw",
"hidden":"1"
}
],
- "/opt/traffic_ops/app/conf/cdn.conf":[
- {
+ "/opt/traffic_ops/app/conf/cdn.conf":[
+ {
"Generate a new secret?":"yes",
"config_var":"genSecret"
},
- {
+ {
"Number of secrets to keep?":"10",
"config_var":"keepSecrets"
}
],
- "/opt/traffic_ops/app/conf/ldap.conf":[
- {
+ "/opt/traffic_ops/app/conf/ldap.conf":[
+ {
"Do you want to set up LDAP?":"no",
"config_var":"setupLdap"
},
- {
+ {
"LDAP server hostname":"",
"config_var":"hostname"
},
- {
+ {
"LDAP Admin DN":"",
"config_var":"admin_dn"
},
- {
+ {
"LDAP Admin Password":"",
"config_var":"password",
"hidden":"1"
},
- {
+ {
"LDAP Search Base":"",
- "config_var":"search_base"
- }
- ],
- "/opt/traffic_ops/install/data/json/users.json":[
- {
- "Administration username for Traffic Ops":"root",
- "config_var":"tmAdminUser"
- },
- {
- "Password for the admin user":"default",
- "config_var":"tmAdminPw",
- "hidden":"1"
- }
- ],
- "/opt/traffic_ops/install/data/profiles/":[
-
- ],
- "/opt/traffic_ops/install/data/json/openssl_configuration.json":[
- {
- "Do you want to generate a certificate?":"yes",
- "config_var":"genCert"
- },
- {
- "Country Name (2 letter code)":"XX",
- "config_var":"country"
- },
- {
- "State or Province Name (full name)":"Default State",
- "config_var":"state"
- },
- {
- "Locality Name (eg, city)":"Default City",
- "config_var":"locality"
- },
- {
- "Organization Name (eg, company)":"Default Company Ltd",
- "config_var":"company"
- },
- {
- "Organizational Unit Name (eg, section)":"",
- "config_var":"org_unit"
- },
- {
- "Common Name (eg, your name or your server's hostname)":"example.com",
- "config_var":"common_name"
- },
- {
- "RSA Passphrase":"password",
- "config_var":"rsaPassword",
- "hidden":"1"
- }
- ],
- "/opt/traffic_ops/install/data/json/profiles.json":[
- {
- "Traffic Ops url":"https://localhost",
- "config_var":"tm.url"
- },
- {
- "Human-readable CDN Name. (No whitespace, please)":"kabletown_cdn",
- "config_var":"cdn_name"
- },
- {
- "Health Polling Interval (milliseconds)":"8000",
- "config_var":"health_polling_int"
- },
- {
- "DNS sub-domain for which your CDN is authoritative":"cdn1.kabletown.net",
- "config_var":"dns_subdomain"
- },
- {
- "TLD SOA admin":"traffic_ops",
- "config_var":"soa_admin"
- },
- {
- "TrafficServer Drive Prefix":"/dev/sd",
- "config_var":"driver_prefix"
- },
- {
- "TrafficServer RAM Drive Prefix":"/dev/ram",
- "config_var":"ram_drive_prefix"
- },
- {
- "TrafficServer RAM Drive Letters (comma separated)":"0,1,2,3,4,5,6,7",
- "config_var":"ram_drive_letters"
- },
- {
- "Health Threshold Load Average":"25",
- "config_var":"health_thresh_load_avg"
- },
- {
- "Health Threshold Available Bandwidth in Kbps":">1750000",
- "config_var":"health_thresh_kbps"
- },
- {
- "Traffic Server Health Connection Timeout (milliseconds)":"2000",
- "config_var":"health_connect_timeout"
- }
- ]
-}
-
+ "input.json" 169 L,
+ 4044 C
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/64f49e3f/traffic_ops/install/bin/postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/postinstall b/traffic_ops/install/bin/postinstall
index 6a747da..1092338 100755
--- a/traffic_ops/install/bin/postinstall
+++ b/traffic_ops/install/bin/postinstall
@@ -1,7 +1,6 @@
#!/usr/bin/perl
#
-#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
@@ -15,702 +14,768 @@
# limitations under the License.
#
-use strict;
-use warnings;
-
use lib qw(/opt/traffic_ops/install/lib /opt/traffic_ops/install/lib/perl5 /opt/traffic_ops/app/local/lib/perl5 /opt/traffic_ops/app/lib);
$ENV{PATH} = "/opt/traffic_ops/install/bin:$ENV{PATH}";
$ENV{PERL5LIB} = "/opt/traffic_ops/install/lib:/opt/traffic_ops/install/lib/perl5:/opt/traffic_ops/app/local/lib/perl5:/opt/traffic_ops/app/lib";
-use DBI;
-use JSON;
+use strict;
+use warnings;
+
+use Safe;
+use POSIX;
+use File::Basename qw{dirname};
+use File::Path qw{make_path};
use InstallUtils qw{ :all };
+use BuildPerlDeps qw{ :all };
+use GenerateCert qw{ :all };
+use ProfileCleanup qw { :all };
use Digest::SHA1 qw(sha1_hex);
-use Data::Dumper;
-use File::Temp;
-use WWW::Curl::Easy;
-use LWP::UserAgent;
-use File::Copy;
-
-my $database_conf = "/opt/traffic_ops/app/conf/production/database.conf";
-my $ldap_conf = "/opt/traffic_ops/app/conf/ldap.conf";
-my $cdn_conf = "/opt/traffic_ops/app/conf/cdn.conf";
-my $migrations_dbconf = "/opt/traffic_ops/app/db/dbconf.yml";
-my $post_install_cfg = "/opt/traffic_ops/install/data/json/post_install.json";
-my $users_file = "/opt/traffic_ops/install/data/json/users.json";
-my $profile_dir = "/opt/traffic_ops/install/data/profiles/";
-my %dbdriver = ( mysql => "mymysql", );
-
-my $reconfigure = "/opt/traffic_ops/.reconfigure";
-my $reconfigure_defaults = "/opt/traffic_ops/.reconfigure_defaults";
-my $tmAdminUser = "";
-my $tmAdminPw = "";
-my $parameters;
-
-my $installMsg = << 'EOF';
-
-This script will initialize the Traffic Ops database.
-Please enter the following information in order to completely
-configure the Traffic Ops mysql database.
-
-EOF
-
-sub readJson {
- my $file = shift;
- open( my $fh, '<', $file ) or return;
- local $/; # slurp mode
- my $text = <$fh>;
- undef $fh;
- return JSON->new->utf8->decode($text);
+use Data::Dumper qw(Dumper);
+use Scalar::Util qw(looks_like_number);
+use Getopt::Long;
+
+# paths of the output configuration files
+our $databaseConfFile = "/opt/traffic_ops/app/conf/production/database.conf";
+our $dbConfFile = "/opt/traffic_ops/app/db/dbconf.yml";
+our $cdnConfFile = "/opt/traffic_ops/app/conf/cdn.conf";
+our $ldapConfFile = "/opt/traffic_ops/app/conf/ldap.conf";
+our $usersConfFile = "/opt/traffic_ops/install/data/json/users.json";
+our $profilesConfFile = "/opt/traffic_ops/install/data/profiles/";
+our $opensslConfFile = "/opt/traffic_ops/install/data/json/openssl_configuration.json";
+our $paramConfFile = "/opt/traffic_ops/install/data/json/profiles.json";
+
+our $profile_dir = "/opt/traffic_ops/install/data/profiles/";
+our $post_install_cfg = "/opt/traffic_ops/install/data/json/post_install.json";
+
+our $reconfigure_defaults = "/opt/traffic_ops/.reconfigure_defaults";
+
+our $parameters;
+
+# old way of reconfiguring postinstall - only here to check for file and let user know it is deprecated
+my $reconfigure_file = "/opt/traffic_ops/.reconfigure";
+
+# whether or not to reconfigure traffic ops
+my $reconfigure;
+
+# whether to create a config file with default values
+my $dumpDefaults;
+
+# log file for the installer
+our $logFile = "/var/log/traffic_ops/postinstall.log";
+
+# maximum size the uncompressed log file should be before rotating it - rotating it copies the current log
+# file to the same name appended with .bkp replacing the old backup if any is there
+my $maxLogSize = 1000000; #bytes
+
+# log file for cpan - this log becomes large and is rotated every install
+our $cpanLogFile = "/var/log/traffic_ops/cpan.log";
+
+# configuration file output with answers which can be used as input to postinstall
+our $outputConfigFile = "/var/log/traffic_ops/configuration_file.json";
+
+sub getDbDriver {
+ return "mymysql";
}
-sub writeJson {
- my $file = shift;
- open( my $fh, '>', $file ) or die("open(): $!");
- foreach my $data (@_) {
- my $json_text = JSON->new->utf8->encode($data);
- print $fh $json_text, "\n";
- }
- close $fh;
+sub getInstallPath {
+ my $relPath = shift;
+ return join( '/', "/tmp/traffic_ops", $relPath );
}
-sub writeYamlToFH {
- my $fh = shift;
- my $data = shift;
- my $level = shift || 0;
- my $prefix = shift || '';
-
- my $type = ref($data);
- my $indent = ' ' x $level;
- if ( $type eq '' ) {
-
- # scalar
- print $fh "$indent$prefix$data\n";
- }
- elsif ( $type eq 'HASH' ) {
- foreach my $key ( keys %$data ) {
- my $value = $data->{$key};
- if ( ref($value) eq '' ) {
- print $fh "$indent$key: $value\n";
- }
- else {
- print $fh "$indent$key:\n";
- writeYamlToFH( $fh, $data->{$key}, $level + 1 );
- }
- }
- }
- elsif ( $type eq 'ARRAY' ) {
- foreach my $d (@$data) {
- writeYamlToFH( $fh, $d, $level + 1, '- ' );
- }
- }
+# given a var to the hash of config_var and question, will return the question
+sub getConfigQuestion {
+ my $var = shift;
+ foreach my $key ( keys $var ) {
+ if ( $key ne "hidden" && $key ne "config_var" ) {
+ return $key;
+ }
+ }
}
-sub writeYaml {
- my $file = shift;
- my $data = shift;
- open my $fh, '>', $file or die "open(): $!";
- writeYamlToFH( $fh, $data );
+# question: The question given in the config file
+# config_answer: The answer given in the config file - if no config file given will be defaultInput
+# hidden: Whether or not the answer should be hidden from the terminal and logs, ex. passwords
+#
+# Determines if the script is being run in complete interactive mode and prompts user - otherwise
+# returns answer to question in config or defaults
+
+sub getField {
+ my $question = shift;
+ my $config_answer = shift;
+ my $hidden = shift;
+
+ # if there is no config file and not in automatic mode prompt for all questions with default answers
+ if ( !$::inputFile && !$::automatic ) {
+
+ # if hidden then dont show password in terminal
+ if ($hidden) {
+ return promptPasswordVerify($question);
+ }
+ else {
+ return promptUser( $question, $config_answer );
+ }
+ }
+
+ return $config_answer;
}
-# Init.
-sub init () {
- my $c = readJson($database_conf);
- my %dbconf = %$c;
- my $dbAdminUser;
- my $dbAdminPw;
-
- # loop exits on successful db connect
- while (1) {
- execCommand( "/usr/bin/tput", "clear" );
-
- if ($DBI::errstr) {
- print "Error connecting to database using the supplied information: $DBI::errstr\n";
- }
-
- print "\n$installMsg\n";
-
- $dbconf{type} = promptUser( "Database type", $dbconf{type} || "mysql" );
- $dbconf{dbname} = promptUser( "Database name", $dbconf{dbname} || "traffic_ops_db" );
- $dbconf{hostname} = promptUser( "Database server hostname IP or FQDN", $dbconf{hostname} || "localhost" );
- $dbconf{port} = promptUser( "Database port number", $dbconf{port} || "3306" );
- $dbconf{user} = promptUser( "Traffic Ops database user", $dbconf{user} || "traffic_ops" );
- $dbconf{password} = promptPasswordVerify("Password for $dbconf{user}");
- $dbconf{description} = "$dbconf{type} database on $dbconf{hostname}:$dbconf{port}";
- print "\n";
- $dbAdminUser = promptUser( "Database server root (admin) user name", "root" );
- $dbAdminPw = promptPassword("Database server $dbAdminUser password");
-
- print "Database Type: $dbconf{type}\n";
- print "Database Name: $dbconf{dbname}\n";
- print "Hostname: $dbconf{hostname}\n";
- print "Port: $dbconf{port}\n";
- print "Database User: $dbconf{user}\n";
- my $ans = promptUser( "Is the above information correct (y/n)", "n" );
-
- if ( $ans eq "y" ) {
- my $dsn = sprintf( "DBI:mysql:%s:%s:%s", "mysql", $dbconf{hostname}, $dbconf{port} );
- my $dbh = DBI->connect( $dsn, $dbAdminUser, $dbAdminPw );
- if ($dbh) {
-
- # Success!
- $dbh->disconnect();
- last;
- }
- }
- }
-
- writeJson( $database_conf, \%dbconf );
- print "\nThe database properties have been saved to $database_conf\n";
-
- # migrations dbconf is in YAML
- my $driver = $dbdriver{ $dbconf{type} };
- my %migrations = ( production => { driver => $driver, open => "tcp:$dbconf{hostname}:$dbconf{port}*$dbconf{dbname}/$dbconf{user}/$dbconf{password}" } );
- writeYaml( $migrations_dbconf, \%migrations );
-
- my $msg = << 'EOF';
-
- The database configuration has been saved. Now we need to set some custom
- fields that are necessary for the CDN to function correctly.
-
-EOF
-
- print $msg, "\n";
- while (1) {
-
- my $tmurl = promptUser( "Traffic Ops url", $parameters->{"tm.url"} || "https://localhost" );
- $parameters->{"tm.url"} = $tmurl;
- $parameters->{"tm.infourl"} = "$tmurl/info";
-
- $parameters->{cdnname} = promptUser( "Human-readable CDN Name. (No whitespace, please)", $parameters->{cdnname} || "kabletown_cdn" );
- $parameters->{domainname} = promptUser( "DNS sub-domain for which your CDN is authoritative", $parameters->{domainname} || "cdn1.kabletown.net" );
-
- my $geolocationUrl = "$tmurl/routing/GeoIP2-City.mmdb.gz";
- $parameters->{"geolocation.polling.url"} = $geolocationUrl;
-
- my $coverageZoneUrl = "$tmurl/routing/coverage-zone.json";
- $parameters->{"coveragezone.polling.url"} = $coverageZoneUrl;
-
- my $centosTarballFqn = '';
- my $skip;
- while (1) {
- $centosTarballFqn = promptUser( "Fully qualified name of your CentOS ISO kickstart tarball, or 'na' to skip and add files later",
- "/var/cache/centos72.tgz" );
- if ( $centosTarballFqn eq 'na' ) {
- $skip = 1;
- last;
- }
- if ( -f $centosTarballFqn ) {
- last;
- }
- print "\nNo file named $centosTarballFqn found.\n\n";
- }
-
- my $kickstartFilesFqn = promptUser( "Fully qualified location to store your ISO kickstart files", "/var/www/files" );
- my $parametersJson = "/opt/traffic_ops/install/data/json/parameter.json";
-
- ## Replace parameter with $kickstartFilesFqn
- open( my $json_fh, "<:encoding(UTF-8)", $parametersJson )
- or die("Can't open \$filename\": $!\n");
-
- my $json = JSON->new;
- my @json_obj;
- while ( my $json_text = <$json_fh> ) {
- my $data = $json->decode($json_text);
-
- if ( $data->{"name"} eq "kickstart.files.location" ) {
- $data->{"value"} = $kickstartFilesFqn;
- }
- push @json_obj, $data;
- }
- writeJson( $parametersJson, @json_obj );
-
- execCommand( "/bin/cp", "/opt/traffic_ops/install/data/perl/osversions.cfg", $kickstartFilesFqn );
-
- if ( !$skip ) {
- print "\nUncompressing CentOS ISO kickstart tarball.\n";
- print "\nFirst creating $kickstartFilesFqn.\n";
- execCommand( "/bin/mkdir", "-p", $kickstartFilesFqn );
- print "\nUncompressing $centosTarballFqn.\n";
- execCommand( "/bin/tar", "-xzf", $centosTarballFqn, "-C", $kickstartFilesFqn );
- }
-
- print "\nTraffic Ops URL: $parameters->{'tm.url'}\n";
- print "Traffic Ops Info URL: $parameters->{'tm.infourl'}\n";
- print "Domainname: $parameters->{domainname}\n";
- print "CDN Name: $parameters->{cdnname}\n";
- print "GeoLocation Polling URL: $parameters->{'geolocation.polling.url'}\n";
- print "CoverageZone Polling URL: $parameters->{'coveragezone.polling.url'}\n\n";
- my $ans = promptUser( "Is the above information correct (y/n)", "n" );
- if ( $ans eq 'y' ) {
- last;
- }
- }
- writeJson( $post_install_cfg, $parameters );
- print "Install information has been saved to $post_install_cfg\n\n";
-
- print "\nAdding an administration user to the Traffic Ops database.\n\n";
- my %user = ();
- $tmAdminUser = promptUser( "Administration username for Traffic Ops", 'admin' );
- $user{username} = $tmAdminUser;
- $tmAdminPw = promptPasswordVerify("Password for the admin user $tmAdminUser");
- $user{password} = sha1_hex($tmAdminPw);
-
- writeJson( $users_file, \%user );
-
- my $ans = promptUser( "Do you wish to create an ldap configuration for access to traffic ops [y/n] ?", "n" );
- if ( $ans eq "y" ) {
- my %ldapconf = readJson($ldap_conf);
- while (1) {
- $ldapconf{host} = promptUser( "LDAP server hostname", $ldapconf{host} || "ldap.foobar.com" );
- $ldapconf{admin_dn} = promptUser( "LDAP Admin DN", $ldapconf{admin_dn} || 'admin@foobar.com' );
- $ldapconf{admin_pass} = promptPasswordVerify("LDAP Admin Password");
- $ldapconf{search_base} = promptUser( "LDAP Search Base", "dc=foobar,dc=com" );
- my $correct = promptUser( "Are the above values correct [y/n]?", "y" );
- if ( $correct eq 'y' ) {
- last;
- }
- }
- writeJson( $ldap_conf, \%ldapconf );
- print "The ldap configuration has been saved.\n\n";
- }
-
- # Prompt for new secret
- writeSecret($cdn_conf);
-
- #
- # Call mysql initialization script.
- #
- print "Creating database\n";
- my $result = execCommand( "/opt/traffic_ops/install/bin/create_db", $dbAdminUser, $dbAdminPw );
- if ( $result != 0 ) {
- print "failed to create the database.\n";
- exit 1;
- }
-
- print "Setting up database\n";
- chdir("/opt/traffic_ops/app");
- $result = execCommand( "/usr/bin/perl", "db/admin.pl", "--env=production", "setup" );
-
- if ( $result != 0 ) {
- print "Database initialization failed.\n";
- exit 2;
- }
- else {
- print "Database initialization succeeded.\n";
- }
-
- $result = execCommand( "/opt/traffic_ops/install/bin/dataload", $dbAdminUser, $dbAdminPw );
- if ( $result != 0 ) {
- print "failed to load seed data.\n";
- exit 1;
- }
-
- print "Downloading MaxMind data.\n";
- chdir("/opt/traffic_ops/app/public/routing");
- $result = execCommand("/usr/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz");
- if ( $result != 0 ) {
- print "failed to download MaxMind data.\n";
-
- # exit 1;
- }
-
- print "Copying coverage zone file to public dir.\n";
- $result = execCommand("/bin/mv /opt/traffic_ops/app/public/coverage-zone.json .");
- if ( $result != 0 ) {
- print "failed to copy coverage zone file.\n";
-
- # exit 1;
- }
-
- if ( -x "/usr/bin/openssl" ) {
- print "\nInstalling SSL Certificates.\n\n";
- $result = execCommand("/opt/traffic_ops/install/bin/generateCert");
-
- if ( $result != 0 ) {
- print "\nSSL Certificate Installation failed.\n";
- exit 3;
- }
- else {
- print "\nSSL Certificates have been installed.\n";
- }
- }
- else {
- print "Unable to install SSL certificates as openssl is not installed.\n";
- print "Install openssl and then run /opt/traffic_ops/install/bin/generateCert to install SSL certificates.\n";
- exit 4;
- }
-} # end of Init
-
-sub writeSecret {
- print "\n\nTraffic Ops requires a secret key to generate authentication cookies.\n\n";
-
- # read conf file -- see if secrets already there
- my $cdnh = do $cdn_conf;
- unless ( ref($cdnh) eq 'HASH' ) {
- my $err = $@ || $! || ' -- not a HASH';
- if ($err) {
- print "Could not load $cdn_conf $err";
- exit 4;
- }
- }
-
- # newSecret
- my $secrets = $cdnh->{secrets};
- if ( ( ref $secrets eq 'ARRAY' ) && scalar @$secrets > 0 ) {
- print "One or more secrets found in $cdn_conf.\n";
- my $ans = promptUser( " Do want to add a new one (only 2 will be kept) [y/n] ?", "y" );
- if ( $ans eq "n" ) {
-
- # nothing further to do...
- return;
- }
- }
- my $new_secret = "";
- while ( length $new_secret == 0 ) {
- print "Adding a new secret.\n";
- my $ans = promptUser( " Do you want one generated for you [y/n] ?", "y" );
- if ( $ans eq "n" ) {
- $new_secret = promptUser( "Secret key:", "" );
- }
- else {
-
- # create random word 12 chars long
- $new_secret = randomWord(12);
- }
- }
-
- # keep 2 at most..
- unshift( @$secrets, $new_secret );
- if ( scalar @$secrets > 2 ) {
- $#{$secrets} = 1;
- }
-
- # dump conf data in compact but readable form
- my $dumper = Data::Dumper->new( [$cdnh] );
- $dumper->Indent(1)->Terse(1)->Quotekeys(0);
-
- # write whole config to temp file in pwd (keeps in same filesystem)
- my $tmpfile = File::Temp->new(DIR => '.');
- print $tmpfile $dumper->Dump();
- close $tmpfile;
-
- # rename current config file to something unique so it's not lost
- my $backup_num = 0;
- my $backup_name;
- do {
- $backup_num++;
- $backup_name = "$cdn_conf.backup$backup_num";
- } while ( -e $backup_name );
- rename( $cdn_conf, $backup_name ) or die("rename(): $!");
-
- # rename temp file to cdn.conf and set ownership/permissions same as backup
- my @stats = stat($backup_name);
- my ( $uid, $gid, $perm ) = @stats[ 4, 5, 2 ];
- rename( $tmpfile, $cdn_conf ) or die("rename(): $!");
-
- chown $uid, $gid, $cdn_conf;
- chmod $perm, $cdn_conf;
+# userInput: The entire input config file which is either user input or the defaults
+# fileName: The name of the output config file given by the input config file
+#
+# Loops through an input config file and determines answers to each question using getField
+# and returns the hash of answers
+
+sub getConfig {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %config;
+
+ if ( !defined $userInput->{$fileName} ) {
+ logger( "No $fileName found in config", "error" );
+ }
+
+ logger( "===========$fileName===========", "info" );
+
+ foreach my $var ( @{ $userInput->{$fileName} } ) {
+ my $question = getConfigQuestion($var);
+ my $hidden = $var->{"hidden"} if ( exists $var->{"hidden"} );
+ my $answer = $config{ $var->{"config_var"} } = getField( $question, $var->{$question}, $hidden );
+
+ $config{ $var->{"config_var"} } = $answer;
+ if ( !$hidden ) {
+ logger( "$question: $answer", "info" );
+ }
+ }
+ return %config;
}
-chdir("/opt/traffic_ops/install/bin");
-
-$parameters = readJson($post_install_cfg);
-if ( -f $reconfigure ) {
- my $rc = execCommand( "/opt/traffic_ops/install/bin/build_trafficops_perl_library", "-i" );
- if ( $rc != 0 ) {
- print "ERROR: failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error.\n";
- exit 5;
- }
- $rc = execCommand( "./download_web_deps", "-i" );
- if ( $rc != 0 ) {
- print "ERROR: failed to install Traffic Ops Web dependencies, check the console output and rerun postinstall once you've resolved the error.\n";
- }
- init();
- unlink($reconfigure);
+# userInput: The entire input config file which is either user input or the defaults
+# dbFileName: The filename of the output config file for the database
+# toDBFileName: The filename of the output config file for the Traffic Ops database
+#
+# Generates a config file for the database based on the questions and answers in the input config file
+
+sub generateDbConf {
+ my $userInput = shift;
+ my $dbFileName = shift;
+ my $toDBFileName = shift;
+
+ my %dbconf = getConfig( $userInput, $dbFileName );
+ $dbconf{"description"} = "$dbconf{type} database on $dbconf{hostname}:$dbconf{port}";
+ make_path( dirname($dbFileName), { mode => 0755 } );
+ writeJson( $dbFileName, \%dbconf );
+ logger( "Database configuration has been saved", "info" );
+
+ # broken out into separate file/config area
+ my %todbconf = getConfig( $userInput, $toDBFileName );
+
+ # No YAML library installed, but this is a simple file..
+ open( my $fh, '>', $toDBFileName ) or errorOut("Can't write to $toDBFileName!");
+ print $fh "production:\n";
+ print $fh " driver: ", getDbDriver() . "\n";
+ print $fh " open: tcp:$dbconf{hostname}:$dbconf{port}*$dbconf{dbname}/$dbconf{user}/$dbconf{password}\n";
+ close $fh;
+
+ return \%todbconf;
}
-else {
- my $rc = execCommand("/opt/traffic_ops/install/bin/build_trafficops_perl_library");
- if ( $rc != 0 ) {
- print "ERROR: failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error.\n";
- exit 6;
- }
- $rc = execCommand( "./download_web_deps", "-i" );
- if ( $rc != 0 ) {
- print "ERROR: failed to install Traffic Ops Web dependencies, check the console output and rerun postinstall once you've resolved the error.\n";
- }
+
+# userInput: The entire input config file which is either user input or the defaults
+# fileName: The filename of the output config file
+#
+# Generates a config file for the CDN
+
+sub generateCdnConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %cdnConfiguration = getConfig( $userInput, $fileName );
+
+ # First, read existing one -- already loaded with a bunch of stuff
+ my $cdnConf;
+ if ( -f $fileName ) {
+ $cdnConf = Safe->new->rdo($fileName) or errorOut("Error loading $fileName: $@");
+ }
+ if ( lc $cdnConfiguration{genSecret} =~ /^y(?:es)?/ ) {
+ my @secrets = @{ $cdnConf->{secrets} };
+ my $newSecret = randomWord();
+ unshift @secrets, randomWord();
+ if ( $cdnConfiguration{keepSecrets} > 0 && $#secrets > $cdnConfiguration{keepSecrets} - 1 ) {
+
+ # Shorten the array to requested length
+ $#secrets = $cdnConfiguration{keepSecrets} - 1;
+ }
+ }
+ writePerl( $fileName, $cdnConf );
}
-sub profile_replace {
- my($profile) = @_;
- my $profile_bak = $profile . ".bak";
- rename($profile, $profile_bak) or die("rename(): $!");
- open(my $fh, '<', $profile_bak) or die("open(): $!");
- open(my $ofh, '>', $profile) or die("open(): $!");
- while (<$fh>) {
- s/{{.TmUrl}}/$parameters->{'tm.url'}/g;
- s/{{.TmInfoUrl}}/$parameters->{"tminfo.url"}/g;
- s/{{.TmInstanceName}}/$parameters->{"cdnname"}/g;
- s/{{.GeolocationPollingUrl}}/$parameters->{"geolocation.polling.url"}/g;
- s/{{.Geolocation6PollingUrl}}/$parameters->{"geolocation6.polling.url"}/g;
- s/{{.TmUrl}}/$parameters->{'tm.url'}/g;
- s/{{.TmToolName}}/Traffic Ops/g;
- s/{{.HealthPollingInterval}}/$parameters->{"health.polling.interval"}/g;
- s/{{.CoveragezonePollingUrl}}/$parameters->{"coveragezone.polling.url"}/g;
- s/{{.DomainName}}/$parameters->{"domainname"}/g;
- s/{{.TldSoaAdmin}}/$parameters->{"tld.soa.admin"}/g;
- s/{{.DrivePrefix}}/$parameters->{"Drive_Prefix"}/g;
- s/{{.HealthThresholdLoadavg}}/$parameters->{"health.threshold.loadavg"}/g;
- s/{{.HealthThresholdAvailableBandwidthInKbps}}/$parameters->{"health.threshold.availableBandwidthInKbps"}/g;
- s/{{.RAMDrivePrefix}}/$parameters->{"RAM_Drive_Prefix"}/g;
- s/{{.RAMDriveLetters}}/$parameters->{"RAM_Drive_Letters"}/g;
- s/{{.HealthConnectionTimeout}}/$parameters->{"health.connection.timeout"}/g;
- s#{{.CronOrtSyncds}}#*/15 * * * * root /opt/ort/traffic_ops_ort.pl syncds warn $parameters->{'tm.url'} $tmAdminUser:$tmAdminPw > /tmp/ort/syncds.log 2>&1#g;
- print $ofh $_;
- }
- close $fh;
- close $ofh;
- unlink $profile_bak;
+# userInput: The entire input config file which is either user input or the defaults
+# fileName: The filename of the output config file
+#
+# Generates an LDAP config file
+
+sub generateLdapConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my $useLdap = $userInput->{$fileName}[0]->{"Do you want to set up LDAP?"};
+
+ if ( !lc $useLdap =~ /^y(?:es)?/ ) {
+ logger( "Not setting up ldap", "info" );
+ return;
+ }
+
+ my %ldapConf = getConfig( $userInput, $fileName );
+
+ make_path( dirname($fileName), { mode => 0755 } );
+ writeJson( $fileName, \%ldapConf );
}
-sub replace_profile_templates() {
- while (!defined $parameters->{'tm.url'} || $parameters->{'tm.url'} eq "") {
- $parameters->{'tm.url'} = InstallUtils::promptUser ("Traffic Ops url", "https://localhost");
- }
- while (!defined $parameters->{"tminfo.url"} || $parameters->{"tminfo.url"} eq "") {
- $parameters->{"tminfo.url"} = "$parameters->{'tm.url'}/info"
- }
- while (!defined $parameters->{"cdnname"} || $parameters->{"cdnname"} eq "") {
- $parameters->{"cdnname"} = InstallUtils::promptUser ("Human-readable CDN Name. (No whitespace, please)", "kabletown_cdn");
- }
- while (!defined $parameters->{"geolocation.polling.url"} || $parameters->{"geolocation.polling.url"} eq "") {
- $parameters->{"geolocation.polling.url"} = "$parameters->{'tm.url'}/routing/GeoIP2-City.mmdb.gz";
- }
- while (!defined $parameters->{"geolocation6.polling.url"} || $parameters->{"geolocation6.polling.url"} eq "") {
- $parameters->{"geolocation6.polling.url"} = "$parameters->{'tm.url'}/routing/GeoIP2-Cityv6.mmdb.gz";
- }
- while (!defined $parameters->{"health.polling.interval"} || $parameters->{"health.polling.interval"} eq "") {
- $parameters->{"health.polling.interval"} = InstallUtils::promptUser ("Health Polling Interval (milliseconds)", "8000");
- }
- while (!defined $parameters->{"coveragezone.polling.url"} || $parameters->{"coveragezone.polling.url"} eq "") {
- $parameters->{"coveragezone.polling.url"} = "$parameters->{'tm.url'}/routing/coverage-zone.json"
- }
- while (!defined $parameters->{"domainname"} || $parameters->{"domainname"} eq "") {
- $parameters->{"domainname"} = InstallUtils::promptUser ("DNS sub-domain for which your CDN is authoritative", "cdn1.kabletown.net");
- }
- while (!defined $parameters->{"tld.soa.admin"} || $parameters->{"tld.soa.admin"} eq "") {
- $parameters->{"tld.soa.admin"} = InstallUtils::promptUser ("TLD SOA admin", "traffic_ops");
- }
- while (!defined $parameters->{"Drive_Prefix"} || $parameters->{"Drive_Prefix"} eq "") {
- $parameters->{"Drive_Prefix"} = InstallUtils::promptUser ("TrafficServer Drive Prefix", "/dev/sd");
- }
- while (!defined $parameters->{"RAM_Drive_Prefix"} || $parameters->{"RAM_Drive_Prefix"} eq "") {
- $parameters->{"RAM_Drive_Prefix"} = InstallUtils::promptUser ("TrafficServer RAM Drive Prefix", "/dev/ram");
- }
- while (!defined $parameters->{"RAM_Drive_Letters"} || $parameters->{"RAM_Drive_Letters"} eq "") {
- $parameters->{"RAM_Drive_Letters"} = InstallUtils::promptUser ("TrafficServer RAM Drive Letters (comma separated)", "0,1,2,3,4,5,6,7");
- }
- while (!defined $parameters->{"health.threshold.loadavg"} || $parameters->{"health.threshold.loadavg"} eq "") {
- $parameters->{"health.threshold.loadavg"} = InstallUtils::promptUser ("Health Threshold Load Average", "25");
- }
- while (!defined $parameters->{"health.threshold.availableBandwidthInKbps"} || $parameters->{"health.threshold.availableBandwidthInKbps"} eq "" || $parameters->{"health.threshold.availableBandwidthInKbps"} eq ">") {
- $parameters->{"health.threshold.availableBandwidthInKbps"} = ">" . InstallUtils::promptUser ("Health Threshold Available Bandwidth in Kbps", "1750000");
- }
- while (!defined $parameters->{"health.connection.timeout"} || $parameters->{"health.connection.timeout"} eq "") {
- $parameters->{"health.connection.timeout"} = InstallUtils::promptUser ("Traffic Server Health Connection Timeout (milliseconds)", "2000");
- }
-
- profile_replace($profile_dir . "profile.global.traffic_ops");
- profile_replace($profile_dir . "profile.traffic_monitor.traffic_ops");
- profile_replace($profile_dir . "profile.traffic_router.traffic_ops");
- profile_replace($profile_dir . "profile.trafficserver_edge.traffic_ops");
- profile_replace($profile_dir . "profile.trafficserver_mid.traffic_ops");
- writeJson( $post_install_cfg, $parameters );
+sub generateUsersConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %user = ();
+ my %config = getConfig( $userInput, $fileName );
+
+ $user{username} = $config{tmAdminUser};
+ $user{password} = sha1_hex( $config{tmAdminPw} );
+
+ writeJson( $fileName, \%user );
+ $user{password} = $config{tmAdminPw};
+ return \%user;
}
-# Takes the Traffic Ops URI, user, and password.
-# Returns the cookie, or the empty string on error
-sub get_traffic_ops_cookie {
- my($uri, $user, $pass) = @_;
-
- my $loginUri = "/api/1.2/user/login";
-
- my $curl = WWW::Curl::Easy->new;
- my $response_body = "";
- open(my $fileb, ">", \$response_body);
- my $loginData = JSON::encode_json({ u => $user, p => $pass});
- $curl->setopt(WWW::Curl::Easy::CURLOPT_URL, $uri . $loginUri);
- $curl->setopt(WWW::Curl::Easy::CURLOPT_SSL_VERIFYPEER, 0);
- $curl->setopt(WWW::Curl::Easy::CURLOPT_HEADER, 1); # include header in response
- $curl->setopt(WWW::Curl::Easy::CURLOPT_NOBODY, 1); # disclude body in response
- $curl->setopt(WWW::Curl::Easy::CURLOPT_POST, 1);
- $curl->setopt(WWW::Curl::Easy::CURLOPT_POSTFIELDS, $loginData);
- $curl->setopt(WWW::Curl::Easy::CURLOPT_WRITEDATA, $fileb); # put response in this var
- $curl->perform();
-
- my $cookie = $response_body;
- if($cookie =~ /mojolicious=(.*); expires/)
- {
- $cookie = $1;
- }
- else
- {
- $cookie = ""
- }
- return $cookie;
+sub generateProfilesDir {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my $userIn = $userInput->{$fileName};
}
-# Takes the filename of a Traffic Ops (TO) profile to import, the TO URI, and the TO login cookie
-sub profile_import_single {
- my($profileFilename, $uri, $trafficOpsCookie) = @_;
- print "Importing Profiles with: " . "curl -v -k -X POST -H \"Cookie: mojolicious=$trafficOpsCookie\" -F \"filename=$profileFilename\" -F \"profile_to_import=\@$profileFilename\" $uri/profile/doI\
-mport";
- my $rc = execCommand("curl -v -k -X POST -H \"Cookie: mojolicious=$trafficOpsCookie\" -F \"filename=$profileFilename\" -F \"profile_to_import=\@$profileFilename\" $uri/profile/doImport");
- if ( $rc != 0 ) {
- print "ERROR: failed to import Traffic Ops profile, check the console output and rerun postinstall once you've resolved the error.\n";
+sub generateOpenSSLConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ if ( !defined $userInput->{$fileName} ) {
+ logger( "No OpenSSL Configuration - questions will be asked", "info" );
+
+ # write an empty config so openssl does not use an old file
+ writeJson( $fileName, my %emptyConfig );
+ return;
}
+
+ my %config = getConfig( $userInput, $fileName );
+
+ writeJson( $fileName, \%config );
+ return \%config;
}
-sub import_profiles() {
- while (length $tmAdminUser == 0) {
- $tmAdminUser = InstallUtils::promptUser ("Administration username for Traffic Ops");
- }
- while ($tmAdminPw eq "") {
- $tmAdminPw = InstallUtils::promptUser ("Password for the admin user $tmAdminUser", "", 1);
- }
- while (!defined $parameters->{'tm.url'} || length $parameters->{'tm.url'} == 0) {
- $parameters->{'tm.url'} = InstallUtils::promptUser ("Traffic Ops url", "https://localhost");
- }
-
- print "Importing profiles...\n";
- # \todo take as params
- my $toUri = $parameters->{'tm.url'};
- my $toUser = $tmAdminUser;
- my $toPass = $tmAdminPw;
-
- my $toCookie = get_traffic_ops_cookie($toUri, $toUser, $toPass);
-
- print "Got cookie: " . $toCookie;
-
- # \todo use an array?
- print "Importing Global profile...\n";
- profile_import_single($profile_dir . "profile.global.traffic_ops", $toUri, $toCookie);
- print "Importing Traffic Monitor profile...\n";
- profile_import_single($profile_dir . "profile.traffic_monitor.traffic_ops", $toUri, $toCookie);
- print "Importing Traffic Router profile...\n";
- profile_import_single($profile_dir . "profile.traffic_router.traffic_ops", $toUri, $toCookie);
- print "Importing TrafficServer Edge profile...\n";
- profile_import_single($profile_dir . "profile.trafficserver_edge.traffic_ops", $toUri, $toCookie);
- print "Importing TrafficServer Mid profile...\n";
- profile_import_single($profile_dir . "profile.trafficserver_mid.traffic_ops", $toUri, $toCookie);
- print "Finished Importing Profiles.\n";
+sub generateParamConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %config = getConfig( $userInput, $fileName );
+ writeJson( $fileName, \%config );
+ return \%config;
}
-print "\nStarting Traffic Ops.\n\n";
-execCommand("/sbin/service traffic_ops start");
-
-print "\nWaiting for Traffic Ops to start.\n\n";
-sleep(5);
-
-sub profiles_exist {
- if ( -f $reconfigure_defaults ) {
- print "Default profiles were previously created. Remove " . $reconfigure_defaults . " to create again.\n";
- return 1;
- }
-
- while ( length $tmAdminUser == 0 ) {
- $tmAdminUser =
- InstallUtils::promptUser("Administration username for Traffic Ops");
- }
- while ( $tmAdminPw eq "" ) {
- $tmAdminPw =
- InstallUtils::promptUser( "Password for the admin user $tmAdminUser",
- "", 1 );
- }
- while ( !defined $parameters->{'tm.url'}
- || length $parameters->{'tm.url'} == 0 )
- {
- $parameters->{'tm.url'} =
- InstallUtils::promptUser( "Traffic Ops url", "https://localhost" );
- }
-
- my $uri = $parameters->{'tm.url'};
- my $toCookie = get_traffic_ops_cookie( $parameters->{'tm.url'},
- $tmAdminUser, $tmAdminPw );
-
- my $profileEndpoint = "/api/1.2/profiles.json";
-
- my $ua = LWP::UserAgent->new;
- $ua->ssl_opts( verify_hostname => 0, SSL_verify_mode => 0x00 );
- my $req = HTTP::Request->new( GET => $uri . $profileEndpoint );
- $req->header( 'Cookie' => "mojolicious=" . $toCookie );
- my $resp = $ua->request($req);
-
- if ( !$resp->is_success ) {
- print "Error checking if profiles exist: " . $resp->status_line . "\n";
- return 1; # return true, so we don't attempt to create profiles
- }
- my $message = $resp->decoded_content;
-
- my $profiles = JSON->new->utf8->decode($message);
- if ( ( !defined $profiles->{"response"} )
- || ( ref $profiles->{"response"} ne 'ARRAY' ) )
- {
- print "Error checking if profiles exist: invalid JSON: $message\n";
- return 1; # return true, so we don't attempt to create profiles
- }
-
- my $num_profiles = scalar( @{ $profiles->{"response"} } );
- print "Existing Profile Count: $num_profiles\n";
-
- my %initial_profiles = (
- "INFLUXDB" => 1,
- "RIAK_ALL" => 1,
- "TRAFFIC_STATS" => 1,
- "TRAFFIC_PORTAL" => 1
- );
-
- my $profiles_response = $profiles->{"response"};
- foreach my $profile (@$profiles_response) {
- if ( !exists $initial_profiles{ $profile->{"name"} } ) {
- print "Found existing profile (" . $profile->{"name"} . ")\n";
- open( my $reconfigure_defaults_file, '>', $reconfigure_defaults ) or die("Failed to open() $reconfigure_defaults: $!");
- close( $reconfigure_defaults_file );
- return 1;
- }
- }
- return 0;
+# check default values for missing config_var parameter
+sub sanityCheckDefaults {
+ foreach my $file ( ( keys $::defaultInputs ) ) {
+ foreach my $defaultValue ( @{ $::defaultInputs->{$file} } ) {
+ my $question = getConfigQuestion($defaultValue);
+
+ if ( !defined $defaultValue->{"config_var"}
+ || $defaultValue->{"config_var"} eq "" )
+ {
+ errorOut("Question '$question' in file '$file' has no config_var");
+ }
+ }
+ }
}
-if ( !profiles_exist() ) {
- print "Creating default profiles...\n";
- replace_profile_templates();
- import_profiles();
- profiles_exist(); # call again to create $reconfigure_defaults file if import was successful
+# userInput: The entire input config file which is either user input or the defaults
+#
+# Checks the input config file against the default inputs. If there is a question located in the default inputs which
+# is not located in the input config file it will output a warning message.
+
+sub sanityCheckConfig {
+ my $userInput = shift;
+ my $diffs = 0;
+
+ foreach my $file ( ( keys $::defaultInputs ) ) {
+ if ( !defined $userInput->{$file} ) {
+ logger( "File '$file' found in defaults but not config file", "warn" );
+ $userInput->{$file} = [];
+ }
+
+ foreach my $defaultValue ( @{ $::defaultInputs->{$file} } ) {
+
+ my $found = 0;
+ foreach my $configValue ( @{ $userInput->{$file} } ) {
+ if ( $defaultValue->{"config_var"} eq $configValue->{"config_var"} ) {
+ $found = 1;
+ }
+ }
+
+ # if the question is not found in the config file add it from defaults
+ if ( !$found ) {
+ my $question = getConfigQuestion($defaultValue);
+ logger( "Question '$question' found in defaults but not in '$file'", "warn" );
+
+ my %temp;
+ my $answer;
+ my $hidden = exists $defaultValue->{"hidden"} && $defaultValue->{"hidden"} ? 1 : 0;
+
+ # in automatic mode add the missing question with default answer
+ if ($::automatic) {
+ $answer = $defaultValue->{$question};
+ logger( "Adding question '$question' with default answer " . ( $hidden ? "" : "'$answer'" ), "info" );
+ }
+
+ # in interactive mode prompt the user for answer to missing question
+ else {
+ logger( "Prompting user for answer", "info" );
+ if ($hidden) {
+ $answer = promptPasswordVerify($question);
+ }
+ else {
+ $answer = promptUser( $question, $defaultValue->{$question} );
+ }
+ }
+
+ %temp = (
+ "config_var" => $defaultValue->{"config_var"},
+ $question => $answer
+ );
+
+ if ($hidden) {
+ $temp{"hidden"} .= "true";
+ }
+
+ push $userInput->{$file}, \%temp;
+
+ $diffs++;
+ }
+ }
+ }
+
+ logger( "File sanity check complete - found $diffs difference" . ( $diffs == 1 ? "" : "s" ), "info" );
}
-else {
- print "Not creating default profiles.\n";
+
+# A function which returns the default inputs data structure. These questions and answers will be used if there is no
+# user input config file or if there are questions in the input config file which do not have answers
+
+sub getDefaults {
+ return {
+ $::databaseConfFile => [
+ {
+ "Database type" => "mysql",
+ "config_var" => "type"
+ },
+ {
+ "Database name" => "traffic_ops",
+ "config_var" => "dbname"
+ },
+ {
+ "Database server hostname IP or FQDN" => "localhost",
+ "config_var" => "hostname"
+ },
+ {
+ "Database port number" => "3306",
+ "config_var" => "port"
+ },
+ {
+ "Traffic Ops database user" => "traffic_ops",
+ "config_var" => "user"
+ },
+ {
+ "Password for Traffic Ops database user" => "",
+ "config_var" => "password",
+ "hidden" => "true"
+ }
+ ],
+ $::dbConfFile => [
+ {
+ "Database server root (admin) user" => "root",
+ "config_var" => "dbAdminUser"
+ },
+ {
+ "Password for database server admin" => "",
+ "config_var" => "dbAdminPw",
+ "hidden" => "true"
+ }
+ ],
+ $::cdnConfFile => [
+ {
+ "Generate a new secret?" => "yes",
+ "config_var" => "genSecret"
+ },
+ {
+ "Number of secrets to keep?" => "10",
+ "config_var" => "keepSecrets"
+ }
+ ],
+ $::ldapConfFile => [
+ {
+ "Do you want to set up LDAP?" => "no",
+ "config_var" => "setupLdap"
+ },
+ {
+ "LDAP server hostname" => "",
+ "config_var" => "hostname"
+ },
+ {
+ "LDAP Admin DN" => "",
+ "config_var" => "admin_dn"
+ },
+ {
+ "LDAP Admin Password" => "",
+ "config_var" => "password",
+ "hidden" => "true"
+ },
+ {
+ "LDAP Search Base" => "",
+ "config_var" => "search_base"
+ }
+ ],
+ $::usersConfFile => [
+ {
+ "Administration username for Traffic Ops" => "admin",
+ "config_var" => "tmAdminUser"
+ },
+ {
+ "Password for the admin user" => "",
+ "config_var" => "tmAdminPw",
+ "hidden" => "true"
+ }
+ ],
+ $::profilesConfFile => [],
+ $::opensslConfFile => [
+ {
+ "Do you want to generate a certificate?" => "yes",
+ "config_var" => "genCert"
+ },
+ {
+ "Country Name (2 letter code)" => "XX",
+ "config_var" => "country"
+ },
+ {
+ "State or Province Name (full name)" => "San Jose",
+ "config_var" => "state"
+ },
+ {
+ "Locality Name (eg, city)" => "Default City",
+ "config_var" => "locality"
+ },
+ {
+ "Organization Name (eg, company)" => "Default Company Ltd",
+ "config_var" => "company"
+ },
+ {
+ "Organizational Unit Name (eg, section)" => "",
+ "config_var" => "org_unit"
+ },
+ {
+ "Common Name (eg, your name or your server's hostname)" => "example.com",
+ "config_var" => "common_name"
+ },
+ {
+ "RSA Passphrase" => "",
+ "config_var" => "rsaPassword",
+ "hidden" => "true"
+ }
+ ],
+ $::paramConfFile => [
+ {
+ "Traffic Ops url" => "https://localhost",
+ "config_var" => "tm.url"
+ },
+ {
+ "Human-readable CDN Name. (No whitespace, please)" => "kabletown_cdn",
+ "config_var" => "cdn_name"
+ },
+ {
+ "Health Polling Interval (milliseconds)" => "8000",
+ "config_var" => "health_polling_int"
+ },
+ {
+ "DNS sub-domain for which your CDN is authoritative" => "cdn1.kabletown.net",
+ "config_var" => "dns_subdomain"
+ },
+ {
+ "TLD SOA admin" => "traffic_ops",
+ "config_var" => "soa_admin"
+ },
+ {
+ "TrafficServer Drive Prefix" => "/dev/sd",
+ "config_var" => "driver_prefix"
+ },
+ {
+ "TrafficServer RAM Drive Prefix" => "/dev/ram",
+ "config_var" => "ram_drive_prefix"
+ },
+ {
+ "TrafficServer RAM Drive Letters (comma separated)" => "0,1,2,3,4,5,6,7",
+ "config_var" => "ram_drive_letters"
+ },
+ {
+ "Health Threshold Load Average" => "25",
+ "config_var" => "health_thresh_load_avg"
+ },
+ {
+ "Health Threshold Available Bandwidth in Kbps" => "1750000",
+ "config_var" => "health_thresh_kbps"
+ },
+ {
+ "Traffic Server Health Connection Timeout (milliseconds)" => "2000",
+ "config_var" => "health_connect_timeout"
+ }
+
+ ]
+ };
}
-#print "\nRunning smoke tests.\n\n";
-#$rc = execCommand ("/opt/traffic_ops/install/bin/systemtest", "localhost", $user{username}, $tmAdminPw, "0");
-{
- my $ans = promptUser( "\nInstall Cron entry to clean install .iso files older than 7 days? [y/n]", "n" );
- if ($ans eq "y" || $ans eq "Y") {
- execCommand( "/bin/echo \"00 04 * * * root /bin/find /opt/traffic_ops/app/public/iso/*.iso -mtime +7 -exec /bin/rm {} \; > /dev/null 2>&1 \" > /etc/cron.d/trafops_clean_isos" );
- }
+# carried over from old postinstall
+#
+# todbconf: The database configuration to be used
+# opensslconf: The openssl configuration if any
+
+sub setupDatabase {
+ my $todbconf = shift;
+ my $opensslconf = shift;
+ my $genCert = shift;
+
+ #
+ # Call mysql initialization script.
+ #
+ logger( "Creating database with user: $todbconf->{dbAdminUser}", "info" );
+ my $result = execCommand( "/opt/traffic_ops/install/bin/create_db", $todbconf->{dbAdminUser}, $todbconf->{dbAdminPw} );
+ if ( $result != 0 ) {
+ errorOut("Failed to create the database");
+ }
+
+ logger( "Setting up database", "info" );
+ chdir("/opt/traffic_ops/app");
+ $result = execCommand( "/usr/bin/perl", "db/admin.pl", "--env=production", "setup" );
+
+ if ( $result != 0 ) {
+ errorOut("Database initialization failed");
+ }
+ else {
+ logger( "Database initialization succeeded", "info" );
+ }
+
+ $result = execCommand( "/opt/traffic_ops/install/bin/dataload", $todbconf->{dbAdminUser}, $todbconf->{dbAdminPw} );
+ if ( $result != 0 ) {
+ logger( "Failed to load seed data", "error" );
+ }
+
+ logger( "Downloading MaxMind data", "info" );
+ chdir("/opt/traffic_ops/app/public/routing");
+ $result = execCommand("/usr/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz");
+ if ( $result != 0 ) {
+ logger( "Failed to download MaxMind data", "error" );
+ }
+
+ logger( "Copying coverage zone file to public dir", "info" );
+ $result = execCommand("/bin/mv /opt/traffic_ops/app/public/coverage-zone.json .");
+ if ( $result != 0 ) {
+ logger( "Failed to copy coverage zone file", "error" );
+ }
+
+ if ( lc $genCert =~ /^y(?:es)?/ ) {
+ if ( -x "/usr/bin/openssl" ) {
+ logger( "Installing SSL Certificates", "info" );
+ $result = GenerateCert::createCert($opensslconf);
+
+ if ( $result != 0 ) {
+ errorOut("SSL Certificate Installation failed");
+ }
+ else {
+ logger( "SSL Certificates have been installed", "info" );
+ }
+ }
+ else {
+ logger( "Unable to install SSL certificates as openssl is not installed", "error" );
+ logger( "Install openssl and then run /opt/traffic_ops/install/bin/generateCert to install SSL certificates", "error" );
+ exit 4;
+ }
+ }
+ else {
+ logger("Not generating openssl certification", "info");
+ }
}
-{
- my $ans = promptUser( "\nShutdown Traffic Ops [y/n]", "n" );
- if ( $ans eq "y" ) {
- print "\nShutting down Traffic Ops.\n\n";
- execCommand( "/sbin/service", "traffic_ops", "stop" );
- }
+# -cfile - Input File: The input config file used to ask and answer questions
+# -a - Automatic mode: If there are questions in the config file which do not have answers, the script
+# will look to the defaults for the answer. If the answer is not in the defaults
+# the script will exit
+# -r - Reconfigure: Whether or not to reconfigure the database and check perl dependencies - This will rereate the database
+# -defaults - Defaults: Writes out a configuration file with defaults which can be used as input
+# -debug - Debug Mode: More output to the terminal
+# -h - Help: Basic command line help menu
+
+sub main {
+ our $inputFile = "";
+ our $automatic = 0;
+ our $debug = 0;
+ my $help = 0;
+
+ my $usageString = "Usage: postinstall [-a] [-debug] [-defaults] [-r] -cfile=[config_file]\n";
+
+ GetOptions(
+ "cfile=s" => \$inputFile,
+ "automatic" => \$automatic,
+ "reconfigure" => \$reconfigure,
+ "defaults" => \$dumpDefaults,
+ "debug" => \$debug,
+ "help" => \$help
+ ) or die($usageString);
+
+ # stores the default questions and answers
+ our $defaultInputs = getDefaults();
+
+ if ($help) {
+ print $usageString;
+ exit(0);
+ }
+
+ # check if the user running postinstall is root
+ if ( $ENV{USER} ne "root" ) {
+ errorOut("You must run this script as the root user");
+ }
+
+ if ( -f "$logFile.gz" ) {
+ execCommand( "/bin/gunzip", "$logFile.gz" );
+ }
+
+ logger( "Starting postinstall", "info" );
+
+ logger( "Debug is on", "info" );
+
+ if ($::automatic) {
+ logger( "Running in automatic mode", "info" );
+ }
+
+ # check if the reconfigure_file is present on the system - if it is let the user know its deprecated
+ # and exit with an error
+ if ( -f $reconfigure_file ) {
+ logger( "$reconfigure_file file is reprecated - please remove and rerun postinstall", "error" );
+ return;
+ }
+
+ if ($dumpDefaults) {
+ logger( "Writing default configuration file to $outputConfigFile", "info" );
+ writeJson( $outputConfigFile, $::defaultInputs );
+ return;
+ }
+
+ logger( "Postinstall " . ( defined $reconfigure ? "in" : "not" ) . " in reconfigure mode", "info" );
+
+ rotateLog($cpanLogFile);
+
+ if ( -s $::logFile > $maxLogSize ) {
+ logger( "Postinstall log above max size of $maxLogSize bytes - rotating", "info" );
+ rotateLog($logFile);
+ }
+
+ # used to store the questions and answers provided by the user
+ my $userInput;
+
+ # if no input file provided use the defaults
+ if ( $::inputFile eq "" ) {
+ logger( "No input file given - using defaults", "info" );
+ $userInput = $::defaultInputs;
+ }
+ else {
+ logger( "Using input file $::inputFile", "info" );
+
+ # check if the input file exists
+ errorOut("File '$::inputFile' not found") if ( !-f $::inputFile );
+
+ # read and store the input file
+ $userInput = readJson($::inputFile);
+ }
+
+ # sanity check the defaults if running them automatically
+ sanityCheckDefaults();
+
+ # check the input config file against the defaults to check for missing questions
+ sanityCheckConfig($userInput) if ( $inputFile ne "" );
+
+ chdir("/opt/traffic_ops/install/bin");
+
+ # if the reconfigure file exists or reconfigure is set then rebuild the perl deps
+ if ( -f $reconfigure_file || $reconfigure ) {
+ my $rc = BuildPerlDeps::build(1);
+ if ( $rc != 0 ) {
+ errorOut("Failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error");
+ }
+ $rc = execCommand( "./download_web_deps", "-i" );
+ if ( $rc != 0 ) {
+ errorOut("Failed to install Traffic Ops Web dependencies, check the console output and rerun postinstall once you've resolved the error");
+ }
+ }
+ else {
+ my $rc = BuildPerlDeps::build();
+ if ( $rc != 0 ) {
+ errorOut("Failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error");
+ }
+ $rc = execCommand( "./download_web_deps", "-i" );
+ if ( $rc != 0 ) {
+ errorOut("Failed to install Traffic Ops Web dependencies, check the console output and rerun postinstall once you've resolved the error");
+ }
+ }
+
+ # The generator functions handle checking input/default/automatic mode
+
+ # todbconf will be used later when setting up the database
+ my $todbconf = generateDbConf( $userInput, $::databaseConfFile, $::dbConfFile );
+ generateCdnConf( $userInput, $::cdnConfFile );
+ generateLdapConf( $userInput, $::ldapConfFile );
+ my $adminconf = generateUsersConf( $userInput, $::usersConfFile );
+ generateProfilesDir( $userInput, $::profilesConfFile );
+ my $opensslconf = generateOpenSSLConf( $userInput, $::opensslConfFile );
+ my $paramconf = generateParamConf( $userInput, $::paramConfFile );
+
+ # if the reconfigure file exists or the reconfigure command line arg is set then setup the database
+ if ( -f $reconfigure_file || $reconfigure ) {
+ if ($::automatic) {
+ setupDatabase( $todbconf, $::opensslConfFile, $opensslconf->{genCert} );
+ }
+ else {
+ setupDatabase( $todbconf, 0, $opensslconf->{genCert} );
+ }
+ }
+
+ # remove the reconfigure file if it exists
+ if ( -f $reconfigure_file ) {
+ logger( "Removing reconfigure file", "info" );
+ unlink($reconfigure_file);
+ }
+
+ logger( "Starting Traffic Ops", "info" );
+ execCommand("/sbin/service traffic_ops start");
+
+ logger( "Waiting for Traffic Ops to start", "info" );
+
+ if ( !profiles_exist( $adminconf, $paramconf->{"tm.url"} ) ) {
+ logger( "Creating default profiles...", "info" );
+ replace_profile_templates($paramconf);
+ import_profiles($adminconf);
+ profiles_exist( $adminconf, $paramconf->{"tm.url"} ); # call again to create $reconfigure_defaults file if import was successful
+ }
+ else {
+ logger( "Not creating default profiles", "info" );
+ }
+
+ logger("Postinstall complete");
+
+ execCommand( "/bin/gzip", "$logFile" );
}
-print "\nTo start Traffic Ops: service traffic_ops start\n";
-print "To stop Traffic Ops: service traffic_ops stop\n";
-print "\n";
+main;
-exit 0;
+# vi:syntax=perl