def install(self):
        """
        Download and install the Elasticsearch software in the install path. If already downloaded or installed
        those steps are skipped.

        :rtype : ElasticsearchRunner
        :return: The instance called on.
        """
        if self.version in ES_URLS:
            download_url = ES_URLS[self.version]
        else:
            if self.version.startswith('1'):
                download_url = "%s-%s.zip" % (ES_DEFAULT_URL_LOCATION, self.version)
            else:
                download_url = "%s%s/elasticsearch-%s.zip" % (ES2_DEFAULT_URL_LOCATION, self.version, self.version)
        es_archive_fn = download_file(download_url, self.install_path)

        if not os.path.exists(os.path.join(self.install_path, self.version_folder)):
            with ZipFile(es_archive_fn, "r") as z:
                z.extractall(self.install_path)

        # insert basic config file
        copyfile(os.path.join(package_path(), 'elasticsearch_runner', 'resources', 'embedded_elasticsearch.yml'),
                 os.path.join(self.install_path, self.version_folder, 'config', 'elasticsearch.yml'))

        return self
    def run(self):
        """
        Start the elasticsearch server. Running REST port and PID is stored in the es_state field.

        :rtype : ElasticsearchRunner
        :return: The instance called on.
        """
        if self.is_running():
            logging.warn('Elasticsearch already running ...')
        else:
            # generate and insert Elasticsearch configuration file with transient data and log paths
            cluster_name = generate_cluster_name()
            cluster_path = mkdtemp(prefix='%s-%s-' % (self.version, cluster_name), dir=self.install_path)
            es_data_dir = os.path.join(cluster_path, "data")
            es_config_dir = os.path.join(cluster_path, "config")
            es_log_dir = os.path.join(cluster_path, "log")
            self.es_config = generate_config(cluster_name=cluster_name, data_path=es_data_dir, log_path=es_log_dir)
            config_fn = os.path.join(es_config_dir, 'elasticsearch.yml')

            try:
                os.makedirs(es_log_dir)
                os.makedirs(es_data_dir)
                os.makedirs(es_config_dir)
            except OSError as exception:
                if exception.errno != errno.EEXIST:
                    raise
            with open(config_fn, 'w') as f:
                serialize_config(f, self.es_config)

            copyfile(os.path.join(package_path(), 'elasticsearch_runner', 'resources', 'embedded_logging.yml'),
                 os.path.join(es_config_dir, 'logging.yml'))

            es_log_fn = os.path.join(es_log_dir, '%s.log' % cluster_name)
            # create the log file if it doesn't exist yet. We need to open it and seek to to the end before
            # sniffing out the configuration info from the log.

            open(es_log_fn, 'a').close()

            runcall = self._es_wrapper_call(os.name) + ['-Des.path.conf=%s' % es_config_dir, '-Des.path.logs=%s' % es_log_dir]
            wrapper_proc = Popen(runcall)

            es_log_f = open(es_log_fn, 'r')
            es_log_f.seek(0, 2)

            # watch the log
            server_pid, es_port = parse_es_log_header(es_log_f)

            if not server_pid:
                logging.error('Server PID not detected ... runcall was %s' % runcall)

            if not es_port:
                logging.error('Server http port not detected ...')

            self.es_state = ElasticsearchState(wrapper_pid=wrapper_proc.pid,
                                               server_pid=server_pid,
                                               port=es_port,
                                               config_fn=config_fn)
        return self