def create_session(docker_image=None,
                   docker_rm=None,
                   echo=False,
                   loglevel='WARNING',
                   nocolor=False,
                   session_type='bash',
                   vagrant_session_name=None,
                   vagrant_image='ubuntu/xenial64',
                   vagrant_gui=False,
                   vagrant_memory='1024',
                   vagrant_num_machines='1',
                   vagrant_provider='virtualbox',
                   vagrant_root_folder=None,
                   vagrant_swapsize='2G',
                   vagrant_version='1.8.6',
                   vagrant_virt_method='virtualbox',
                   video=-1,
                   walkthrough=False):
	"""Creates a distinct ShutIt session. Sessions can be of type:

	bash    - a bash shell is spawned and
	vagrant - a Vagrantfile is created and 'vagrant up'ped
	"""
	assert session_type in ('bash','docker','vagrant'), shutit_util.print_debug()
	shutit_global_object = shutit_global.shutit_global_object
	if video != -1 and video > 0:
		walkthrough = True
	if session_type in ('bash','docker'):
		return shutit_global_object.create_session(session_type,
		                                           docker_image=docker_image,
		                                           rm=docker_rm,
		                                           echo=echo,
		                                           walkthrough=walkthrough,
		                                           walkthrough_wait=video,
		                                           nocolor=nocolor,
		                                           loglevel=loglevel)
	elif session_type == 'vagrant':
		if vagrant_session_name is None:
			vagrant_session_name = 'shutit' + shutit_util.random_id()
		if isinstance(vagrant_num_machines, int):
			vagrant_num_machines = str(vagrant_num_machines)
		assert isinstance(vagrant_num_machines, str)
		assert isinstance(int(vagrant_num_machines), int)
		if vagrant_root_folder is None:
			vagrant_root_folder = shutit_global.shutit_global_object.owd
		return create_session_vagrant(vagrant_session_name,
		                              vagrant_num_machines,
		                              vagrant_image,
		                              vagrant_provider,
		                              vagrant_gui,
		                              vagrant_memory,
		                              vagrant_swapsize,
		                              echo,
		                              walkthrough,
		                              nocolor,
		                              video,
		                              vagrant_version,
		                              vagrant_virt_method,
		                              vagrant_root_folder,
		                              loglevel)
Esempio n. 2
0
	def setup_prompt(self,
	                 prompt_name,
	                 prefix='default',
	                 delaybeforesend=0,
	                 loglevel=logging.DEBUG):
		"""Use this when you've opened a new shell to set the PS1 to something
		sane. By default, it sets up the default expect so you don't have to
		worry about it and can just call shutit.send('a command').
		
		If you want simple login and logout, please use login() and logout()
		within this module.
		
		Typically it would be used in this boilerplate pattern::
		
		    shutit.send('su - auser', expect=shutit_global.shutit.cfg['expect_prompts']['base_prompt'], check_exit=False)
		    shutit.setup_prompt('tmp_prompt')
		    shutit.send('some command')
		    [...]
		    shutit.set_default_shutit_pexpect_session_expect()
		    shutit.send('exit')
		
		This function is assumed to be called whenever there is a change
		of environment.
		
		@param prompt_name:         Reference name for prompt.
		@param prefix:              Prompt prefix. Default: 'default'
		@param shutit_pexpect_child:               See send()
		                            to the new prompt. Default: True
		
		@type prompt_name:          string
		@type prefix:               string
		"""
		local_prompt = prefix + '#' + shutit_util.random_id() + '> '
		cfg = shutit_global.shutit.cfg
		cfg['expect_prompts'][prompt_name] = local_prompt
		# Set up the PS1 value.
		# Unset the PROMPT_COMMAND as this can cause nasty surprises in the output.
		# Set the cols value, as unpleasant escapes are put in the output if the
		# input is > n chars wide.
		# The newline in the expect list is a hack. On my work laptop this line hangs
		# and times out very frequently. This workaround seems to work, but I
		# haven't figured out why yet - imiell.
		shutit_global.shutit.send((" export SHUTIT_BACKUP_PS1_%s=$PS1 && PS1='%s' && unset PROMPT_COMMAND && stty sane && stty cols " + str(cfg['build']['stty_cols'])) % (prompt_name, local_prompt), expect=['\r\n' + cfg['expect_prompts'][prompt_name]], fail_on_empty_before=False, timeout=5, shutit_pexpect_child=self.pexpect_child, echo=False, loglevel=loglevel, delaybeforesend=delaybeforesend)
		shutit_global.shutit.log('Resetting default expect to: ' + cfg['expect_prompts'][prompt_name],level=logging.DEBUG)
		self.default_expect = cfg['expect_prompts'][prompt_name]
		# Ensure environment is set up OK.
		self.setup_environment(prefix)
Esempio n. 3
0
 def __init__(self, sendspec):
     # Stub this with a simple command for now
     self.sendspec = sendspec
     self.block_other_commands = sendspec.block_other_commands
     self.retry = sendspec.retry
     self.tries = 0
     self.pid = None
     self.return_value = None
     self.start_time = None
     self.run_state = 'N'  # State as per ps man page, but 'C' == Complete, 'N' == not started, 'F' == failed, 'S' == sleeping/running, 'T' == timed out by ShutIt
     self.cwd = self.sendspec.shutit_pexpect_child.send_and_get_output(
         ' command pwd', ignore_background=True)
     self.id = shutit_util.random_id()
     self.output_file = '/tmp/shutit_background_' + self.id + '_output.log'
     self.exit_code_file = '/tmp/shutit_background_' + self.id + '_exit_code_file.log'
     if self.sendspec.run_in_background:
         self.sendspec.send = ' set +m && { : $(command cd ' + self.cwd + '>' + self.output_file + ' && ' + self.sendspec.send + ' >>' + self.output_file + ' 2>&1; echo $? >' + self.exit_code_file + ') & } 2>/dev/null'
Esempio n. 4
0
	def __init__(self,
	             sendspec):
		# Stub this with a simple command for now
		self.sendspec               = sendspec
		self.block_other_commands   = sendspec.block_other_commands
		self.retry                  = sendspec.retry
		self.tries                  = 0
		self.pid                    = None
		self.return_value           = None
		self.start_time             = None
		self.run_state              = 'N' # State as per ps man page, but 'C' == Complete, 'N' == not started, 'F' == failed, 'S' == sleeping/running, 'T' == timed out by ShutIt
		self.cwd                    = self.sendspec.shutit_pexpect_child.send_and_get_output(' command pwd', ignore_background=True)
		self.id                     = shutit_util.random_id()
		self.output_file            = '/tmp/shutit_background_' + self.id + '_output.log'
		self.exit_code_file         = '/tmp/shutit_background_' + self.id + '_exit_code_file.log'
		self.command_file           = '/tmp/shutit_background_' + self.id + '_command.log'
		if self.sendspec.run_in_background:
			# TODO: consider separating out into a simple send for the part that creates the command file, the cd and the output file. Perhaps send file first and run that in the background?
			self.sendspec.send          = ' set +m && { : $(echo "' + self.sendspec.original_send + '" >' + self.command_file + ' && command cd "' + self.cwd + '">' + self.output_file + ' && ' + self.sendspec.send + ' >>' + self.output_file + ' 2>&1; echo $? >' + self.exit_code_file + ') & } 2>/dev/null'
Esempio n. 5
0
	def create_command_file(self, expect, send):
		"""Internal function. Do not use.

		Takes a long command, and puts it in an executable file ready to run. Returns the filename.
		"""
		cfg = shutit_global.shutit.cfg
		random_id = shutit_util.random_id()
		fname = cfg['build']['shutit_state_dir_base'] + '/tmp_' + random_id
		working_str = send
		self.sendline(' truncate --size 0 '+ fname)
		self.pexpect_child.expect(expect)
		size = cfg['build']['stty_cols'] - 25
		while len(working_str) > 0:
			curr_str = working_str[:size]
			working_str = working_str[size:]
			self.sendline(' ' + shutit_util.get_command('head') + ''' -c -1 >> ''' + fname + """ << 'END_""" + random_id + """'\n""" + curr_str + """\nEND_""" + random_id)
			self.expect(expect)
		self.sendline(' chmod +x ' + fname)
		self.expect(expect)
		return fname
Esempio n. 6
0
	def __init__(self,
	             sendspec,
	             shutit_obj):
		# Stub this with a simple command for now
		self.sendspec               = sendspec
		self.block_other_commands   = sendspec.block_other_commands
		self.retry                  = sendspec.retry
		self.tries                  = 0
		self.pid                    = None
		self.return_value           = None
		self.start_time             = None
		self.run_state              = 'N' # State as per ps man page, but 'C' == Complete, 'N' == not started, 'F' == failed, 'S' == sleeping/running, 'T' == timed out by ShutIt
		self.cwd                    = self.sendspec.shutit_pexpect_child.send_and_get_output(' command pwd', ignore_background=True)
		self.id                     = shutit_util.random_id()
		self.output_file            = '/tmp/shutit_background_' + self.id + '_output.log'
		self.exit_code_file         = '/tmp/shutit_background_' + self.id + '_exit_code_file.log'
		self.command_file           = '/tmp/shutit_background_' + self.id + '_command.log'
		if self.sendspec.run_in_background:
			# TODO: consider separating out into a simple send for the part that creates the command file, the cd and the output file. Perhaps send file first and run that in the background?
			self.sendspec.send          = ' set +m && { : $(echo "' + self.sendspec.original_send + '" >' + self.command_file + ' && command cd "' + self.cwd + '">' + self.output_file + ' && ' + self.sendspec.send + ' >>' + self.output_file + ' 2>&1; echo $? >' + self.exit_code_file + ') & } 2>/dev/null'
		self.shutit_obj             = shutit_obj
Esempio n. 7
0
    def __init__(self, prefix):
        """Represents a new 'environment' in ShutIt, which corresponds to a host or any
		machine-like location (eg docker container, ssh'd to host, or even a chroot jail
		with a /tmp folder that has not been touched by shutit.
		"""
        if prefix == 'ORIGIN_ENV':
            self.environment_id = prefix
        else:
            self.environment_id = shutit_util.random_id()
        self.module_root_dir = '/'
        self.modules_installed = []  # has been installed in this build
        self.modules_not_installed = []  # modules _known_ not to be installed
        self.modules_ready = [
        ]  # has been checked for readiness and is ready (in this build)
        self.modules_recorded = []
        self.modules_recorded_cache_valid = False
        self.install_type = ''
        self.distro = ''
        self.distro_version = ''
        self.users = dict()
        self.build = {}
        self.build['apt_update_done'] = False
        self.build['emerge_update_done'] = False
        self.build['apk_update_done'] = False
	def __init__(self,
	             prefix):
		"""Represents a new 'environment' in ShutIt, which corresponds to a host or any
		machine-like location (eg docker container, ssh'd to host, or even a chroot jail
		with a /tmp folder that has not been touched by shutit.
		"""
		if prefix == 'ORIGIN_ENV':
			self.environment_id = prefix
		else:
			self.environment_id = shutit_util.random_id()
		self.module_root_dir              = '/'
		self.modules_installed            = [] # has been installed in this build
		self.modules_not_installed        = [] # modules _known_ not to be installed
		self.modules_ready                = [] # has been checked for readiness and is ready (in this build)
		self.modules_recorded             = []
		self.modules_recorded_cache_valid = False
		self.install_type                 = ''
		self.distro                       = ''
		self.distro_version               = ''
		self.users                        = dict()
		self.build                        = {}
		self.build['apt_update_done']     = False
		self.build['emerge_update_done']  = False
		self.build['apk_update_done']     = False
Esempio n. 9
0
	def setup_environment(self,
	                      prefix,
	                      delaybeforesend=0,
	                      loglevel=logging.DEBUG):
		"""If we are in a new environment then set up a new data structure.
		A new environment is a new machine environment, whether that's
		over ssh, docker, whatever.
		If we are not in a new environment ensure the env_id is correct.
		Returns the environment id every time.
		"""
		# Set this to be the default session.
		shutit_global.shutit.set_default_shutit_pexpect_session(self)
		cfg = shutit_global.shutit.cfg
		environment_id_dir = cfg['build']['shutit_state_dir'] + '/environment_id'
		if shutit_global.shutit.file_exists(environment_id_dir,directory=True):
			files = shutit_global.shutit.ls(environment_id_dir)
			if len(files) != 1 or type(files) != list:
				if len(files) == 2 and (files[0] == 'ORIGIN_ENV' or files[1] == 'ORIGIN_ENV'):
					for f in files:
						if f != 'ORIGIN_ENV':
							environment_id = f
							cfg['build']['current_environment_id'] = environment_id
							# Workaround for CygWin terminal issues. If the envid isn't in the cfg item
							# Then crudely assume it is. This will drop through and then assume we are in the origin env.
							try:
								_=cfg['environment'][cfg['build']['current_environment_id']]
							except Exception:
								cfg['build']['current_environment_id'] = 'ORIGIN_ENV'
							break
				else:
					# See comment above re: cygwin.
					if shutit_global.shutit.file_exists('/cygdrive'):
						cfg['build']['current_environment_id'] = 'ORIGIN_ENV'
					else:
						shutit_global.shutit.fail('Wrong number of files in environment_id_dir: ' + environment_id_dir)
			else:
				if shutit_global.shutit.file_exists('/cygdrive'):
					environment_id = 'ORIGIN_ENV'
				else:
					environment_id = files[0]
			if cfg['build']['current_environment_id'] != environment_id:
				# Clean out any trace of this new environment, and return the already-existing one.
				shutit_global.shutit.send(' rm -rf ' + environment_id_dir + '/environment_id/' + environment_id, echo=False, loglevel=loglevel, delaybeforesend=delaybeforesend)
				return cfg['build']['current_environment_id']
			if not environment_id == 'ORIGIN_ENV':
				return environment_id
		# Origin environment is a special case.
		if prefix == 'ORIGIN_ENV':
			environment_id = prefix
		else:
			environment_id = shutit_util.random_id()
		cfg['build']['current_environment_id']                             = environment_id
		cfg['environment'][environment_id] = {}
		# Directory to revert to when delivering in bash and reversion to directory required.
		cfg['environment'][environment_id]['module_root_dir']              = '/'
		cfg['environment'][environment_id]['modules_installed']            = [] # has been installed (in this build)
		cfg['environment'][environment_id]['modules_not_installed']        = [] # modules _known_ not to be installed
		cfg['environment'][environment_id]['modules_ready']                = [] # has been checked for readiness and is ready (in this build)
		# Installed file info
		cfg['environment'][environment_id]['modules_recorded']             = []
		cfg['environment'][environment_id]['modules_recorded_cache_valid'] = False
		cfg['environment'][environment_id]['setup']                        = False
		# Exempt the ORIGIN_ENV from getting distro info
		if prefix != 'ORIGIN_ENV':
			shutit_global.shutit.get_distro_info(environment_id)
		fname = environment_id_dir + '/' + environment_id
		shutit_global.shutit.send(' mkdir -p ' + environment_id_dir + ' && chmod -R 777 ' + cfg['build']['shutit_state_dir_base'] + ' && touch ' + fname, echo=False, loglevel=loglevel, delaybeforesend=delaybeforesend)
		cfg['environment'][environment_id]['setup']                        = True
		return environment_id
Esempio n. 10
0
	def login(self,
			  user='******',
			  command='su -',
			  password=None,
			  prompt_prefix=None,
			  expect=None,
			  timeout=180,
			  escape=False,
			  note=None,
			  go_home=True,
			  delaybeforesend=0.05,
			  loglevel=logging.DEBUG):
		"""Logs the user in with the passed-in password and command.
		Tracks the login. If used, used logout to log out again.
		Assumes you are root when logging in, so no password required.
		If not, override the default command for multi-level logins.
		If passwords are required, see setup_prompt() and revert_prompt()

		@param user:          User to login with. Default: root
		@param command:       Command to login with. Default: "su -"
		@param escape:        See send(). We default to true here in case
		                      matches an expect we add.
		@param password:      Password.
		@param prompt_prefix: Prefix to use in prompt setup.
		@param expect:        See send()
		@param timeout:		  How long to wait for a response. Default: 20.
		@param note:          See send()
		@param go_home:       Whether to automatically cd to home.

		@type user:           string
		@type command:        string
		@type password:       string
		@type prompt_prefix:  string
		@type timeout:        integer
		"""
		# We don't get the default expect here, as it's either passed in, or a base default regexp.
		r_id = shutit_util.random_id()
		if prompt_prefix == None:
			prompt_prefix = r_id
		cfg = shutit_global.shutit.cfg
		# Be helpful.
		if ' ' in user:
			shutit_global.shutit.fail('user has space in it - did you mean: login(command="' + user + '")?')
		if cfg['build']['delivery'] == 'bash' and command == 'su -':
			# We want to retain the current working directory
			command = 'su'
		if command == 'su -' or command == 'su' or command == 'login':
			send = command + ' ' + user
		else:
			send = command
		if expect == None:
			login_expect = cfg['expect_prompts']['base_prompt']
		else:
			login_expect = expect
		# We don't fail on empty before as many login programs mess with the output.
		# In this special case of login we expect either the prompt, or 'user@' as this has been seen to work.
		general_expect = [login_expect]
		# Add in a match if we see user+ and then the login matches. Be careful not to match against '[email protected]:'******'@.*'+'[@#$]']
		# If not an ssh login, then we can match against user + @sign because it won't clash with 'user@adasdas password:'******'ssh') == 0:
			general_expect = general_expect + [user+'@']
			general_expect = general_expect + ['.*[@#$]']
		if user == 'bash' and command == 'su -':
			shutit_global.shutit.log('WARNING! user is bash - if you see problems below, did you mean: login(command="' + user + '")?',level=loglevel.WARNING)
		shutit_global.shutit._handle_note(note,command=command + ', as user: "******"',training_input=send)
		# r'[^t] login:'******'last login:'******'ontinue connecting':'yes','assword':password,r'[^t] login:'******'cd',shutit_pexpect_child=self.pexpect_child,check_exit=False, echo=False, loglevel=loglevel, delaybeforesend=delaybeforesend)
		self.login_stack_append(r_id)
		shutit_global.shutit._handle_note_after(note=note)
Esempio n. 11
0
def create_session(docker_image=None,
                   docker_rm=None,
                   echo=False,
                   loglevel='WARNING',
                   nocolor=False,
                   session_type='bash',
                   vagrant_session_name=None,
                   vagrant_image='ubuntu/xenial64',
                   vagrant_gui=False,
                   vagrant_memory='1024',
                   vagrant_num_machines='1',
                   vagrant_provider='virtualbox',
                   vagrant_root_folder=None,
                   vagrant_swapsize='2G',
                   vagrant_version='1.8.6',
                   vagrant_virt_method='virtualbox',
                   vagrant_cpu='1',
                   video=-1,
                   walkthrough=False):
	"""Creates a distinct ShutIt session. Sessions can be of type:

	bash    - a bash shell is spawned and
	vagrant - a Vagrantfile is created and 'vagrant up'ped
	"""
	assert session_type in ('bash','docker','vagrant'), shutit_util.print_debug()
	shutit_global_object = shutit_global.shutit_global_object
	if video != -1 and video > 0:
		walkthrough = True
	if session_type in ('bash','docker'):
		return shutit_global_object.create_session(session_type,
		                                           docker_image=docker_image,
		                                           rm=docker_rm,
		                                           echo=echo,
		                                           walkthrough=walkthrough,
		                                           walkthrough_wait=video,
		                                           nocolor=nocolor,
		                                           loglevel=loglevel)
	elif session_type == 'vagrant':
		if vagrant_session_name is None:
			vagrant_session_name = 'shutit' + shutit_util.random_id()
		if isinstance(vagrant_num_machines, int):
			vagrant_num_machines = str(vagrant_num_machines)
		assert isinstance(vagrant_num_machines, str)
		assert isinstance(int(vagrant_num_machines), int)
		if vagrant_root_folder is None:
			vagrant_root_folder = shutit_global.shutit_global_object.owd
		return create_session_vagrant(vagrant_session_name,
		                              vagrant_num_machines,
		                              vagrant_image,
		                              vagrant_provider,
		                              vagrant_gui,
		                              vagrant_memory,
		                              vagrant_swapsize,
		                              echo,
		                              walkthrough,
		                              nocolor,
		                              video,
		                              vagrant_version,
		                              vagrant_virt_method,
		                              vagrant_root_folder,
		                              vagrant_cpu,
		                              loglevel)