Example #1
0
int
DockerAPI::stats(const std::string &container, uint64_t &memUsage, uint64_t &netIn, uint64_t &netOut) {
newstats(container, memUsage, netIn, netOut);
	ArgList args;
	if ( ! add_docker_arg(args))
		return -1;
	args.AppendArg( "stats" );
	args.AppendArg( "--no-stream" );
	args.AppendArg( container.c_str() );

	MyString displayString;
	TemporaryPrivSentry sentry(PRIV_ROOT);

	args.GetArgsStringForLogging( & displayString );

	dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() );

		// Read from Docker's combined output and error streams.
	FILE * dockerResults = my_popen( args, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	const int statLineSize = 256;
	char header[statLineSize];
	char data[statLineSize];
	if( NULL == fgets( header, statLineSize, dockerResults ) ) {
		my_pclose(dockerResults);
		return -2;
	}

	if( NULL == fgets( data, statLineSize, dockerResults ) ) {
		my_pclose(dockerResults);
		return -2;
	}
	my_pclose(dockerResults);

	dprintf(D_FULLDEBUG, "Docker stats data is:\n%s\n", data);
		// condor stats output looks like:
		// Name	cpu%   mem usage/limit  mem%  net i/o   block i/o
		// container  0.00%  0 B / 0 B        0.00% 0 B / 0 B  0 B / 0 B
		//
	char memUsageUnit[2];
	char netInUnit[2];
	char netOutUnit[2];

	double memRaw, netInRaw, netOutRaw;
	int matches = sscanf(data, "%*s %*g%% %lg %s / %*g %*s %*g%% %lg %s / %lg %s", &memRaw, &memUsageUnit[0], &netInRaw, &netInUnit[0], &netOutRaw, &netOutUnit[0]);
	if (matches < 6) {
		return -2;
	}

	memUsage = convertUnits(memRaw, memUsageUnit);
	netIn    = convertUnits(netInRaw, netInUnit);
	netOut   = convertUnits(netOutRaw, netOutUnit);
  
	dprintf(D_FULLDEBUG, "memUsage is %g (%s), net In is %g (%s), net Out is %g (%s)\n", memRaw, memUsageUnit, netInRaw, netInUnit, netOutRaw, netOutUnit);
	return 0;
}
Example #2
0
//
// FIXME: We have a lot of boilerplate code in this function and file.
//
int DockerAPI::version( std::string & version, CondorError & /* err */ ) {

	ArgList versionArgs;
	if ( ! add_docker_arg(versionArgs))
		return -1;
	versionArgs.AppendArg( "-v" );

	MyString displayString;
	versionArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() );

	FILE * dockerResults = my_popen( versionArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	char buffer[1024];
	if( NULL == fgets( buffer, 1024, dockerResults ) ) {
		if( errno ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		my_pclose( dockerResults );
		return -3;
	}

	if( NULL != fgets( buffer, 1024, dockerResults ) ) {
		if( strstr( buffer, "Jansens" ) != NULL ) {
			dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker.  If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker.  The (first line of the) trailing text was '%s'.\n", displayString.c_str(), buffer );
		}
		my_pclose( dockerResults );
		return -5;
	}

	int exitCode = my_pclose( dockerResults );
	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, buffer );
		return -4;
	}

	unsigned end = strlen(buffer) - 1;
	if( buffer[end] == '\n' ) { buffer[end] = '\0'; }
	version = buffer;

	return 0;
}
Example #3
0
void PartitionManager::query_available_partitions(char *script)
{
	FILE *fin = NULL;
	ArgList args;
	priv_state priv;

	/* load a description of the available partitions which could be 
		backed, booted, or generatable. */

	dprintf(D_ALWAYS, "Finding available partitions with: %s\n", script);

	args.AppendArg(script);

	priv = set_root_priv();
	fin = my_popen(args, "r", TRUE);

	if (fin == NULL) {
		EXCEPT("Can't execute %s", script);
	}

	read_partitions(fin);

	my_pclose(fin);
	set_priv(priv);
}
Example #4
0
const char * 
sysapi_get_darwin_info(void)
{
    char ver_str[255];
    char *args[] = {"/usr/bin/sw_vers", "-productVersion", NULL};
    FILE *output_fp;

    char tmp_info[262];
    char *info_str;
    char *os_name = "MacOSX ";
 
    if ((output_fp = my_popenv(args, "r", FALSE)) != NULL) {
	fgets(ver_str, 255, output_fp);
	my_pclose(output_fp);
    } else 
    {
	info_str = strdup( "Unknown" );
    }

    int ten = 0, major = 0, minor = 0;
    int fields = sscanf(ver_str, "%d.%d.%d", &ten, &major, &minor);
    if ((fields != 3) || ten != 10) {
        dprintf(D_FULLDEBUG, "UNEXPECTED MacOS version string %s", ver_str);
    }

    sprintf( tmp_info, "%s%d.%d", os_name, major, minor);
    info_str = strdup( tmp_info );

    if( !info_str ) {
    	EXCEPT( "Out of memory!" );
    }

    return info_str;
}
Example #5
0
void
GangliaD::initializeHostList()
{
    m_monitored_hosts.clear();
    m_need_heartbeat.clear();
    m_ganglia_metrics_sent = 0;

	FILE *fp = my_popenv(m_gstat_argv,"r",MY_POPEN_OPT_WANT_STDERR);
	if( !fp ) {
		dprintf(D_ALWAYS,"Failed to execute %s: %s\n",m_gstat_command.c_str(),strerror(errno));
		return;
	}

	char line[1024];
	while( fgets(line,sizeof(line),fp) ) {
        if (char *colon = strchr(line, ':')) {
            *colon = 0;
            // if number of CPUs > 0, this host is monitored by ganglia
            if (atoi(colon + 1) > 0) {
                m_monitored_hosts.insert(line);
            }
        }
    }
    my_pclose(fp);
    dprintf(D_ALWAYS, "Ganglia is monitoring %ld hosts\n", m_monitored_hosts.size());
}
Example #6
0
void Partition::back(char *script)
{
	FILE *fin = NULL;
	ArgList args;
	MyString line;
	priv_state priv;

	dprintf(D_ALWAYS, "\t%s %s %ld %s\n",
		script,
		get_name().Value(),
		get_size(),
		pkind_xlate(get_pkind()).Value());

	args.AppendArg(script);
	args.AppendArg(get_name());
	args.AppendArg(get_size());
	args.AppendArg(pkind_xlate(get_pkind()).Value());

	priv = set_root_priv();
	fin = my_popen(args, "r", MY_POPEN_OPT_WANT_STDERR);
	line.readLine(fin); // read back OK or NOT_OK, XXX ignore
	my_pclose(fin);
	set_priv(priv);

	// we don't know it is backed until the 
	// STARTD_FACTORY_SCRIPT_AVAILABLE_PARTITIONS
	// tells us it is actually backed. This prevents overcommit of a
	// partition to multiple startds.
	set_pstate(ASSIGNED);
}
Example #7
0
// This is a blocking call and must provide a fully booted partition when it
// returns. Otherwise, this partition could be overcommitted given the 
// nature of the use of this call.
// script partition_name size kind
void Partition::boot(char *script, PKind pkind)
{
	FILE *fin = NULL;
	ArgList args;
	MyString line;
	priv_state priv;

	// we're told what kind of partition this is going to be
	set_pkind(pkind);

	dprintf(D_ALWAYS, "\t%s %s %ld %s\n",
		script,
		get_name().Value(),
		get_size(),
		pkind_xlate(get_pkind()).Value());

	args.AppendArg(script);
	args.AppendArg(get_name());
	args.AppendArg(get_size());
	args.AppendArg(pkind_xlate(get_pkind()).Value());

	priv = set_root_priv();
	fin = my_popen(args, "r", MY_POPEN_OPT_WANT_STDERR);
	line.readLine(fin); // read back OK or NOT_OK, XXX ignore
	my_pclose(fin);
	set_priv(priv);

	// Now that the script is done, mark it booted.
	set_pstate(BOOTED);
}
Example #8
0
int
run_simple_docker_command(const std::string &command, const std::string &container,
			CondorError &)
{
	ArgList args;
	if ( ! add_docker_arg(args))
		return -1;
	args.AppendArg( command );
	args.AppendArg( container.c_str() );

	MyString displayString;
	args.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() );

	// Read from Docker's combined output and error streams.
	FILE * dockerResults = my_popen( args, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	// On a success, Docker writes the containerID back out.
	char buffer[1024];
	if( NULL == fgets( buffer, 1024, dockerResults ) ) {
		if( errno ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		my_pclose( dockerResults );
		return -3;
	}

	int length = strlen( buffer );
	if( length < 1 || strncmp( buffer, container.c_str(), length - 1 ) != 0 ) {
		dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str() );
		dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
		while( NULL != fgets( buffer, 1024, dockerResults ) ) {
			dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
		}
		my_pclose( dockerResults );
		return -4;
	}

	my_pclose( dockerResults );
	return 0;
}
Example #9
0
Starter*
StarterMgr::makeStarter( const char* path )
{
	Starter* new_starter;
	FILE* fp;
	char *args[] = { const_cast<char*>(path),
					 const_cast<char*>("-classad"),
					 NULL };
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
		// note we run the starter here as root if possible,
		// since that is how the starter will be invoked for real,
		// and the real uid of the starter may influence the
		// list of capabilities the "-classad" option returns.
	{
		TemporaryPrivSentry sentry(PRIV_ROOT);
		fp = my_popenv( args, "r", FALSE );
	}

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid starter\n", buf );
			delete( ad );
			pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, 
				 "\"%s -classad\" did not produce any output, ignoring\n", 
				 path ); 
		delete( ad );
		return NULL;
	}

	new_starter = new Starter();
	new_starter->setAd( ad );
	new_starter->setPath( path );
	int is_dc = 0;
	ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc );
	new_starter->setIsDC( (bool)is_dc );

	return new_starter;
}
Example #10
0
Shadow*
ShadowMgr::makeShadow( const char* path )
{
	Shadow* new_shadow;
	FILE* fp;
	const char *args[] = {const_cast<char*>(path), "-classad", NULL};
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
	fp = my_popenv( args, "r", FALSE );

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid shadow\n", buf );
			delete( ad );
			my_pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, "\"%s -classad\" did not produce any output, "
				 "ignoring\n", path ); 
		delete( ad );
		return NULL;
	}
	new_shadow = new Shadow( path, ad );
	return new_shadow;
}
Example #11
0
void WorkloadManager::query_workloads(char *script)
{
	FILE *fin = NULL;
	int idx;
	ClassAd *ad = NULL;
	int eof, error, empty;
	const char *classad_delimitor = "---\n";
	ArgList args;
	priv_state priv;

	dprintf(D_ALWAYS, "Querying workloads with: %s\n", script);

	args.AppendArg(script);

	priv = set_root_priv();
	fin = my_popen(args, "r", TRUE);

	if (fin == NULL) {
		EXCEPT("Can't execute %s\n", script);
	}

	// wipe out whatever was there initially.
	for (idx = 0; idx < m_wklds.getsize(); idx++)
	{
		ad = m_wklds[idx].detach();
		delete ad;
	}

	m_wklds.truncate(0);

	// read a series of classads which represent the workloads this daemon
	// must try to allocate/deallocate partitions to match.
	idx = 0;
	ad = new ClassAd(fin,classad_delimitor,eof,error,empty);
	while(!empty)
	{
		m_wklds[idx].attach(ad);

		// get ready for the next one.
		idx++;

		ad = new ClassAd(fin,classad_delimitor,eof,error,empty);
	}

	// The last ad is empty, doesn't get recorded anywhere, and is deleted.
	delete(ad);

	my_pclose(fin);
	set_priv(priv);
}
Example #12
0
/*
  How much disk space we need to reserve for the AFS cache.  Answer is
  in kilobytes.
*/
static int
reserve_for_afs_cache()
{
#ifdef WIN32
	return 0;
#else
	int		answer;
	FILE	*fp;
	const char	*args[] = {FS_PROGRAM, FS_COMMAND, NULL};
	int		cache_size, cache_in_use;
	int		do_it;

	/* See if we're configured to deal with an AFS cache */
	do_it = _sysapi_reserve_afs_cache;

		/* If we're not configured to deal with AFS cache, just return 0 */
	if( !do_it ) {
		return 0;
	}

		/* Run an AFS utility program to learn how big the cache is and
		   how much is in use. */
	dprintf( D_FULLDEBUG, "Checking AFS cache parameters\n" );
	fp = my_popenv( args, "r", FALSE );
	if( !fp ) {
		return 0;
	}
	if (fscanf( fp, FS_OUTPUT_FORMAT, &cache_in_use, &cache_size ) != 2) {
		dprintf( D_ALWAYS, "Failed to parse AFS cache parameters, assuming no cache\n" );
		cache_size = 0;
		cache_in_use = 0;
	}
	my_pclose( fp );
	dprintf( D_FULLDEBUG, "cache_in_use = %d, cache_size = %d\n",
		cache_in_use,
		cache_size
	);
	answer = cache_size - cache_in_use;

		/* The cache may be temporarily over size, in this case AFS will
		   clean up itself, so we don't have to allow for that. */
	if( answer < 0 ) {
		answer = 0;
	}

	dprintf( D_FULLDEBUG, "Reserving %d kbytes for AFS cache\n", answer );
	return answer;
#endif
}
Example #13
0
Starter*
StarterMgr::makeStarter( const char* path )
{
	Starter* new_starter;
	FILE* fp;
	char *args[] = { const_cast<char*>(path),
					 const_cast<char*>("-classad"),
					 NULL };
	char buf[1024];

		// first, try to execute the given path with a "-classad"
		// option, and grab the output as a ClassAd
	fp = my_popenv( args, "r", FALSE );

	if( ! fp ) {
		dprintf( D_ALWAYS, "Failed to execute %s, ignoring\n", path );
		return NULL;
	}
	ClassAd* ad = new ClassAd;
	bool read_something = false;
	while( fgets(buf, 1024, fp) ) {
		read_something = true;
		if( ! ad->Insert(buf) ) {
			dprintf( D_ALWAYS, "Failed to insert \"%s\" into ClassAd, "
					 "ignoring invalid starter\n", buf );
			delete( ad );
			pclose( fp );
			return NULL;
		}
	}
	my_pclose( fp );
	if( ! read_something ) {
		dprintf( D_ALWAYS, 
				 "\"%s -classad\" did not produce any output, ignoring\n", 
				 path ); 
		delete( ad );
		return NULL;
	}

	new_starter = new Starter();
	new_starter->setAd( ad );
	new_starter->setPath( path );
	int is_dc = 0;
	ad->LookupBool( ATTR_IS_DAEMON_CORE, is_dc );
	new_starter->setIsDC( (bool)is_dc );

	return new_starter;
}
int
GLExecPrivSepHelper::run_script(ArgList& args,MyString &error_desc)
{
	if (!proxy_valid_right_now()) {
		dprintf(D_ALWAYS, "GLExecPrivSepHelper::run_script: not invoking glexec since the proxy is not valid!\n");
		error_desc += "The job proxy is not valid.";
		return INVALID_PROXY_RC;
	}

		/* Note that set_user_priv is a no-op if condor is running as
		   non-root (the "usual" mode for invoking glexec) */
	priv_state priv_saved = set_user_priv();
	FILE* fp = my_popen(args, "r", TRUE);
	set_priv(priv_saved);
	if (fp == NULL) {
		dprintf(D_ALWAYS,
		        "GLExecPrivSepHelper::run_script: "
		            "my_popen failure on %s: errno=%d (%s)\n",
		        args.GetArg(0),
			errno,
			strerror(errno));
		return -1;
	}
	MyString str;
	while (str.readLine(fp, true));

	priv_saved = set_user_priv();
	int ret = my_pclose(fp);
	set_priv(priv_saved);

	if (ret != 0) {
		str.trim();
		dprintf(D_ALWAYS,
		        "GLExecPrivSepHelper::run_script: %s exited "
		            "with status %d and following output:\n%s\n",
		        args.GetArg(0),
		        ret,
		        str.Value());
		error_desc.formatstr_cat("%s exited with status %d and the following output: %s",
				       condor_basename(args.GetArg(0)),
				       ret,
				       str.Value());
		error_desc.replaceString("\n","; ");
	}
	return ret;
}
Example #15
0
int DockerAPI::detect( CondorError & err ) {
	// FIXME: Remove ::version() as a public API and return it from here,
	// because there's no point in doing this twice.
	std::string version;
	if( DockerAPI::version( version, err ) != 0 ) {
		dprintf( D_ALWAYS | D_FAILURE, "DockerAPI::detect() failed to detect the Docker version; assuming absent.\n" );
		return -4;
	}

	ArgList infoArgs;
	if ( ! add_docker_arg(infoArgs))
		return -1;
	infoArgs.AppendArg( "info" );

	MyString displayString;
	infoArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() );

	FILE * dockerResults = my_popen( infoArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	// Even if we don't care about the success output, the failure output
	// can be handy for debugging...
	char buffer[1024];
	std::vector< std::string > output;
	while( fgets( buffer, 1024, dockerResults ) != NULL ) {
		unsigned end = strlen(buffer) - 1;
		if( buffer[end] == '\n' ) { buffer[end] = '\0'; }
		output.push_back( buffer );
	}
	for( unsigned i = 0; i < output.size(); ++i ) {
		dprintf( D_FULLDEBUG, "[docker info] %s\n", output[i].c_str() );
	}

	int exitCode = my_pclose( dockerResults );
	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, output[0].c_str() );
		return -3;
	}

	return 0;
}
Example #16
0
// This is a blocking call and must provide a fully shutdown partition when it
// returns.
// script partition_name 
void Partition::shutdown(char *script)
{
	FILE *fin = NULL;
	ArgList args;
	MyString line;
	priv_state priv;

	dprintf(D_ALWAYS, "\t%s %s\n",
		script,
		get_name().Value());

	args.AppendArg(script);
	args.AppendArg(get_name());

	priv = set_root_priv();
	fin = my_popen(args, "r", MY_POPEN_OPT_WANT_STDERR);
	line.readLine(fin); // read back OK or NOT_OK, XXX ignore
	my_pclose(fin);
	set_priv(priv);

	// Now that the script is done, mark it simply generated.
	set_pstate(GENERATED);
}
Example #17
0
//-----------------------------------------------------------------------------
int util_popen (ArgList &args) {
	MyString cmd; // for debug output
	args.GetArgsStringForDisplay( &cmd );
    debug_printf( DEBUG_VERBOSE, "Running: %s\n", cmd.Value() );

	FILE *fp = my_popen( args, "r", MY_POPEN_OPT_WANT_STDERR );

    int r = 0;
    if (fp == NULL || (r = my_pclose(fp) & 0xff) != 0) {
		debug_printf( DEBUG_QUIET, "Warning: failure: %s\n", cmd.Value() );
		if( fp != NULL ) {
			debug_printf ( DEBUG_QUIET,
						"\t(my_pclose() returned %d (errno %d, %s))\n",
						r, errno, strerror( errno ) );
		} else {
			debug_printf ( DEBUG_QUIET,
						"\t(my_popen() returned NULL (errno %d, %s))\n",
						errno, strerror( errno ) );
			r = -1;
		}
		check_warning_strictness( DAG_STRICT_1 );
    }
    return r;
}
Example #18
0
int
my_system(ArgList &args, Env *env_ptr)
{
	FILE* fp = my_popen(args, "w", FALSE, env_ptr);
	return (fp != NULL) ? my_pclose(fp): -1;
}
Example #19
0
int DockerAPI::detect( CondorError & err ) {
	// FIXME: Remove ::version() as a public API and return it from here,
	// because there's no point in doing this twice.
	std::string version;
	int rval = DockerAPI::version( version, err );
	if( rval  != 0 ) {
		dprintf(D_ALWAYS, "DockerAPI::detect() failed to detect the Docker version; assuming absent.\n" );
		return -4;
	}

	ArgList infoArgs;
	if ( ! add_docker_arg(infoArgs))
		return -1;
	infoArgs.AppendArg( "info" );

	MyString displayString;
	infoArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() );

#if 1
	MyPopenTimer pgm;
	if (pgm.start_program(infoArgs, true, NULL, false) < 0) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	int exitCode;
	if ( ! pgm.wait_for_exit(default_timeout, &exitCode) || exitCode != 0) {
		pgm.close_program(1);
		MyString line;
		line.readLine(pgm.output(), false); line.chomp();
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, line.c_str());
		return -3;
	}

	if (IsFulldebug(D_ALWAYS)) {
		MyString line;
		do {
			line.readLine(pgm.output(), false);
			line.chomp();
			dprintf( D_FULLDEBUG, "[docker info] %s\n", line.c_str() );
		} while (line.readLine(pgm.output(), false));
	}

#else
	FILE * dockerResults = my_popen( infoArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	// Even if we don't care about the success output, the failure output
	// can be handy for debugging...
	char buffer[1024];
	std::vector< std::string > output;
	while( fgets( buffer, 1024, dockerResults ) != NULL ) {
		size_t end = strlen(buffer);
		if (end > 0 && buffer[end-1] == '\n') { buffer[end-1] = '\0'; }
		output.push_back( buffer );
	}
	for( unsigned i = 0; i < output.size(); ++i ) {
		dprintf( D_FULLDEBUG, "[docker info] %s\n", output[i].c_str() );
	}

	int exitCode = my_pclose( dockerResults );
	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, output[0].c_str() );
		return -3;
	}
#endif
	return 0;
}
Example #20
0
/* 
** Close the stream to the mailer.  It'd be nice to return the exit
** status from the mailer here, but on many platforms we cannot safely
** do a pclose and need to do an fclose.
*/
void
email_close(FILE *mailer)
{
	char *temp;
	mode_t prev_umask;
	priv_state priv;
	char *customSig;

	if ( mailer == NULL ) {
		return;
	}

	/* Want the letter to come from "condor" if possible */
	priv = set_condor_priv();

	customSig = NULL;
	if ((customSig = param("EMAIL_SIGNATURE")) != NULL) {
		fprintf( mailer, "\n\n");
		fprintf( mailer, "%s", customSig);
		fprintf( mailer, "\n");
		free(customSig);
	} else {
		
		/* Put a signature on the bottom of the email */
		fprintf( mailer, "\n\n-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\n" );
		fprintf( mailer, "Questions about this message or HTCondor in general?\n" );

			/* See if there's an address users should use for help */
		temp = param( "CONDOR_SUPPORT_EMAIL" );
		if( ! temp ) {
			temp = param( "CONDOR_ADMIN" );
		}
		if( temp ) {
			fprintf( mailer, "Email address of the local HTCondor administrator: "
					 "%s\n", temp );
			free( temp );
		}
		fprintf( mailer, "The Official HTCondor Homepage is "
				 "http://www.cs.wisc.edu/htcondor\n" );
	}

	fflush(mailer);
	/* there are some oddities with how pclose can close a file. In some
		arches, pclose will create temp files for locking and they need to
		be of the correct perms in order to be deleted. So the umask is
		set to something useable for the close operation. -pete 9/11/99
	*/
	prev_umask = umask(022);
	/* 
	** we fclose() on UNIX, pclose on win32 
	*/
#if defined(WIN32)
	if (EMAIL_FINAL_COMMAND == NULL) {
		my_pclose( mailer );
	} else {
		char *email_filename = NULL;
		/* Should this be a pclose??? -Erik 9/21/00 */ 
		fclose( mailer );
		dprintf(D_FULLDEBUG,"Sending email via system(%s)\n",
			EMAIL_FINAL_COMMAND);
		system(EMAIL_FINAL_COMMAND);
		if ( (email_filename=strrchr(EMAIL_FINAL_COMMAND,'<')) ) {
			email_filename++;	/* go past the "<" */
			email_filename++;	/* go past the space after the < */
			if ( unlink(email_filename) == -1 ) {
				dprintf(D_ALWAYS,"email_close: cannot unlink temp file %s\n",
					email_filename);
			}
		}
		free(EMAIL_FINAL_COMMAND);
		EMAIL_FINAL_COMMAND = NULL;
	}
#else
	(void)fclose( mailer );
#endif
	umask(prev_umask);

	/* Set priv state back */
	set_priv(priv);

}
Example #21
0
static bool
submit_try( ArgList &args, CondorID &condorID, bool prohibitMultiJobs )
{
  MyString cmd; // for debug output
  args.GetArgsStringForDisplay( &cmd );

  FILE * fp = my_popen( args, "r", TRUE );
  if (fp == NULL) {
    debug_printf( DEBUG_NORMAL, 
		  "ERROR: my_popen(%s) in submit_try() failed!\n",
		  cmd.Value() );
    return false;
  }
  
  //----------------------------------------------------------------------
  // Parse submit command output for a HTCondor job ID.  This
  // desperately needs to be replaced by HTCondor submit APIs.
  //
  // Typical condor_submit output for HTCondor v6 looks like:
  //
  //   Submitting job(s).
  //   Logging submit event(s).
  //   1 job(s) submitted to cluster 2267.
  //----------------------------------------------------------------------

  char buffer[UTIL_MAX_LINE_LENGTH];
  buffer[0] = '\0';

  	// Configure what we look for in the command output according to
	// which type of job we have.
  const char *marker = NULL;
  parse_submit_fnc parseFnc = NULL;

  marker = " submitted to cluster ";

  // Note: we *could* check how many jobs got submitted here, and
  // correlate that with how many submit events we see later on.
  // I'm not worrying about that for now...  wenger 2006-02-07.
  // We also have to check the number of jobs to get an accurate
  // count of submitted jobs to report in the dagman.out file.

  // We should also check whether we got more than one cluster, and
  // either deal with it correctly or generate an error message.
  parseFnc = parse_condor_submit;
  
  // Take all of the output (both stdout and stderr) from condor_submit,
  // and echo it to the dagman.out file.  Look for
  // the line (if any) containing the word "cluster" (HTCondor).
  // If we don't find such a line, something
  // went wrong with the submit, so we return false.  The caller of this
  // function can retry the submit by repeatedly calling this function.

  MyString  command_output("");
  MyString keyLine("");
  while (fgets(buffer, UTIL_MAX_LINE_LENGTH, fp)) {
    MyString buf_line = buffer;
	buf_line.chomp();
	debug_printf(DEBUG_VERBOSE, "From submit: %s\n", buf_line.Value());
	command_output += buf_line;
    if (strstr(buffer, marker) != NULL) {
	  keyLine = buf_line;
	}
  }

  { // Relocated this curly bracket to its previous position to hopefully
    // fix Coverity warning.  Not sure why these curly brackets are here
	// at all...  wenger 2013-06-12
    int status = my_pclose(fp) & 0xff;

    if (keyLine == "") {
      debug_printf(DEBUG_NORMAL, "failed while reading from pipe.\n");
      debug_printf(DEBUG_NORMAL, "Read so far: %s\n", command_output.Value());
      return false;
    }

    if (status != 0) {
		debug_printf(DEBUG_NORMAL, "Read from pipe: %s\n", 
					 command_output.Value());
		debug_printf( DEBUG_QUIET, "ERROR while running \"%s\": "
					  "my_pclose() failed with status %d (errno %d, %s)!\n",
					  cmd.Value(), status, errno, strerror( errno ) );
		return false;
    }
  }

  int	jobProcCount;
  if ( !parseFnc( keyLine.Value(), jobProcCount, condorID._cluster) ) {
		// We are going forward (do not return false here)
		// Expectation is that higher levels will catch that we
		// did not get a cluster initialized properly here, fail,
		// and write a rescue DAG. gt3658 2013-06-03
		//
		// This is better than the old failure that would submit
		// DAGMAN_MAX_SUBMIT_ATTEMPT copies of the same job.
      debug_printf( DEBUG_NORMAL, "WARNING: submit returned 0, but "
        "parsing submit output failed!\n" );
		// Returning here so we don't try to process invalid values
		// below.  (This should really return something like "submit failed
		// don't retry" -- see gittrac #3685.)
  	  return true;
  }

  	// Check for multiple job procs if configured to disallow that.
  if ( prohibitMultiJobs && (jobProcCount > 1) ) {
	debug_printf( DEBUG_NORMAL, "Submit generated %d job procs; "
				"disallowed by DAGMAN_PROHIBIT_MULTI_JOBS setting\n",
				jobProcCount );
	main_shutdown_rescue( EXIT_ERROR, Dag::DAG_STATUS_ERROR );
  }
  
  return true;
}
Example #22
0
static void GCC_DumpStack(void)
{
  int i;
  void *p = &p; /* dummy start value */
  address_T syms[ADDRESSLIST_SIZE + 1];
  char buffer[MAX_BUFFER_SIZE];
  int fd;
  pid_t pid;
  unsigned long addr;
  unsigned long highestAddress;
  unsigned long lowestAddress;
  char type;
  char *pname;
  char name[MAX_BUFFER_SIZE];
  int number;

  for (i = 0; p; i++)
    {
      /*
       * This is based on code by Steve Coleman <steve.colemanjhuapl.edu>
       *
       * __builtin_return_address() only accepts a constant as argument.
       */
      switch (i)
	{
	case 0:
	  p = __builtin_return_address(0);
	  break;
	case 1:
	  p = __builtin_return_address(1);
	  break;
	case 2:
	  p = __builtin_return_address(2);
	  break;
	case 3:
	  p = __builtin_return_address(3);
	  break;
	case 4:
	  p = __builtin_return_address(4);
	  break;
	case 5:
	  p = __builtin_return_address(5);
	  break;
	case 6:
	  p = __builtin_return_address(6);
	  break;
	case 7:
	  p = __builtin_return_address(7);
	  break;
	case 8:
	  p = __builtin_return_address(8);
	  break;
	case 9:
	  p = __builtin_return_address(9);
	  break;
	case 10:
	  p = __builtin_return_address(10);
	  break;
	case 11:
	  p = __builtin_return_address(11);
	  break;
	case 12:
	  p = __builtin_return_address(12);
	  break;
	case 13:
	  p = __builtin_return_address(13);
	  break;
	case 14:
	  p = __builtin_return_address(14);
	  break;
	case 15:
	  p = __builtin_return_address(15);
	  break;
	case 16:
	  p = __builtin_return_address(16);
	  break;
	case 17:
	  p = __builtin_return_address(17);
	  break;
	case 18:
	  p = __builtin_return_address(18);
	  break;
	case 19:
	  p = __builtin_return_address(19);
	  break;
	default:
	  /* Change ADDRESSLIST_SIZE if more are added */
	  p = NULL;
	  break;
	}
      if ((p) && (i < ADDRESSLIST_SIZE))
	{
	  syms[i].realAddress = (unsigned long)p;
	  syms[i].closestAddress = 0;
	  syms[i].name[0] = (char)0;
	  syms[i].type = ' ';
	}
      else
	{
	  syms[i].realAddress = 0;
	  break; /* for */
	}
    } /* for */


  /* First find out if we are using GNU or vendor nm */
  number = 0;
  strcpy(buffer, "nm -V 2>/dev/null | grep GNU | wc -l");
  fd = my_popen(buffer, &pid);
  if (SYS_ERROR != fd)
    {
      if (my_getline(fd, buffer, sizeof(buffer)))
	{
	  sscanf(buffer, "%d", &number);
	}
      my_pclose(fd, pid);
    }
  if (number == 0) /* vendor nm */
    {
# if defined(PLATFORM_SOLARIS) || defined(PLATFORM_SCO) || defined(PLATFORM_HPUX)
      strcpy(buffer, "nm -x -p ");
# elif defined(PLATFORM_AIX) || defined(PLATFORM_IRIX) || defined(PLATFORM_OSF)
      strcpy(buffer, "nm -x -B ");
# else
      strcpy(buffer, "nm -B ");
# endif
    }
  else /* GNU nm */
    strcpy(buffer, "nm -B ");
  strcat(buffer, global_progname);

  lowestAddress = ULONG_MAX;
  highestAddress = 0;
  fd = my_popen(buffer, &pid);
  if (SYS_ERROR != fd)
    {
      while (my_getline(fd, buffer, sizeof(buffer)))
	{
	  if (buffer[0] == '\n')
	    continue;
	  if (3 == sscanf(buffer, "%lx %c %s", &addr, &type, name))
	    {
	      if ((type == 't') || type == 'T')
		{
		  if (addr == 0)
		    continue; /* while */
		  if (addr < lowestAddress)
		    lowestAddress = addr;
		  if (addr > highestAddress)
		    highestAddress = addr;
		  for (i = 0; syms[i].realAddress != 0; i++)
		    {
		      if ((addr <= syms[i].realAddress) &&
			  (addr > syms[i].closestAddress))
			{
			  syms[i].closestAddress = addr;
			  strncpy(syms[i].name, name, MAX_BUFFER_SIZE);
			  syms[i].name[MAX_BUFFER_SIZE] = (char)0;
			  syms[i].type = type;
			}
		    }
		}
	    }
	}
      my_pclose(fd, pid);

      for (i = 0; syms[i].realAddress != 0; i++)
	{
	  if ((syms[i].name[0] == (char)0) ||
	      (syms[i].realAddress <= lowestAddress) ||
	      (syms[i].realAddress >= highestAddress))
	    {
	      sprintf(buffer, "[%d] 0x%08lx ???\n", i, syms[i].realAddress);
	    }
	  else
	    {
	      sprintf(buffer, "[%d] 0x%08lx <%s + 0x%lx> %c\n",
		      i,
		      syms[i].realAddress,
		      syms[i].name,
		      syms[i].realAddress - syms[i].closestAddress,
		      syms[i].type);
	    }
	  write(global_output, buffer, strlen(buffer));
	}
    }
}
Example #23
0
/*************************************************************************
 * DumpStack [private]
 */
static int DumpStack(char *format, ...)
{
  int gotSomething = FALSE;
  int fd;
  pid_t pid;
  int status = EXIT_FAILURE;
  int rc;
  va_list args;
  char *buffer;
  char cmd[MAX_BUFFER_SIZE];
  char buf[MAX_BUFFER_SIZE];

  /*
   * Please note that vsprintf() is not ASync safe (ie. cannot safely
   * be used from a signal handler.) If this proves to be a problem
   * then the cmd string can be built by more basic functions such as
   * strcpy, strcat, and a homemade integer-to-ascii function.
   */
  va_start(args, format);
  vsprintf(cmd, format, args);
  va_end(args);
  
  fd = my_popen(cmd, &pid);
  if (SYS_ERROR != fd)
    {
      /*
       * Wait for the child to exit. This must be done
       * to make the debugger attach successfully.
       * The output from the debugger is buffered on
       * the pipe.
       *
       * AIX needs the looping hack
       */
      do
	{
	  rc = waitpid(pid, &status, 0);
	}
      while ((SYS_ERROR == rc) && (EINTR == errno));

      //FIXME: deactivated separate piping of debugger output, as it caused problems in conjunction with threads
/*
      if ((WIFEXITED(status)) && (WEXITSTATUS(status) == EXIT_SUCCESS))
	{
	  while (my_getline(fd, buf, sizeof(buf)))
	    {
	      buffer = buf;
	      if (! gotSomething)
		{
		  write(global_output, "Output from ",
			strlen("Output from "));
		  strtok(cmd, " ");
		  write(global_output, cmd, strlen(cmd));
		  write(global_output, "\n", strlen("\n"));
		  gotSomething = TRUE;
		}
	      if ('\n' == buf[strlen(buf)-1])
		{
		  buf[strlen(buf)-1] = (char)0;
		}
	      write(global_output, buffer, strlen(buffer));
	      write(global_output, "\n", strlen("\n"));
	    }
	}
*/
      gotSomething = TRUE; //HACK: to compensate the commented FIXME block above

      my_pclose(fd, pid);
    }
  return gotSomething;
}
Example #24
0
float
lookup_load_avg_via_uptime()
{
	
	float    loadavg;
	FILE *output_fp;
	int counter;
	char word[20];

	if (uptime_path == NULL) {
		uptime_path = path_to_uptime();
	}

	/*  We start uptime and pipe its output to ourselves.
	 *  Then we read word by word till we get "load average".  We read the
	 *  next number.  This is the number we want.
	 */
	if (uptime_path != NULL) {
		char *args[2] = {uptime_path, NULL};
		if ((output_fp = my_popenv(args, "r", FALSE)) == NULL) {
			return DEFAULT_LOADAVG;
		}
		
		do { 
			if (fscanf(output_fp, "%s", word) == EOF) {
				dprintf(D_ALWAYS,"can't get \"average:\" from uptime\n");
				my_pclose(output_fp);
				return DEFAULT_LOADAVG;
			}
			
			if (strcmp(word, "average:") == 0) {
				/*
				 *  We are at the required position.  Read in the next
				 *  floating
				 *  point number.  That is the required average.
				 */
				if (fscanf(output_fp, "%f", &loadavg) != 1) {
					dprintf(D_ALWAYS, "can't read loadavg from uptime\n");
					my_pclose(output_fp);
					return DEFAULT_LOADAVG;
				}
				
				/*
				 *  Some callers of this routine may have a SIGCHLD handler.
				 *  If this is so, calling pclose will interfere withthat.
				 *  We check if this is the case and use fclose instead.
				 *  -- Ajitk
				 */
				my_pclose(output_fp);
				return loadavg;
			}
		} while (!feof(output_fp)); 
		
		/*
		 *  Reached EOF before getting at load average!  -- Ajitk
		 */
        
		my_pclose(output_fp);
	}

	
	/* not reached */
	return DEFAULT_LOADAVG;
}
Example #25
0
static int
slow_poll(FILE *dbgfp, int dbgall, size_t *nbytes )
{
    int moreSources;
    struct timeval tv;
    fd_set fds;
#if defined( __hpux )
    size_t maxFD = 0;
#else
    int maxFD = 0;
#endif /* OS-specific brokenness */
    int bufPos, i, usefulness = 0;


    /* Fire up each randomness source */
    FD_ZERO(&fds);
    for (i = 0; dataSources[i].path != NULL; i++) {
	/* Since popen() is a fairly heavy function, we check to see whether
	 * the executable exists before we try to run it */
	if (access(dataSources[i].path, X_OK)) {
	    if( dbgfp && dbgall )
		fprintf(dbgfp, "%s not present%s\n", dataSources[i].path,
			       dataSources[i].hasAlternative ?
					", has alternatives" : "");
	    dataSources[i].pipe = NULL;
	}
	else
	    dataSources[i].pipe = my_popen(&dataSources[i]);

	if (dataSources[i].pipe != NULL) {
	    dataSources[i].pipeFD = fileno(dataSources[i].pipe);
	    if (dataSources[i].pipeFD > maxFD)
		maxFD = dataSources[i].pipeFD;

#ifdef O_NONBLOCK /* Ohhh what a hack (used for Atari) */
	    fcntl(dataSources[i].pipeFD, F_SETFL, O_NONBLOCK);
#else
#error O_NONBLOCK is missing
#endif

	    FD_SET(dataSources[i].pipeFD, &fds);
	    dataSources[i].length = 0;

	    /* If there are alternatives for this command, don't try and
	     * execute them */
	    while (dataSources[i].hasAlternative) {
		if( dbgfp && dbgall )
		    fprintf(dbgfp, "Skipping %s\n", dataSources[i + 1].path);
		i++;
	    }
	}
    }


    /* Suck all the data we can get from each of the sources */
    bufPos = 0;
    moreSources = 1;
    while (moreSources && bufPos <= gather_buffer_size) {
	/* Wait for data to become available from any of the sources, with a
	 * timeout of 10 seconds.  This adds even more randomness since data
	 * becomes available in a nondeterministic fashion.  Kudos to HP's QA
	 * department for managing to ship a select() which breaks its own
	 * prototype */
	tv.tv_sec = 10;
	tv.tv_usec = 0;

#if defined( __hpux ) && ( OS_VERSION == 9 )
	if (select(maxFD + 1, (int *)&fds, NULL, NULL, &tv) == -1)
#else  /*  */
	if (select(maxFD + 1, &fds, NULL, NULL, &tv) == -1)
#endif /* __hpux */
	    break;

	/* One of the sources has data available, read it into the buffer */
	for (i = 0; dataSources[i].path != NULL; i++) {
	    if( dataSources[i].pipe && FD_ISSET(dataSources[i].pipeFD, &fds)) {
		size_t noBytes;

		if ((noBytes = fread(gather_buffer + bufPos, 1,
				     gather_buffer_size - bufPos,
				     dataSources[i].pipe)) == 0) {
		    if (my_pclose(&dataSources[i]) == 0) {
			int total = 0;

			/* Try and estimate how much entropy we're getting
			 * from a data source */
			if (dataSources[i].usefulness) {
			    if (dataSources[i].usefulness < 0)
				total = (dataSources[i].length + 999)
					/ -dataSources[i].usefulness;
			    else
				total = dataSources[i].length
					/ dataSources[i].usefulness;
			}
			if( dbgfp )
			    fprintf(dbgfp,
			       "%s %s contributed %d bytes, "
			       "usefulness = %d\n", dataSources[i].path,
			       (dataSources[i].arg != NULL) ?
				       dataSources[i].arg : "",
				      dataSources[i].length, total);
			if( dataSources[i].length )
			    usefulness += total;
		    }
		    dataSources[i].pipe = NULL;
		}
		else {
		    int currPos = bufPos;
		    int endPos = bufPos + noBytes;

		    /* Run-length compress the input byte sequence */
		    while (currPos < endPos) {
			int ch = gather_buffer[currPos];

			/* If it's a single byte, just copy it over */
			if (ch != gather_buffer[currPos + 1]) {
			    gather_buffer[bufPos++] = ch;
			    currPos++;
			}
			else {
			    int count = 0;

			    /* It's a run of repeated bytes, replace them
			     * with the byte count mod 256 */
			    while ((ch == gather_buffer[currPos])
				    && currPos < endPos) {
				count++;
				currPos++;
			    }
			    gather_buffer[bufPos++] = count;
			    noBytes -= count - 1;
			}
		    }

		    /* Remember the number of (compressed) bytes of input we
		     * obtained */
		    dataSources[i].length += noBytes;
		}
	    }
	}

	/* Check if there is more input available on any of the sources */
	moreSources = 0;
	FD_ZERO(&fds);
	for (i = 0; dataSources[i].path != NULL; i++) {
	    if (dataSources[i].pipe != NULL) {
		FD_SET(dataSources[i].pipeFD, &fds);
		moreSources = 1;
	    }
	}
    }

    if( dbgfp ) {
	fprintf(dbgfp, "Got %d bytes, usefulness = %d\n", bufPos, usefulness);
	fflush(dbgfp);
    }
    *nbytes = bufPos;
    return usefulness;
}
Example #26
0
int DockerAPI::rm( const std::string & containerID, CondorError & /* err */ ) {

	ArgList rmArgs;
	if ( ! add_docker_arg(rmArgs))
		return -1;
	rmArgs.AppendArg( "rm" );
	rmArgs.AppendArg( "-f" );  // if for some reason still running, kill first
	rmArgs.AppendArg( "-v" );  // also remove the volume
	rmArgs.AppendArg( containerID.c_str() );

	MyString displayString;
	rmArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() );

	// Read from Docker's combined output and error streams.
#if 1
	MyPopenTimer pgm;
	if (pgm.start_program( rmArgs, true, NULL, false ) < 0) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}
	const char * got_output = pgm.wait_and_close(default_timeout);

	// On a success, Docker writes the containerID back out.
	MyString line;
	if ( ! got_output || ! line.readLine(pgm.output(), false)) {
		int error = pgm.error_code();
		if( error ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), pgm.error_str(), error );
			if (pgm.was_timeout()) {
				dprintf( D_ALWAYS | D_FAILURE, "Declaring a hung docker\n");
				return docker_hung;
			}
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		return -3;
	}

	line.chomp(); line.trim();
	if (line != containerID.c_str()) {
		// Didn't get back the result I expected, report the error and check to see if docker is hung.
		return check_if_docker_offline(pgm, "Docker remove", -4);
	}
#else
	FILE * dockerResults = my_popen( rmArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	// On a success, Docker writes the containerID back out.
	char buffer[1024];
	if( NULL == fgets( buffer, 1024, dockerResults ) ) {
		if( errno ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		my_pclose( dockerResults );
		return -3;
	}

	int length = strlen( buffer );
	if( length < 1 || strncmp( buffer, containerID.c_str(), length - 1 ) != 0 ) {
		dprintf( D_ALWAYS | D_FAILURE, "Docker remove failed, printing first few lines of output.\n" );
		dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
		while( NULL != fgets( buffer, 1024, dockerResults ) ) {
			dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
		}
		my_pclose( dockerResults );
		return -4;
	}

	my_pclose( dockerResults );
#endif
	return 0;
}
Example #27
0
int
DockerAPI::rmi(const std::string &image, CondorError &err) {
		// First, try to remove the named image
	run_simple_docker_command("rmi", image, default_timeout, err, true);
		
		// That may have succeed or failed.  It could have
		// failed if the image doesn't exist (anymore), or
		// if someone else deleted it outside of condor.
		// Check to see if the image still exists.  If it
		// has been removed, return 0.

	ArgList args;
	if ( ! add_docker_arg(args))
		return -1;
	args.AppendArg( "images" );
	args.AppendArg( "-q" );
	args.AppendArg( image );

	MyString displayString;
	args.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() );

#if 1
	MyPopenTimer pgm;
	if (pgm.start_program(args, true, NULL, false) < 0) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	int exitCode;
	if ( ! pgm.wait_for_exit(default_timeout, &exitCode) || exitCode != 0) {
		pgm.close_program(1);
		MyString line;
		line.readLine(pgm.output(), false); line.chomp();
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, line.c_str());
		return -3;
	}

	return pgm.output_size() > 0;
#else
	FILE * dockerResults = my_popen( args, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	char buffer[1024];
	std::vector< std::string > output;
	while( fgets( buffer, 1024, dockerResults ) != NULL ) {
		size_t end = strlen(buffer);
		if (end > 0 && buffer[end-1] == '\n') { buffer[end-1] = '\0'; }
		output.push_back( buffer );
	}

	int exitCode = my_pclose( dockerResults );
	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, output[0].c_str() );
		return -3;
	}

	if (output.size() == 0) {
		return 0;
	} else {
		return 1;
	}
#endif
}
Example #28
0
//
// FIXME: We have a lot of boilerplate code in this function and file.
//
int DockerAPI::version( std::string & version, CondorError & /* err */ ) {

	ArgList versionArgs;
	if ( ! add_docker_arg(versionArgs))
		return -1;
	versionArgs.AppendArg( "-v" );

	MyString displayString;
	versionArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: '%s'.\n", displayString.c_str() );

#if 1
	MyPopenTimer pgm;
	if (pgm.start_program(versionArgs, true, NULL, false) < 0) {
		// treat 'file not found' as not really error
		int d_level = (pgm.error_code() == ENOENT) ? D_FULLDEBUG : (D_ALWAYS | D_FAILURE);
		dprintf(d_level, "Failed to run '%s' errno=%d %s.\n", displayString.c_str(), pgm.error_code(), pgm.error_str() );
		return -2;
	}

	int exitCode;
	if ( ! pgm.wait_for_exit(default_timeout, &exitCode)) {
		pgm.close_program(1);
		dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), pgm.error_str(), pgm.error_code() );
		return -3;
	}

	if (pgm.output_size() <= 0) {
		dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		return -3;
	}

	MyStringSource * src = &pgm.output();
	MyString line;
	if (line.readLine(*src, false)) {
		line.chomp();
		bool jansens = strstr( line.c_str(), "Jansens" ) != NULL;
		bool bad_size = ! src->isEof() || line.size() > 1024 || line.size() < (int)sizeof("Docker version ");
		if (bad_size && ! jansens) {
			// check second line of output for the word Jansens also.
			MyString tmp; tmp.readLine(*src, false);
			jansens = strstr( tmp.c_str(), "Jansens" ) != NULL;
		}
		if (jansens) {
			dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker.  If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" );
			return -5;
		} else if (bad_size) {
			dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker.  The (first line of the) trailing text was '%s'.\n", displayString.c_str(), line.c_str() );
			return -5;
		}
	}

	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, line.c_str() );
		return -4;
	}

	version = line.c_str();

#else
	FILE * dockerResults = my_popen( versionArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	char buffer[1024];
	if( NULL == fgets( buffer, 1024, dockerResults ) ) {
		if( errno ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		my_pclose( dockerResults );
		return -3;
	}

	if( NULL != fgets( buffer, 1024, dockerResults ) ) {
		if( strstr( buffer, "Jansens" ) != NULL ) {
			dprintf( D_ALWAYS | D_FAILURE, "The DOCKER configuration setting appears to point to OpenBox's docker.  If you want to use Docker.IO, please set DOCKER appropriately in your configuration.\n" );
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "Read more than one line (or a very long line) from '%s', which we think means it's not Docker.  The (first line of the) trailing text was '%s'.\n", displayString.c_str(), buffer );
		}
		my_pclose( dockerResults );
		return -5;
	}

	int exitCode = my_pclose( dockerResults );
	if( exitCode != 0 ) {
		dprintf( D_ALWAYS, "'%s' did not exit successfully (code %d); the first line of output was '%s'.\n", displayString.c_str(), exitCode, buffer );
		return -4;
	}

	size_t end = strlen(buffer);
	if (end > 0 && buffer[end-1] == '\n') { buffer[end-1] = '\0'; }
	version = buffer;
#endif
	sscanf(version.c_str(), "Docker version %d.%d", &DockerAPI::majorVersion, &DockerAPI::minorVersion);
	return 0;
}
Example #29
0
int
run_simple_docker_command(const std::string &command, const std::string &container, int timeout, CondorError &, bool ignore_output)
{
  ArgList args;
  if ( ! add_docker_arg(args))
    return -1;
  args.AppendArg( command );
  args.AppendArg( container.c_str() );

  MyString displayString;
  args.GetArgsStringForLogging( & displayString );
  dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() );

#if 1
	MyPopenTimer pgm;
	if (pgm.start_program( args, true, NULL, false ) < 0) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -2;
	}

	if ( ! pgm.wait_and_close(timeout) || pgm.output_size() <= 0) {
		int error = pgm.error_code();
		if( error ) {
			dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), pgm.error_str(), error );
			if (pgm.was_timeout()) {
				dprintf( D_ALWAYS | D_FAILURE, "Declaring a hung docker\n");
				return DockerAPI::docker_hung;
			}
		} else {
			dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
		}
		return -3;
	}

	// On a success, Docker writes the containerID back out.
	MyString line;
	line.readLine(pgm.output());
	line.chomp(); line.trim();
	if (!ignore_output && line != container.c_str()) {
		// Didn't get back the result I expected, report the error and check to see if docker is hung.
		dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str());
		for (int ii = 0; ii < 10; ++ii) {
			if ( ! line.readLine(pgm.output(), false)) break;
			dprintf( D_ALWAYS | D_FAILURE, "%s\n", line.c_str() );
		}
		return -4;
	}

#else
  // Read from Docker's combined output and error streams.
  FILE * dockerResults = my_popen( args, "r", 1 , 0, false);
  if( dockerResults == NULL ) {
    dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
    return -2;
  }

  // On a success, Docker writes the containerID back out.
  char buffer[1024];
  if( NULL == fgets( buffer, 1024, dockerResults ) ) {
    if( errno ) {
      dprintf( D_ALWAYS | D_FAILURE, "Failed to read results from '%s': '%s' (%d)\n", displayString.c_str(), strerror( errno ), errno );
    } else {
      dprintf( D_ALWAYS | D_FAILURE, "'%s' returned nothing.\n", displayString.c_str() );
    }
    my_pclose( dockerResults );
    return -3;
  }

  size_t length = strlen( buffer );
  if (!ignore_output) {
    if( length < 1 || strncmp( buffer, container.c_str(), length - 1 ) != 0 ) {
      dprintf( D_ALWAYS | D_FAILURE, "Docker %s failed, printing first few lines of output.\n", command.c_str() );
      dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
      while( NULL != fgets( buffer, 1024, dockerResults ) ) {
	dprintf( D_ALWAYS | D_FAILURE, "%s", buffer );
      }
      my_pclose( dockerResults );
      return -4;
    }
  }

  my_pclose( dockerResults );
#endif
  return 0;
}
Example #30
0
int DockerAPI::inspect( const std::string & containerID, ClassAd * dockerAd, CondorError & /* err */ ) {
	if( dockerAd == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "dockerAd is NULL.\n" );
		return -2;
	}

	ArgList inspectArgs;
	if ( ! add_docker_arg(inspectArgs))
		return -1;
	inspectArgs.AppendArg( "inspect" );
	inspectArgs.AppendArg( "--format" );
	StringList formatElements(	"ContainerId=\"{{.Id}}\" "
								"Pid={{.State.Pid}} "
								"Name=\"{{.Name}}\" "
								"Running={{.State.Running}} "
								"ExitCode={{.State.ExitCode}} "
								"StartedAt=\"{{.State.StartedAt}}\" "
								"FinishedAt=\"{{.State.FinishedAt}}\" "
								"DockerError=\"{{.State.Error}}\" "
								"OOMKilled=\"{{.State.OOMKilled}}\" " );
	char * formatArg = formatElements.print_to_delimed_string( "\n" );
	inspectArgs.AppendArg( formatArg );
	free( formatArg );
	inspectArgs.AppendArg( containerID );

	MyString displayString;
	inspectArgs.GetArgsStringForLogging( & displayString );
	dprintf( D_FULLDEBUG, "Attempting to run: %s\n", displayString.c_str() );

#if 1
	MyPopenTimer pgm;
	if (pgm.start_program(inspectArgs, true, NULL, false) < 0) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to run '%s'.\n", displayString.c_str() );
		return -6;
	}

	MyStringSource * src = NULL;
	if (pgm.wait_and_close(default_timeout)) {
		src = &pgm.output();
	}

	int expected_rows = formatElements.number();
	dprintf( D_FULLDEBUG, "exit_status=%d, error=%d, %d bytes. expecting %d lines\n",
		pgm.exit_status(), pgm.error_code(), pgm.output_size(), expected_rows );

	// If the output isn't exactly formatElements.number() lines long,
	// something has gone wrong and we'll at least be able to print out
	// the error message(s).
	std::vector<std::string> correctOutput(expected_rows);
	if (src) {
		MyString line;
		int i=0;
		while (line.readLine(*src,false)) {
			line.chomp();
			//dprintf( D_FULLDEBUG, "\t[%2d] %s\n", i, line.c_str() );
			if (i >= expected_rows) {
				if (line.empty()) continue;
				correctOutput.push_back(line.c_str());
			} else {
				correctOutput[i] = line.c_str();
			}
			std::string::iterator first = 
				std::find(correctOutput[i].begin(),
					correctOutput[i].end(),
					'\"');
			if (first != correctOutput[i].end()) {
				std::replace(++first,
					--correctOutput[i].end(), '\"','\'');
			}
			//dprintf( D_FULLDEBUG, "\tfix: %s\n", correctOutput[i].c_str() );
			++i;
		}
	}
#else
	FILE * dockerResults = my_popen( inspectArgs, "r", 1 , 0, false);
	if( dockerResults == NULL ) {
		dprintf( D_ALWAYS | D_FAILURE, "Unable to run '%s'.\n", displayString.c_str() );
		return -6;
	}

	// If the output isn't exactly formatElements.number() lines long,
	// something has gone wrong and we'll at least be able to print out
	// the error message(s).
	char buffer[1024];
	std::vector<std::string> correctOutput(formatElements.number());
	for( int i = 0; i < formatElements.number(); ++i ) {
		if( fgets( buffer, 1024, dockerResults ) != NULL ) {
			correctOutput[i] = buffer;
			std::string::iterator first = 
				std::find(correctOutput[i].begin(),
					correctOutput[i].end(),
					'\"');
			if (first != correctOutput[i].end()) {
				std::replace(++first,
					-- --correctOutput[i].end(), '\"','\'');
			}
		}
	}
	my_pclose( dockerResults );
#endif

	int attrCount = 0;
	for( int i = 0; i < formatElements.number(); ++i ) {
		if( correctOutput[i].empty() || dockerAd->Insert( correctOutput[i].c_str() ) == FALSE ) {
			break;
		}
		++attrCount;
	}

	if( attrCount != formatElements.number() ) {
		dprintf( D_ALWAYS | D_FAILURE, "Failed to create classad from Docker output (%d).  Printing up to the first %d (nonblank) lines.\n", attrCount, formatElements.number() );
		for( int i = 0; i < formatElements.number() && ! correctOutput[i].empty(); ++i ) {
			dprintf( D_ALWAYS | D_FAILURE, "%s", correctOutput[i].c_str() );
		}
		return -4;
	}

	dprintf( D_FULLDEBUG, "docker inspect printed:\n" );
	for( int i = 0; i < formatElements.number() && ! correctOutput[i].empty(); ++i ) {
		dprintf( D_FULLDEBUG, "\t%s\n", correctOutput[i].c_str() );
	}
	return 0;
}