예제 #1
0
/**
 * attempts to stop collectd rrd stats for the current test iteration. returns
 * TRUE on success, FALSE otherwise
 * @param string $dir the base directory where collectd rrd files are stored
 * @param string $saveTo the directory where the rrd zip file should be created
 * @param array $options test options - used to construct collectd rrd results 
 * directories
 * @param boolean $verbose enable verbose output
 * @return boolean
 */
function ch_collectd_rrd_stop($dir, $saveTo, $verbose)
{
    $stopped = FALSE;
    if (is_dir($dir) && ch_check_sudo()) {
        $tdir = '/tmp/' . rand();
        exec(sprintf('sudo mkdir %s', $tdir));
        print_msg(sprintf('Attempting to save collectd rrd files in %s to %s/collectd-rrd.zip using tmp directory %s', $dir, $saveTo, $tdir), $verbose, __FILE__, __LINE__);
        $rename = array();
        $d = dir($dir);
        while ($entry = $d->read()) {
            if (!preg_match('/[a-zA-Z0-9]+/', $entry)) {
                continue;
            }
            $rdir = sprintf('%s/%s', $dir, $entry);
            if (substr($rdir, -1) == '/') {
                $rdir = substr($rdir, 0, -1);
            }
            if (!is_dir($rdir)) {
                continue;
            }
            if (is_dir($rdir)) {
                print_msg(sprintf('Evaluating collectd rrd directory %s', $rdir), $verbose, __FILE__, __LINE__);
                if (preg_match('/\\.bak$/', $entry)) {
                    $rename[] = $rdir;
                } else {
                    exec($cmd = sprintf('sudo mv %s %s', $rdir, $tdir));
                    print_msg(sprintf('Successfully moved test collectd rrd directory %s to %s', basename($rdir), $tdir), $verbose, __FILE__, __LINE__);
                }
            }
        }
        $d->close();
        foreach ($rename as $rdir) {
            $renameTo = substr($rdir, 0, -4);
            exec($cmd = sprintf('sudo rm -rf %s;sudo mv %s %s', $renameTo, $rdir, $renameTo));
            if (is_dir($renameTo)) {
                print_msg(sprintf('Successfully renamed backup collectd rrd directory from %s to %s', $rdir, $renameTo), $verbose, __FILE__, __LINE__);
            } else {
                print_msg(sprintf('Unable to rename existing collectd rrd directory from %s to %s', $rdir, $renameTo), $verbose, __FILE__, __LINE__, TRUE);
            }
        }
        if (shell_exec(sprintf('find %s -maxdepth 1 -type d 2>/dev/null | wc -l', $tdir)) * 1 < 2) {
            print_msg(sprintf('collectd rrd directory %s did not contain any files', $dir), $verbose, __FILE__, __LINE__, TRUE);
        } else {
            $zip = sprintf('%s/collectd-rrd.zip', $saveTo);
            exec($cmd = sprintf('cd %s;sudo zip -r collectd-rrd.zip *;sudo mv collectd-rrd.zip %s', $tdir, $saveTo, $tdir));
            if ($stopped = file_exists($zip) && filesize($zip)) {
                print_msg(sprintf('Successfully saved collectd rrd files to %s', $zip), $verbose, __FILE__, __LINE__);
            } else {
                print_msg(sprintf('Unable to save collectd rrd files: %s', $cmd), $verbose, __FILE__, __LINE__, TRUE);
            }
        }
    } else {
        print_msg(sprintf('collectd rrd directory %s does not exist or user does not have sudo access', $dir), $verbose, __FILE__, __LINE__, TRUE);
    }
    // sleep for 10 seconds to allow collectd to restart
    sleep(10);
    return $stopped;
}
예제 #2
0
 /**
  * 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;
 }
예제 #3
0
 /**
  * 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;
 }