You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by mi...@apache.org on 2017/04/17 17:09:46 UTC
[4/9] incubator-trafficcontrol git commit: add postinstall wrapper
add postinstall wrapper
Project: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/commit/9015339f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/tree/9015339f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/diff/9015339f
Branch: refs/heads/master
Commit: 9015339f91fd2a2f5976fdb9a70133e7ee29b7de
Parents: 1f01f21
Author: Dan Kirkwood <da...@gmail.com>
Authored: Thu Apr 13 13:28:46 2017 -0600
Committer: Jeremy Mitchell <mi...@gmail.com>
Committed: Mon Apr 17 11:09:07 2017 -0600
----------------------------------------------------------------------
traffic_ops/install/bin/_postinstall | 831 ++++++++++++++++++++++++++++++
traffic_ops/install/bin/postinstall | 826 +----------------------------
2 files changed, 845 insertions(+), 812 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9015339f/traffic_ops/install/bin/_postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/_postinstall b/traffic_ops/install/bin/_postinstall
new file mode 100755
index 0000000..bfae12d
--- /dev/null
+++ b/traffic_ops/install/bin/_postinstall
@@ -0,0 +1,831 @@
+#!/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
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+use lib qw(/opt/traffic_ops/install/lib /opt/traffic_ops/app/lib /opt/traffic_ops/app/local/lib/perl5);
+
+$ENV{PERL5LIB} = "/opt/traffic_ops/install/lib:/opt/traffic_ops/app/lib:/opt/traffic_ops/app/local/lib/perl5:$ENV{PERL5LIB}";
+$ENV{PATH} = "/usr/local/bin:/opt/traffic_ops/install/bin:$ENV{PATH}";
+
+use strict;
+use warnings;
+
+use Safe;
+use DBI;
+use POSIX;
+use File::Basename qw{dirname};
+use File::Path qw{make_path};
+use Digest::SHA1 qw(sha1_hex);
+use Data::Dumper qw(Dumper);
+use Scalar::Util qw(looks_like_number);
+use Getopt::Long;
+
+use InstallUtils qw{ :all };
+use BuildPerlDeps qw{ :all };
+use GenerateCert qw{ :all };
+use ProfileCleanup qw{ :all };
+
+# paths of the output configuration files
+my $databaseConfFile = "/opt/traffic_ops/app/conf/production/database.conf";
+my $dbConfFile = "/opt/traffic_ops/app/db/dbconf.yml";
+my $cdnConfFile = "/opt/traffic_ops/app/conf/cdn.conf";
+my $ldapConfFile = "/opt/traffic_ops/app/conf/ldap.conf";
+my $usersConfFile = "/opt/traffic_ops/install/data/json/users.json";
+my $profilesConfFile = "/opt/traffic_ops/install/data/profiles/";
+my $opensslConfFile = "/opt/traffic_ops/install/data/json/openssl_configuration.json";
+my $paramConfFile = "/opt/traffic_ops/install/data/json/profiles.json";
+
+my $custom_profile_dir = $profilesConfFile . "custom";
+
+# stores parameters for traffic ops config
+my $parameters;
+
+# location of traffic ops profiles
+my $profileDir = "/opt/traffic_ops/install/data/profiles/";
+my $post_install_cfg = "/opt/traffic_ops/install/data/json/post_install.json";
+
+# log file for the installer
+my $logFile = "/var/log/traffic_ops/postinstall.log";
+
+# debug mode
+my $debug = 1;
+
+# log file for cpan output
+my $cpanLogFile = "/var/log/traffic_ops/cpan.log";
+
+# whether or not to reconfigure traffic ops
+my $reconfigure = 1;
+
+# used to check for .reconfigure_defaults file for backwards compatability
+my $reconfigure_defaults = "/opt/traffic_ops/.reconfigure_defaults";
+
+# 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";
+
+# 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 = 10000000; #bytes
+
+# whether to create a config file with default values
+my $dumpDefaults;
+
+# configuration file output with answers which can be used as input to postinstall
+my $outputConfigFile = "/opt/traffic_ops/install/bin/configuration_file.json";
+
+my $inputFile = "";
+my $automatic = 0;
+my $defaultInputs;
+
+sub getInstallPath {
+ my $relPath = shift;
+ return join( '/', "/tmp/traffic_ops", $relPath );
+}
+
+# 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;
+ }
+ }
+}
+
+# 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 InstallUtils::promptPasswordVerify($question);
+ }
+ else {
+ return InstallUtils::promptUser( $question, $config_answer );
+ }
+ }
+
+ return $config_answer;
+}
+
+# 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} ) {
+ InstallUtils::logger( "No $fileName found in config", "error" );
+ }
+
+ InstallUtils::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 ) {
+ InstallUtils::logger( "$question: $answer", "info" );
+ }
+ }
+ return %config;
+}
+
+# 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 } );
+ InstallUtils::writeJson( $dbFileName, \%dbconf );
+ InstallUtils::logger( "Database configuration has been saved", "info" );
+
+ # broken out into separate file/config area
+ my %todbconf = getConfig( $userInput, $toDBFileName );
+
+ # Check if the Postgres db is used and set the driver to be "postgres"
+ my $dbDriver = $dbconf{type};
+ if ( $dbconf{type} eq "Pg" ) {
+ $dbDriver = "postgres";
+ }
+
+ # 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: $dbDriver\n";
+ print $fh " open: host=$dbconf{hostname} port=$dbconf{port} user=$dbconf{user} password=$dbconf{password} dbname=$dbconf{dbname} sslmode=disable\n";
+ close $fh;
+
+ return \%todbconf;
+}
+
+# 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 = InstallUtils::randomWord();
+ unshift @secrets, InstallUtils::randomWord();
+ if ( $cdnConfiguration{keepSecrets} > 0 && $#secrets > $cdnConfiguration{keepSecrets} - 1 ) {
+
+ # Shorten the array to requested length
+ $#secrets = $cdnConfiguration{keepSecrets} - 1;
+ }
+ }
+ InstallUtils::writePerl( $fileName, $cdnConf );
+}
+
+# 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)?/ ) {
+ InstallUtils::logger( "Not setting up ldap", "info" );
+ return;
+ }
+
+ my %ldapConf = getConfig( $userInput, $fileName );
+
+ make_path( dirname($fileName), { mode => 0755 } );
+ InstallUtils::writeJson( $fileName, \%ldapConf );
+}
+
+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} );
+
+ InstallUtils::writeJson( $fileName, \%user );
+ $user{password} = $config{tmAdminPw};
+ return \%user;
+}
+
+sub generateProfilesDir {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my $userIn = $userInput->{$fileName};
+}
+
+sub generateOpenSSLConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %config = getConfig( $userInput, $fileName );
+ return \%config;
+}
+
+sub generateParamConf {
+ my $userInput = shift;
+ my $fileName = shift;
+
+ my %config = getConfig( $userInput, $fileName );
+ InstallUtils::writeJson( $fileName, \%config );
+ return \%config;
+}
+
+# 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");
+ }
+ }
+ }
+}
+
+# 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} ) {
+ InstallUtils::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);
+ InstallUtils::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};
+ InstallUtils::logger( "Adding question '$question' with default answer " . ( $hidden ? "" : "'$answer'" ), "info" );
+ }
+
+ # in interactive mode prompt the user for answer to missing question
+ else {
+ InstallUtils::logger( "Prompting user for answer", "info" );
+ if ($hidden) {
+ $answer = InstallUtils::promptPasswordVerify($question);
+ }
+ else {
+ $answer = InstallUtils::promptUser( $question, $defaultValue->{$question} );
+ }
+ }
+
+ %temp = (
+ "config_var" => $defaultValue->{"config_var"},
+ $question => $answer
+ );
+
+ if ($hidden) {
+ $temp{"hidden"} .= "true";
+ }
+
+ push $userInput->{$file}, \%temp;
+
+ $diffs++;
+ }
+ }
+ }
+
+ InstallUtils::logger( "File sanity check complete - found $diffs difference" . ( $diffs == 1 ? "" : "s" ), "info" );
+}
+
+# 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" => "Pg",
+ "config_var" => "type"
+ },
+ {
+ "Database name" => "traffic_ops",
+ "config_var" => "dbname"
+ },
+ {
+ "Database server hostname IP or FQDN" => "localhost",
+ "config_var" => "hostname"
+ },
+ {
+ "Database port number" => "5432",
+ "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" => "postgres",
+ "config_var" => "dbAdminUser"
+ },
+ {
+ "Password for database server admin" => "",
+ "config_var" => "dbAdminPw",
+ "hidden" => "true"
+ },
+ {
+ "Download Maxmind Database?" => "yes",
+ "config_var" => "maxmind"
+ }
+ ],
+ $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 => [
+ {
+ "Add custom profiles?" => "no",
+ "config_var" => "custom_profiles"
+ }
+ ],
+ $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"
+ }
+
+ ]
+ };
+}
+
+# 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 $setupMaxmind = shift;
+ my $databaseConfFile = shift;
+
+ my $dbconf = InstallUtils::readJson($databaseConfFile);
+
+ # Check if the Postgres db is used and set the admin database to be "postgres"
+ my $dbName = $dbconf->{type};
+ if ( $dbconf->{type} eq "Pg" ) {
+ $dbName = "postgres";
+ }
+
+ my $dsn = sprintf( "DBI:%s:dbname=%s", $dbconf->{"type"}, $dbName );
+ my $dbh = DBI->connect( $dsn, $todbconf->{"dbAdminUser"}, $todbconf->{"dbAdminPw"} );
+ if ($dbh) {
+ InstallUtils::logger( "Database connection succeeded", "info" );
+
+ # Success!
+ $dbh->disconnect();
+ }
+ else {
+ InstallUtils::logger( "Error connecting to database", "error" );
+ exit(-1);
+ }
+
+ InstallUtils::logger( "Setting up database", "info" );
+ $ENV{PGUSER} = $todbconf->{"dbAdminUser"};
+ $ENV{PGPASSWORD} = $todbconf->{"dbAdminPw"};
+ chdir("/opt/traffic_ops/app");
+ my $result = InstallUtils::execCommand( "/usr/bin/perl", "db/admin.pl", "--env=production", "setup" );
+
+ if ( $result != 0 ) {
+ errorOut("Database initialization failed");
+ }
+ else {
+ InstallUtils::logger( "Database initialization succeeded", "info" );
+ }
+
+ if ( $setupMaxmind =~ /^y(?:es)?/ ) {
+ InstallUtils::logger( "Downloading Maxmind data", "info" );
+ chdir("/opt/traffic_ops/app/public/routing");
+ $result = InstallUtils::execCommand("/usr/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz");
+ if ( $result != 0 ) {
+ InstallUtils::logger( "Failed to download MaxMind data", "error" );
+ }
+ }
+ else {
+ InstallUtils::logger("Not downloading Maxmind data");
+ }
+
+ InstallUtils::logger( "Copying coverage zone file to public dir", "info" );
+ $result = InstallUtils::execCommand("/bin/mv /opt/traffic_ops/app/public/coverage-zone.json .");
+ if ( $result != 0 ) {
+ InstallUtils::logger( "Failed to copy coverage zone file", "error" );
+ }
+
+ if ( lc $opensslconf->{"genCert"} =~ /^y(?:es)?/ ) {
+ if ( -x "/usr/bin/openssl" ) {
+ InstallUtils::logger( "Installing SSL Certificates", "info" );
+ $result = GenerateCert::createCert($opensslconf);
+
+ if ( $result != 0 ) {
+ errorOut("SSL Certificate Installation failed");
+ }
+ else {
+ InstallUtils::logger( "SSL Certificates have been installed", "info" );
+ }
+ }
+ else {
+ InstallUtils::logger( "Unable to install SSL certificates as openssl is not installed", "error" );
+ InstallUtils::logger( "Install openssl and then run /opt/traffic_ops/install/bin/generateCert to install SSL certificates", "error" );
+ exit 4;
+ }
+ }
+ else {
+ InstallUtils::logger( "Not generating openssl certification", "info" );
+ }
+}
+
+# -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 recreate 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 {
+ my $help = 0;
+
+ # help string
+ 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
+ $defaultInputs = getDefaults();
+
+ if ($help) {
+ print $usageString;
+ return;
+ }
+
+ # check if the user running postinstall is root
+ if ( $ENV{USER} ne "root" ) {
+ errorOut("You must run this script as the root user");
+ }
+
+ InstallUtils::initLogger( $debug, $logFile );
+
+ print("unzipping log\n");
+ if ( -f "$logFile.gz" ) {
+ InstallUtils::execCommand( "/bin/gunzip", "-f", "$logFile.gz" );
+ }
+
+ InstallUtils::logger( "Starting postinstall", "info" );
+
+ InstallUtils::logger( "Debug is on", "info" );
+
+ if ($automatic) {
+ InstallUtils::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 ) {
+ InstallUtils::logger( "$reconfigure_file file is depreprecated - please remove and rerun postinstall", "error" );
+ return;
+ }
+
+ if ($dumpDefaults) {
+ InstallUtils::logger( "Writing default configuration file to $outputConfigFile", "info" );
+ InstallUtils::writeJson( $outputConfigFile, $defaultInputs );
+ return;
+ }
+
+ InstallUtils::logger( "Postinstall " . ( $reconfigure ? "" : "not " ) . "in reconfigure mode", "info" );
+
+ InstallUtils::rotateLog($cpanLogFile);
+
+ if ( -s $logFile > $maxLogSize ) {
+ InstallUtils::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 "" ) {
+ InstallUtils::logger( "No input file given - using defaults", "info" );
+ $userInput = $defaultInputs;
+ }
+ else {
+ InstallUtils::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 = InstallUtils::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 "" );
+
+ # if reconfigure is set then rebuild the perl deps
+ if ($reconfigure) {
+ my $rc = BuildPerlDeps::build( 1, $cpanLogFile );
+ if ( $rc != 0 ) {
+ errorOut("Failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error");
+ }
+
+ chdir("/opt/traffic_ops/install/bin");
+ $rc = InstallUtils::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");
+ }
+
+ chdir("/opt/traffic_ops/install/bin");
+ $rc = InstallUtils::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 );
+ my $custom_profile = generateProfilesDir( $userInput, $profilesConfFile );
+ my $opensslconf = generateOpenSSLConf( $userInput, $opensslConfFile );
+ my $paramconf = generateParamConf( $userInput, $paramConfFile );
+
+ if ( !-f $post_install_cfg ) {
+ InstallUtils::writeJson( $post_install_cfg, {} );
+ }
+
+ # if reconfigure is set then setup the database
+ if ($reconfigure) {
+ setupDatabase( $todbconf, $opensslconf, $todbconf->{"maxmind"}, $databaseConfFile );
+
+ ## Create the tm_user
+ my $dbconf = InstallUtils::readJson($databaseConfFile);
+ my $dsn = sprintf( "DBI:%s:dbname=%s", $dbconf->{"type"}, $dbconf->{"dbname"} );
+ my $dbh = DBI->connect( $dsn, $todbconf->{"dbAdminUser"}, $todbconf->{"dbAdminPw"} );
+ my $sha1_passwd = sha1_hex( $adminconf->{"password"} );
+ my $sub_string = sprintf( "('%s', 4, '%s')", $adminconf->{"username"}, $sha1_passwd, $sha1_passwd );
+
+ $dbh->do("insert into tm_user (username, role, local_passwd) values $sub_string");
+
+ }
+
+ InstallUtils::logger( "Starting Traffic Ops", "info" );
+ InstallUtils::execCommand("/sbin/service traffic_ops start");
+
+ InstallUtils::logger( "Waiting for Traffic Ops to start", "info" );
+
+ if ( -f $post_install_cfg ) {
+ $parameters = InstallUtils::readJson($post_install_cfg);
+ }
+
+ if ( !ProfileCleanup::profiles_exist( $adminconf, $paramconf->{"tm.url"}, $parameters, $reconfigure_defaults, $reconfigure ) ) {
+ InstallUtils::logger( "Creating default profiles...", "info" );
+ ProfileCleanup::replace_profile_templates( $paramconf, $adminconf, $post_install_cfg, $parameters, $profileDir );
+ ProfileCleanup::import_profiles( $paramconf->{"tm.url"}, $adminconf, $profileDir );
+
+ # call again to create $reconfigure_defaults file if import was successful
+ ProfileCleanup::profiles_exist( $adminconf, $paramconf->{"tm.url"}, $parameters, $reconfigure_defaults, $reconfigure );
+ }
+ else {
+ InstallUtils::logger( "Not creating default profiles", "info" );
+ }
+
+ if ( $custom_profile =~ /^y(?:es)?/ ) {
+ ProfileCleanup::add_custom_profiles( $custom_profile_dir, $adminconf, $parameters->{"tm.url"} );
+ }
+
+ InstallUtils::execCommand("/bin/chown -R trafops:trafops /opt/traffic_ops");
+ InstallUtils::execCommand("/bin/chmod -R a+rX /opt/traffic_ops");
+
+ InstallUtils::logger("Postinstall complete");
+
+ InstallUtils::execCommand( "/bin/gzip", "$logFile" );
+}
+
+main;
+
+# vi:syntax=perl
http://git-wip-us.apache.org/repos/asf/incubator-trafficcontrol/blob/9015339f/traffic_ops/install/bin/postinstall
----------------------------------------------------------------------
diff --git a/traffic_ops/install/bin/postinstall b/traffic_ops/install/bin/postinstall
index bfae12d..f7d8e93 100755
--- a/traffic_ops/install/bin/postinstall
+++ b/traffic_ops/install/bin/postinstall
@@ -1,4 +1,4 @@
-#!/usr/bin/perl
+#!/bin/bash
#
# Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,818 +14,20 @@
# limitations under the License.
#
-use lib qw(/opt/traffic_ops/install/lib /opt/traffic_ops/app/lib /opt/traffic_ops/app/local/lib/perl5);
+# make sure installed with proper permissions
+umask 022
-$ENV{PERL5LIB} = "/opt/traffic_ops/install/lib:/opt/traffic_ops/app/lib:/opt/traffic_ops/app/local/lib/perl5:$ENV{PERL5LIB}";
-$ENV{PATH} = "/usr/local/bin:/opt/traffic_ops/install/bin:$ENV{PATH}";
+# install carton first
+cpanm Carton
-use strict;
-use warnings;
+# carton installs all the perl dependencies in cpanfile
+cd /opt/traffic_ops/app
+/usr/local/bin/carton
-use Safe;
-use DBI;
-use POSIX;
-use File::Basename qw{dirname};
-use File::Path qw{make_path};
-use Digest::SHA1 qw(sha1_hex);
-use Data::Dumper qw(Dumper);
-use Scalar::Util qw(looks_like_number);
-use Getopt::Long;
+export POSTGRES_HOME=/usr/pgsql-9.6
+export GOPATH=/usr/local
+export PERL5LIB=/opt/traffic_ops/app:/opt/traffic_ops/app/local/lib/perl5
+/opt/traffic_ops/install/bin/_postinstall "$@"
-use InstallUtils qw{ :all };
-use BuildPerlDeps qw{ :all };
-use GenerateCert qw{ :all };
-use ProfileCleanup qw{ :all };
-
-# paths of the output configuration files
-my $databaseConfFile = "/opt/traffic_ops/app/conf/production/database.conf";
-my $dbConfFile = "/opt/traffic_ops/app/db/dbconf.yml";
-my $cdnConfFile = "/opt/traffic_ops/app/conf/cdn.conf";
-my $ldapConfFile = "/opt/traffic_ops/app/conf/ldap.conf";
-my $usersConfFile = "/opt/traffic_ops/install/data/json/users.json";
-my $profilesConfFile = "/opt/traffic_ops/install/data/profiles/";
-my $opensslConfFile = "/opt/traffic_ops/install/data/json/openssl_configuration.json";
-my $paramConfFile = "/opt/traffic_ops/install/data/json/profiles.json";
-
-my $custom_profile_dir = $profilesConfFile . "custom";
-
-# stores parameters for traffic ops config
-my $parameters;
-
-# location of traffic ops profiles
-my $profileDir = "/opt/traffic_ops/install/data/profiles/";
-my $post_install_cfg = "/opt/traffic_ops/install/data/json/post_install.json";
-
-# log file for the installer
-my $logFile = "/var/log/traffic_ops/postinstall.log";
-
-# debug mode
-my $debug = 1;
-
-# log file for cpan output
-my $cpanLogFile = "/var/log/traffic_ops/cpan.log";
-
-# whether or not to reconfigure traffic ops
-my $reconfigure = 1;
-
-# used to check for .reconfigure_defaults file for backwards compatability
-my $reconfigure_defaults = "/opt/traffic_ops/.reconfigure_defaults";
-
-# 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";
-
-# 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 = 10000000; #bytes
-
-# whether to create a config file with default values
-my $dumpDefaults;
-
-# configuration file output with answers which can be used as input to postinstall
-my $outputConfigFile = "/opt/traffic_ops/install/bin/configuration_file.json";
-
-my $inputFile = "";
-my $automatic = 0;
-my $defaultInputs;
-
-sub getInstallPath {
- my $relPath = shift;
- return join( '/', "/tmp/traffic_ops", $relPath );
-}
-
-# 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;
- }
- }
-}
-
-# 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 InstallUtils::promptPasswordVerify($question);
- }
- else {
- return InstallUtils::promptUser( $question, $config_answer );
- }
- }
-
- return $config_answer;
-}
-
-# 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} ) {
- InstallUtils::logger( "No $fileName found in config", "error" );
- }
-
- InstallUtils::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 ) {
- InstallUtils::logger( "$question: $answer", "info" );
- }
- }
- return %config;
-}
-
-# 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 } );
- InstallUtils::writeJson( $dbFileName, \%dbconf );
- InstallUtils::logger( "Database configuration has been saved", "info" );
-
- # broken out into separate file/config area
- my %todbconf = getConfig( $userInput, $toDBFileName );
-
- # Check if the Postgres db is used and set the driver to be "postgres"
- my $dbDriver = $dbconf{type};
- if ( $dbconf{type} eq "Pg" ) {
- $dbDriver = "postgres";
- }
-
- # 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: $dbDriver\n";
- print $fh " open: host=$dbconf{hostname} port=$dbconf{port} user=$dbconf{user} password=$dbconf{password} dbname=$dbconf{dbname} sslmode=disable\n";
- close $fh;
-
- return \%todbconf;
-}
-
-# 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 = InstallUtils::randomWord();
- unshift @secrets, InstallUtils::randomWord();
- if ( $cdnConfiguration{keepSecrets} > 0 && $#secrets > $cdnConfiguration{keepSecrets} - 1 ) {
-
- # Shorten the array to requested length
- $#secrets = $cdnConfiguration{keepSecrets} - 1;
- }
- }
- InstallUtils::writePerl( $fileName, $cdnConf );
-}
-
-# 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)?/ ) {
- InstallUtils::logger( "Not setting up ldap", "info" );
- return;
- }
-
- my %ldapConf = getConfig( $userInput, $fileName );
-
- make_path( dirname($fileName), { mode => 0755 } );
- InstallUtils::writeJson( $fileName, \%ldapConf );
-}
-
-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} );
-
- InstallUtils::writeJson( $fileName, \%user );
- $user{password} = $config{tmAdminPw};
- return \%user;
-}
-
-sub generateProfilesDir {
- my $userInput = shift;
- my $fileName = shift;
-
- my $userIn = $userInput->{$fileName};
-}
-
-sub generateOpenSSLConf {
- my $userInput = shift;
- my $fileName = shift;
-
- my %config = getConfig( $userInput, $fileName );
- return \%config;
-}
-
-sub generateParamConf {
- my $userInput = shift;
- my $fileName = shift;
-
- my %config = getConfig( $userInput, $fileName );
- InstallUtils::writeJson( $fileName, \%config );
- return \%config;
-}
-
-# 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");
- }
- }
- }
-}
-
-# 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} ) {
- InstallUtils::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);
- InstallUtils::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};
- InstallUtils::logger( "Adding question '$question' with default answer " . ( $hidden ? "" : "'$answer'" ), "info" );
- }
-
- # in interactive mode prompt the user for answer to missing question
- else {
- InstallUtils::logger( "Prompting user for answer", "info" );
- if ($hidden) {
- $answer = InstallUtils::promptPasswordVerify($question);
- }
- else {
- $answer = InstallUtils::promptUser( $question, $defaultValue->{$question} );
- }
- }
-
- %temp = (
- "config_var" => $defaultValue->{"config_var"},
- $question => $answer
- );
-
- if ($hidden) {
- $temp{"hidden"} .= "true";
- }
-
- push $userInput->{$file}, \%temp;
-
- $diffs++;
- }
- }
- }
-
- InstallUtils::logger( "File sanity check complete - found $diffs difference" . ( $diffs == 1 ? "" : "s" ), "info" );
-}
-
-# 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" => "Pg",
- "config_var" => "type"
- },
- {
- "Database name" => "traffic_ops",
- "config_var" => "dbname"
- },
- {
- "Database server hostname IP or FQDN" => "localhost",
- "config_var" => "hostname"
- },
- {
- "Database port number" => "5432",
- "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" => "postgres",
- "config_var" => "dbAdminUser"
- },
- {
- "Password for database server admin" => "",
- "config_var" => "dbAdminPw",
- "hidden" => "true"
- },
- {
- "Download Maxmind Database?" => "yes",
- "config_var" => "maxmind"
- }
- ],
- $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 => [
- {
- "Add custom profiles?" => "no",
- "config_var" => "custom_profiles"
- }
- ],
- $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"
- }
-
- ]
- };
-}
-
-# 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 $setupMaxmind = shift;
- my $databaseConfFile = shift;
-
- my $dbconf = InstallUtils::readJson($databaseConfFile);
-
- # Check if the Postgres db is used and set the admin database to be "postgres"
- my $dbName = $dbconf->{type};
- if ( $dbconf->{type} eq "Pg" ) {
- $dbName = "postgres";
- }
-
- my $dsn = sprintf( "DBI:%s:dbname=%s", $dbconf->{"type"}, $dbName );
- my $dbh = DBI->connect( $dsn, $todbconf->{"dbAdminUser"}, $todbconf->{"dbAdminPw"} );
- if ($dbh) {
- InstallUtils::logger( "Database connection succeeded", "info" );
-
- # Success!
- $dbh->disconnect();
- }
- else {
- InstallUtils::logger( "Error connecting to database", "error" );
- exit(-1);
- }
-
- InstallUtils::logger( "Setting up database", "info" );
- $ENV{PGUSER} = $todbconf->{"dbAdminUser"};
- $ENV{PGPASSWORD} = $todbconf->{"dbAdminPw"};
- chdir("/opt/traffic_ops/app");
- my $result = InstallUtils::execCommand( "/usr/bin/perl", "db/admin.pl", "--env=production", "setup" );
-
- if ( $result != 0 ) {
- errorOut("Database initialization failed");
- }
- else {
- InstallUtils::logger( "Database initialization succeeded", "info" );
- }
-
- if ( $setupMaxmind =~ /^y(?:es)?/ ) {
- InstallUtils::logger( "Downloading Maxmind data", "info" );
- chdir("/opt/traffic_ops/app/public/routing");
- $result = InstallUtils::execCommand("/usr/bin/wget http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz");
- if ( $result != 0 ) {
- InstallUtils::logger( "Failed to download MaxMind data", "error" );
- }
- }
- else {
- InstallUtils::logger("Not downloading Maxmind data");
- }
-
- InstallUtils::logger( "Copying coverage zone file to public dir", "info" );
- $result = InstallUtils::execCommand("/bin/mv /opt/traffic_ops/app/public/coverage-zone.json .");
- if ( $result != 0 ) {
- InstallUtils::logger( "Failed to copy coverage zone file", "error" );
- }
-
- if ( lc $opensslconf->{"genCert"} =~ /^y(?:es)?/ ) {
- if ( -x "/usr/bin/openssl" ) {
- InstallUtils::logger( "Installing SSL Certificates", "info" );
- $result = GenerateCert::createCert($opensslconf);
-
- if ( $result != 0 ) {
- errorOut("SSL Certificate Installation failed");
- }
- else {
- InstallUtils::logger( "SSL Certificates have been installed", "info" );
- }
- }
- else {
- InstallUtils::logger( "Unable to install SSL certificates as openssl is not installed", "error" );
- InstallUtils::logger( "Install openssl and then run /opt/traffic_ops/install/bin/generateCert to install SSL certificates", "error" );
- exit 4;
- }
- }
- else {
- InstallUtils::logger( "Not generating openssl certification", "info" );
- }
-}
-
-# -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 recreate 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 {
- my $help = 0;
-
- # help string
- 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
- $defaultInputs = getDefaults();
-
- if ($help) {
- print $usageString;
- return;
- }
-
- # check if the user running postinstall is root
- if ( $ENV{USER} ne "root" ) {
- errorOut("You must run this script as the root user");
- }
-
- InstallUtils::initLogger( $debug, $logFile );
-
- print("unzipping log\n");
- if ( -f "$logFile.gz" ) {
- InstallUtils::execCommand( "/bin/gunzip", "-f", "$logFile.gz" );
- }
-
- InstallUtils::logger( "Starting postinstall", "info" );
-
- InstallUtils::logger( "Debug is on", "info" );
-
- if ($automatic) {
- InstallUtils::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 ) {
- InstallUtils::logger( "$reconfigure_file file is depreprecated - please remove and rerun postinstall", "error" );
- return;
- }
-
- if ($dumpDefaults) {
- InstallUtils::logger( "Writing default configuration file to $outputConfigFile", "info" );
- InstallUtils::writeJson( $outputConfigFile, $defaultInputs );
- return;
- }
-
- InstallUtils::logger( "Postinstall " . ( $reconfigure ? "" : "not " ) . "in reconfigure mode", "info" );
-
- InstallUtils::rotateLog($cpanLogFile);
-
- if ( -s $logFile > $maxLogSize ) {
- InstallUtils::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 "" ) {
- InstallUtils::logger( "No input file given - using defaults", "info" );
- $userInput = $defaultInputs;
- }
- else {
- InstallUtils::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 = InstallUtils::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 "" );
-
- # if reconfigure is set then rebuild the perl deps
- if ($reconfigure) {
- my $rc = BuildPerlDeps::build( 1, $cpanLogFile );
- if ( $rc != 0 ) {
- errorOut("Failed to install perl dependencies, check the console output and rerun postinstall once you've resolved the error");
- }
-
- chdir("/opt/traffic_ops/install/bin");
- $rc = InstallUtils::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");
- }
-
- chdir("/opt/traffic_ops/install/bin");
- $rc = InstallUtils::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 );
- my $custom_profile = generateProfilesDir( $userInput, $profilesConfFile );
- my $opensslconf = generateOpenSSLConf( $userInput, $opensslConfFile );
- my $paramconf = generateParamConf( $userInput, $paramConfFile );
-
- if ( !-f $post_install_cfg ) {
- InstallUtils::writeJson( $post_install_cfg, {} );
- }
-
- # if reconfigure is set then setup the database
- if ($reconfigure) {
- setupDatabase( $todbconf, $opensslconf, $todbconf->{"maxmind"}, $databaseConfFile );
-
- ## Create the tm_user
- my $dbconf = InstallUtils::readJson($databaseConfFile);
- my $dsn = sprintf( "DBI:%s:dbname=%s", $dbconf->{"type"}, $dbconf->{"dbname"} );
- my $dbh = DBI->connect( $dsn, $todbconf->{"dbAdminUser"}, $todbconf->{"dbAdminPw"} );
- my $sha1_passwd = sha1_hex( $adminconf->{"password"} );
- my $sub_string = sprintf( "('%s', 4, '%s')", $adminconf->{"username"}, $sha1_passwd, $sha1_passwd );
-
- $dbh->do("insert into tm_user (username, role, local_passwd) values $sub_string");
-
- }
-
- InstallUtils::logger( "Starting Traffic Ops", "info" );
- InstallUtils::execCommand("/sbin/service traffic_ops start");
-
- InstallUtils::logger( "Waiting for Traffic Ops to start", "info" );
-
- if ( -f $post_install_cfg ) {
- $parameters = InstallUtils::readJson($post_install_cfg);
- }
-
- if ( !ProfileCleanup::profiles_exist( $adminconf, $paramconf->{"tm.url"}, $parameters, $reconfigure_defaults, $reconfigure ) ) {
- InstallUtils::logger( "Creating default profiles...", "info" );
- ProfileCleanup::replace_profile_templates( $paramconf, $adminconf, $post_install_cfg, $parameters, $profileDir );
- ProfileCleanup::import_profiles( $paramconf->{"tm.url"}, $adminconf, $profileDir );
-
- # call again to create $reconfigure_defaults file if import was successful
- ProfileCleanup::profiles_exist( $adminconf, $paramconf->{"tm.url"}, $parameters, $reconfigure_defaults, $reconfigure );
- }
- else {
- InstallUtils::logger( "Not creating default profiles", "info" );
- }
-
- if ( $custom_profile =~ /^y(?:es)?/ ) {
- ProfileCleanup::add_custom_profiles( $custom_profile_dir, $adminconf, $parameters->{"tm.url"} );
- }
-
- InstallUtils::execCommand("/bin/chown -R trafops:trafops /opt/traffic_ops");
- InstallUtils::execCommand("/bin/chmod -R a+rX /opt/traffic_ops");
-
- InstallUtils::logger("Postinstall complete");
-
- InstallUtils::execCommand( "/bin/gzip", "$logFile" );
-}
-
-main;
-
-# vi:syntax=perl
+# should all be owned by trafops user
+chown -R trafops:trafops /opt/traffic_ops