include_once dirname(__FILE__) . "/../include/global.php"; } elseif (file_exists(dirname(__FILE__) . "/../include/config.php")) { # Some Cacti installations don't have global.php. debug("including " . dirname(__FILE__) . "/../include/config.php"); include_once dirname(__FILE__) . "/../include/config.php"; } } # ============================================================================ # Make sure we can also be called as a script. # ============================================================================ if (!isset($called_by_script_server)) { debug($_SERVER["argv"]); array_shift($_SERVER["argv"]); # Strip off this script's filename $options = parse_cmdline($_SERVER["argv"]); validate_options($options); $result = ss_get_by_ssh($options); debug($result); if (!$debug) { # Throw away the buffer, which ought to contain only errors. ob_end_clean(); } else { ob_end_flush(); # In debugging mode, print out the errors. } print $result; } # ============================================================================ # End "if file was not included" section. # ============================================================================ }
/** * validation method - may be overriden by sub-classes, but parent method * should still be invoked. returns TRUE if db options are valid, FALSE * otherwise * @return boolean */ protected function validate() { if (!isset($this->valid) && parent::validate()) { $this->valid = TRUE; $validate = array('db_librato_color' => array('color' => TRUE), 'db_librato_display_max' => array('min' => 0), 'db_librato_display_min' => array('min' => 0), 'db_librato_period' => array('min' => 0), 'db_librato_type' => array('option' => array('counter', 'gauge')), 'db_user' => array('required' => TRUE), 'db_pswd' => array('required' => TRUE)); if ($validated = validate_options($this->options, $validate)) { $this->valid = FALSE; foreach ($validated as $param => $err) { print_msg(sprintf('--%s is not valid: %s', $param, $err), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } } else { $valueCol = 'db_librato_value'; if (!isset($this->options['db_librato_value'])) { $valueCol = 'db_librato_count'; if (!isset($this->options['db_librato_count']) || !isset($this->options['db_librato_sum'])) { $this->valid = FALSE; print_msg(sprintf('If --db_librato_value is not set, both --db_librato_count and --db_librato_sum MUST be specified'), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { if (count($this->options['db_librato_count']) != count($this->options['db_librato_sum'])) { $this->valid = FALSE; print_msg(sprintf('--db_librato_count and --db_librato_sum must be repeated the same number of times'), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { if (isset($this->options['db_librato_name']) && count($this->options['db_librato_name']) != count($this->options['db_librato_count'])) { $this->valid = FALSE; print_msg(sprintf('--db_librato_name and --db_librato_count must be repeated the same number of times'), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } } } } else { if (isset($this->options['db_librato_name']) && count($this->options['db_librato_name']) != count($this->options['db_librato_value'])) { $this->valid = FALSE; print_msg(sprintf('--db_librato_name and --db_librato_value must be repeated the same number of times'), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { if (isset($this->options['db_librato_count']) || isset($this->options['db_librato_sum']) || isset($this->options['db_librato_max']) || isset($this->options['db_librato_min']) || isset($this->options['db_librato_sum_squares'])) { $this->valid = FALSE; print_msg(sprintf('--db_librato_value cannot be set with --db_librato_count, --db_librato_sum, --db_librato_max, --db_librato_min or --db_librato_sum_squares because these parameters are mutually exclusive'), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } } } if ($this->valid) { foreach (array('db_librato_aggregate', 'db_librato_color', 'db_librato_count', 'db_librato_description', 'db_librato_display_max', 'db_librato_display_min', 'db_librato_display_name', 'db_librato_display_units_long', 'db_librato_display_units_short', 'db_librato_display_stacked', 'db_librato_display_transform', 'db_librato_max', 'db_librato_min', 'db_librato_measure_time', 'db_librato_period', 'db_librato_source', 'db_librato_sum', 'db_librato_summarize_function', 'db_librato_sum_squares', 'db_librato_type') as $param) { if (isset($this->options[$param]) && count($this->options[$param]) != count($this->options[$valueCol]) && count($this->options[$param]) != 1) { $this->valid = FALSE; print_msg(sprintf('--%s can only be set once or %d times (once for each --%s)', $param, count($this->options[$valueCol]), $valueCol), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } } } } if ($this->valid) { // validate credentials using GET request $curl = ch_curl(self::LIBRATO_METRICS_API_URL, 'GET', NULL, NULL, sprintf('%s:%s', $this->options['db_user'], $this->options['db_pswd']), '200-299', TRUE); $this->valid = ($response = json_decode($curl, TRUE)) ? TRUE : FALSE; if ($curl === NULL) { print_msg(sprintf('Librato API GET request to %s failed', self::LIBRATO_METRICS_API_URL), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { if ($curl === FALSE) { print_msg(sprintf('Librato API GET request to %s resulted in non 200 response code - API credentials may be invalid', self::LIBRATO_METRICS_API_URL), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { if ($curl && !$response) { print_msg(sprintf('Librato API GET request to %s successful, but body did not contain valid JSON', self::LIBRATO_METRICS_API_URL), isset($this->options['verbose']), __FILE__, __LINE__, TRUE); } else { print_msg(sprintf('Librato API GET request to %s successful. There are %d existing metrics', self::LIBRATO_METRICS_API_URL, count($response['metrics'])), isset($this->options['verbose']), __FILE__, __LINE__); } } } } } return $this->valid; }
/** * validate run options. returns an array populated with error messages * indexed by the argument name. If options are valid, the array returned * will be empty * @return array */ public function validateRunOptions() { $validate = array('abort_threshold' => array('min' => 1), 'discard_fastest' => array('max' => 40, 'min' => 0), 'discard_slowest' => array('max' => 40, 'min' => 0), 'dns_retry' => array('max' => 10, 'min' => 1, 'required' => TRUE), 'dns_samples' => array('max' => 100, 'min' => 1, 'required' => TRUE), 'dns_timeout' => array('max' => 60, 'min' => 1, 'required' => TRUE), 'geo_regions' => array('option' => array_keys($this->getGeoRegions())), 'latency_interval' => array('max' => 10, 'min' => 0, 'required' => TRUE), 'latency_samples' => array('max' => 100, 'min' => 1, 'required' => TRUE), 'latency_timeout' => array('max' => 30, 'min' => 1, 'required' => TRUE), 'max_runtime' => array('min' => 10), 'max_tests' => array('min' => 1), 'min_runtime' => array('min' => 10), 'output' => array('write' => TRUE), 'params_url' => array('url' => TRUE), 'params_url_service_type' => array('option' => get_service_types()), 'spacing' => array('min' => 0), 'test' => array('required' => TRUE), 'test_endpoint' => array('required' => TRUE), 'test_service_type' => array('option' => get_service_types()), 'throughput_same_continent' => array('max' => 1024, 'min' => 1), 'throughput_same_country' => array('max' => 1024, 'min' => 1), 'throughput_same_geo_region' => array('max' => 1024, 'min' => 1), 'throughput_same_provider' => array('max' => 1024, 'min' => 1), 'throughput_same_region' => array('max' => 1024, 'min' => 1), 'throughput_same_service' => array('max' => 1024, 'min' => 1), 'throughput_same_state' => array('max' => 1024, 'min' => 1), 'throughput_samples' => array('max' => 100, 'min' => 1, 'required' => TRUE), 'throughput_size' => array('max' => 1024, 'min' => 0, 'required' => TRUE), 'throughput_threads' => array('max' => 32, 'min' => 1, 'required' => TRUE), 'throughput_timeout' => array('max' => 600, 'min' => 1, 'required' => TRUE)); $validated = validate_options($this->getRunOptions(), $validate); // validate tests if (!isset($validated['test'])) { foreach ($this->options['test'] as $tests) { foreach ($tests as $test) { if (!in_array($test, array('latency', 'downlink', 'uplink', 'throughput', 'dns'))) { $validated['test'] = sprintf('--test %s is not valid [must be one of: latency, downlink, uplink, dns]'); break; } } if (isset($validated['test'])) { break; } } } // validate test_endpoint association parameters if (!isset($validated['test_endpoint']) && count($this->options['test_endpoint']) && !isset($this->options['service_lookup']) && !isset($this->options['geoiplookup'])) { foreach (array('test_instance_id', 'test_location', 'test_private_network_type', 'test_provider', 'test_provider_id', 'test_region', 'test_service', 'test_service_id', 'test_service_type', 'throughput_webpage') as $param) { if (!isset($validated[$param]) && isset($this->options[$param]) && count($this->options[$param]) != 1 && count($this->options[$param]) != count($this->options['test_endpoint'])) { $validated[$param] = sprintf('The --%s parameter can be specified once [same for all test_endpoint] or %d times [different for each test_endpoint]', $param, count($this->options[$param])); } } } // validate countries $countries =& $this->getCountries(); if (isset($this->options['meta_location_country']) && !isset($countries[$this->options['meta_location_country']])) { $validated['meta_location'] = sprintf('%s is not a valid ISO 3166 country code', $this->options['meta_location_country']); } if (isset($this->options['test_location_country'])) { foreach ($this->options['test_location_country'] as $country) { if (trim($country) && !isset($countries[$country])) { $validated['test_location'] = sprintf('%s is not a valid ISO 3166 country code', $country); break; } } } if (isset($this->options['throughput_webpage']) && isset($this->options['throughput_webpage_check'])) { $nurls = NULL; $mismatch = FALSE; foreach ($this->options['throughput_webpage'] as $i => $webpages) { if (!isset($nurls)) { $nurls = count($webpages); } else { if (count($webpages) != $nurls) { $mismatch = TRUE; break; } } } if ($mismatch) { $validated['throughput_webpage_check'] = sprintf('Use of --throughput_webpage_check requires the number of webpages in each --throughput_webpage parameter to be equal. The first such parameter contained %d URLs, while the %d parameter contained %d URLs', $nurls, $i + 1, count($webpages)); } else { $sizes = array(); $remove = array(); $headers = isset($this->options['throughput_header']) && is_array($this->options['throughput_header']) && $this->options['throughput_header'] ? $this->options['throughput_header'] : NULL; foreach ($this->options['test_endpoint'] as $idx => $endpoint) { $webpages = isset($this->options['throughput_webpage'][$idx]) ? $this->options['throughput_webpage'][$idx] : $this->options['throughput_webpage'][0]; foreach ($webpages as $i => $webpage) { if (!isset($remove[$i])) { $url = preg_match('/^http/', $webpage) ? $webpage : sprintf('%s%s%s', $endpoint[0], substr($webpage, 0, 1) == '/' ? '' : '/', $webpage); if (file_exists($ofile = ch_curl($url, 'GET', $headers, NULL, NULL, '200-299', 2))) { if (!isset($sizes[$i])) { $sizes[$i] = filesize($ofile); } else { $diff = $sizes[$i] * 0.05; if (abs($sizes[$i] - filesize($ofile)) > $diff) { print_msg(sprintf('Unable to validate endpoint %d URL %d %s because size %d does not match initial request size %d - URL will be removed from all endpoints', $idx + 1, $i + 1, $url, filesize($ofile), $sizes[$i]), $this->verbose, __FILE__, __LINE__, TRUE); $remove[$i] = TRUE; } else { print_msg(sprintf('Successfully validated endpoint %d URL %d %s', $idx + 1, $i + 1, $url), $this->verbose, __FILE__, __LINE__); } } exec(sprintf('rm -f %s', $ofile)); } else { print_msg(sprintf('Unable to validate endpoint %d URL %d %s - URL will be removed from all endpoints', $idx + 1, $i + 1, $url), $this->verbose, __FILE__, __LINE__, TRUE); $remove[$i] = TRUE; } } } } foreach ($this->options['throughput_webpage'] as $i => $webpages) { foreach ($webpages as $n => $webpage) { if (isset($remove[$n])) { print_msg(sprintf('Removing webpage %s from --throughput_webpage %d', $webpage, $i + 1), $this->verbose, __FILE__, __LINE__); unset($this->options['throughput_webpage'][$i][$n]); } } if (!count($this->options['throughput_webpage'][$i])) { $validated['throughput_webpage'] = sprintf('throughput_webpage at index %d has not URIs', $i); break; } } } } // validate collectd rrd options if (isset($this->options['collectd_rrd'])) { if (!ch_check_sudo()) { $validated['collectd_rrd'] = 'sudo privilege is required to use this option'; } else { if (!is_dir($this->options['collectd_rrd_dir'])) { $validated['collectd_rrd_dir'] = sprintf('The directory %s does not exist', $this->options['collectd_rrd_dir']); } else { if (shell_exec('ps aux | grep collectd | wc -l') * 1 < 2) { $validated['collectd_rrd'] = 'collectd is not running'; } else { if (shell_exec(sprintf('find %s -maxdepth 1 -type d 2>/dev/null | wc -l', $this->options['collectd_rrd_dir'])) * 1 < 2) { $validated['collectd_rrd_dir'] = sprintf('The directory %s is empty', $this->options['collectd_rrd_dir']); } } } } } return $validated; }
/** * validate run options. returns an array populated with error messages * indexed by the argument name. If options are valid, the array returned * will be empty * @param array $options the run options (see BlockStorageTest::getRunOptions) * @return array */ public static function validateRunOptions($options) { $validate = array('active_range' => array('min' => 1, 'max' => 100), 'font_size' => array('min' => 6, 'max' => 64), 'oio_per_thread' => array('min' => 1, 'max' => 256), 'output' => array('write' => TRUE), 'precondition_passes' => array('min' => 1, 'max' => 5), 'skip_blocksize' => array('option' => array('1m', '128k', '64k', '32k', '16k', '8k', '512b')), 'skip_workload' => array('option' => array('100/0', '95/5', '65/35', '50/50', '35/65', '5/95')), 'ss_max_rounds' => array('min' => 5, 'max' => 100), 'ss_verification' => array('min' => 1, 'max' => 100), 'target' => array('required' => TRUE, 'write' => TRUE), 'test' => array('option' => BlockStorageTest::getSupportedTests(), 'required' => TRUE), 'threads' => array('min' => 1), 'threads_per_core_max' => array('min' => 1), 'threads_per_target_max' => array('min' => 1), 'timeout' => array('min' => 3600), 'trim_offset_end' => array('min' => 1), 'wd_test_duration' => array('min' => 10)); if (!($valid = validate_options($options, $validate))) { $devices = 0; $volumes = 0; // device and volume type targets cannot be mixed foreach ($options['target'] as $target) { $device = BlockStorageTest::getDevice($target); $device == $target ? $devices++ : $volumes++; } if ($devices && $volumes) { $valid = array('target' => 'Device and volume type targets cannot be mixed'); } // validate collectd rrd options if (isset($options['collectd_rrd'])) { if (!ch_check_sudo()) { $valid['collectd_rrd'] = 'sudo privilege is required to use this option'; } else { if (!is_dir($options['collectd_rrd_dir'])) { $valid['collectd_rrd_dir'] = sprintf('The directory %s does not exist', $options['collectd_rrd_dir']); } else { if (shell_exec('ps aux | grep collectd | wc -l') * 1 < 2) { $valid['collectd_rrd'] = 'collectd is not running'; } else { if (shell_exec(sprintf('find %s -maxdepth 1 -type d 2>/dev/null | wc -l', $options['collectd_rrd_dir'])) * 1 < 2) { $valid['collectd_rrd_dir'] = sprintf('The directory %s is empty', $options['collectd_rrd_dir']); } } } } } } return $valid; }
--notify # Display MacOS notification when script # finishes. --no-sound # Don't allow notifications to play sounds. -h (--help) # Print help and exit EOT; // process args $longopts = array("site:", "no-files", "notify", "no-sound"); $shortopts = ""; $options = array(); build_options($options, $shortopts, $longopts, $usage); // Check the user's options validate_options(); // Requirements // Ensure required commands available $errors = FALSE; //TODO: check for vbox $required_commands = array('git', 'tar', 'gzip', 'vagrant'); foreach ($required_commands as $cmd) { exec("which {$cmd}", $output, $return); if ($return != 0) { print "Error: Can't find required command '{$cmd}'. Please install it or fix your {$PATH}.\n"; $errors = TRUE; } } if ($errors) { exit(1); }