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)
def run_background_command(self): # reset object self.pid = None self.return_value = None self.run_state = 'N' self.start_time = time.time() # record start time # run command self.tries += 1 if self.sendspec.run_in_background: ## Required to reset terminal before a background send. (TODO: why?) #self.sendspec.shutit_pexpect_child.reset_terminal() # Run in the background self.sendspec.shutit_pexpect_child.quick_send(self.sendspec.send,loglevel=logging.DEBUG) # Put into an 'S' state as that means 'running' self.run_state = 'S' # Required to reset terminal after a background send. (TODO: why?) self.sendspec.shutit_pexpect_child.reset_terminal() # record pid self.pid = self.sendspec.shutit_pexpect_child.send_and_get_output(" echo ${!}",ignore_background=True) else: # Run synchronously and mark complete # We need to set this to ignore background before we run it, so that # it does not block itself and end up in an infinite loop. self.sendspec.ignore_background = True self.sendspec.shutit_pexpect_child.send(self.sendspec) self.run_state = 'C' self.sendspec.started = True assert self.run_state in ('C','S','F'), shutit_util.print_debug() return True
def __new__(mcs, name, bases, local): """Checks this is a ShutItModule, and wraps any ShutItModule methods that have been overridden in the subclass. """ # Don't wrap methods of the ShutItModule class, only subclasses if name != 'ShutItModule': sim = mcs.ShutItModule assert sim is not None, shutit_util.print_debug() # Wrap any of the ShutItModule (self, shutit) methods that have been # overridden in a subclass for fname, method in iteritems(local): if not hasattr(sim, fname): continue if not callable(method): continue sim_method = getattr(sim, fname) if sim_method is method: # pragma: no cover continue args = inspect.getargspec(sim_method)[0] if args != ['self', 'shutit']: continue local[fname] = shutit_method_scope(method) cls = super(ShutItMeta, mcs).__new__(mcs, name, bases, local) if name == 'ShutItModule': mcs.ShutItModule = cls return cls
def finalize(self, shutit): """Finalizes the target, exiting for us back to the original shell and performing any repository work required. """ # Finish with the target target_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id( 'target_child') assert not target_child_pexpect_session.sendline( ShutItSendSpec(target_child_pexpect_session, 'exit', ignore_background=True)), shutit_util.print_debug() host_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id( 'host_child') host_child = host_child_pexpect_session.pexpect_child shutit.set_default_shutit_pexpect_session(host_child_pexpect_session) shutit.set_default_shutit_pexpect_session_expect( shutit.expect_prompts['ORIGIN_ENV']) shutit.do_repository_work( shutit.repository['name'], docker_executable=shutit.host['docker_executable'], password=shutit.host['password']) # Final exits host_child.sendline( 'rm -f ' + shutit.build['cidfile']) # Ignore response, just send. host_child.sendline( 'exit') # Exit raw bash. Ignore response, just send. return True
def main(): """Main ShutIt function. Handles the configured actions: - skeleton - create skeleton module - list_configs - output computed configuration - depgraph - output digraph of module dependencies """ # Create base shutit object. shutit = shutit_global.shutit_global_object.shutit_objects[0] if sys.version_info[0] == 2: if sys.version_info[1] < 7: shutit.fail('Python version must be 2.7+') # pragma: no cover try: shutit.setup_shutit_obj() except KeyboardInterrupt: shutit_util.print_debug(sys.exc_info()) shutit_global.shutit_global_object.shutit_print('Keyboard interrupt caught, exiting with status 1') sys.exit(1)
def finalize(self, shutit): """Finalizes the target, exiting for us back to the original shell and performing any repository work required. """ # Finish with the target target_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id( 'target_child') assert not target_child_pexpect_session.sendline( ShutItSendSpec(target_child_pexpect_session, 'exit', ignore_background=True)), shutit_util.print_debug() return True
def create_session(session_type='bash', docker_image=None, rm=None, echo=False, walkthrough=False, nocolor=False, video=-1, loglevel='WARNING'): assert session_type in ('bash', 'docker'), shutit_util.print_debug() shutit_global_object = shutit_global.shutit_global_object if video != -1 and video > 0: walkthrough = True return shutit_global_object.create_session(session_type, docker_image=docker_image, rm=rm, echo=echo, walkthrough=walkthrough, walkthrough_wait=video, nocolor=nocolor, loglevel=loglevel)
def check_background_command_state(self): self.shutit_obj.log('CHECKING background task: ' + self.sendspec.send + ', id: ' + self.id,level=logging.DEBUG) assert self.start_time is not None, shutit_util.print_debug() # Check the command has been started if not self.sendspec.started: assert self.run_state == 'N', shutit_util.print_debug() return self.run_state if self.run_state in ('C','F'): assert self.sendspec.started, shutit_util.print_debug() return self.run_state try: assert self.run_state in ('S',), shutit_util.print_debug(msg='State should be in S, is in fact: ' + self.run_state) except AssertionError: _, _, tb = sys.exc_info() traceback.print_tb(tb) # Fixed format tb_info = traceback.extract_tb(tb) _, line, _, text = tb_info[-1] shutit_global.shutit_global_object.shutit_print('An error occurred on line {} in statement {}'.format(line, text)) # Update the run state. updated_run_state = self.sendspec.shutit_pexpect_child.send_and_get_output(""" command ps -o stat """ + self.pid + """ | command sed '1d' """, ignore_background=True) # Ensure we get the first character only, if one exists. if len(updated_run_state) > 0: # Task is unfinished. self.run_state = updated_run_state[0] updated_run_state = None # state The state is given by a sequence of characters, for example, ``RWNA''. The first character indicates the run state of the process: # I Marks a process that is idle (sleeping for longer than about 20 seconds). # R Marks a runnable process. # S Marks a process that is sleeping for less than about 20 seconds. # T Marks a stopped process. # U Marks a process in uninterruptible wait. # Z Marks a dead process (a ``zombie''). if self.run_state in ('I','R','T','U','Z'): self.shutit_obj.log('background task run state: ' + self.run_state, level=logging.DEBUG) self.run_state = 'S' try: assert self.run_state in ('S',), shutit_util.print_debug(msg='State should be in S having gleaned from ps, is in fact: ' + self.run_state) except AssertionError: _, _, tb = sys.exc_info() traceback.print_tb(tb) # Fixed format tb_info = traceback.extract_tb(tb) _, line, _, text = tb_info[-1] shutit_global.shutit_global_object.shutit_print('An error occurred on line {} in statement {}'.format(line, text)) shutit_global.shutit_global_object.shutit_print(self) # honour sendspec.timeout if self.sendspec.timeout is not None: current_time = time.time() time_taken = current_time - self.start_time if time_taken > self.sendspec.timeout: # We've timed out, kill with prejudice. self.sendspec.shutit_pexpect_child.quick_send(' kill -9 ' + self.pid,loglevel=logging.DEBUG) self.run_state = 'T' assert self.run_state in ('S','T'), shutit_util.print_debug() return self.run_state else: # Task is finished. self.run_state = 'C' self.shutit_obj.log('background task: ' + self.sendspec.send + ', id: ' + self.id + ' complete',level=logging.DEBUG) # Stop this from blocking other commands from here. assert self.return_value is None, shutit_util.print_debug(msg='check_background_command_state called with self.return_value already set?' + str(self)) self.sendspec.shutit_pexpect_child.quick_send(' wait ' + self.pid,loglevel=logging.DEBUG) # Get the exit code. self.return_value = self.sendspec.shutit_pexpect_child.send_and_get_output(' cat ' + self.exit_code_file, ignore_background=True) # If the return value is deemed a failure: if self.return_value not in self.sendspec.exit_values: self.shutit_obj.log('background task: ' + self.sendspec.send + ' failed with exit code: ' + self.return_value, level=logging.DEBUG) self.shutit_obj.log('background task: ' + self.sendspec.send + ' failed with output: ' + self.sendspec.shutit_pexpect_child.send_and_get_output(' cat ' + self.output_file, ignore_background=True), level=logging.DEBUG) if self.retry > 0: self.shutit_obj.log('background task: ' + self.sendspec.send + ' retrying',level=logging.DEBUG) self.retry -= 1 self.run_background_command() # recurse return self.check_background_command_state() else: self.shutit_obj.log('background task final failure: ' + self.sendspec.send + ' failed with exit code: ' + self.return_value, level=logging.DEBUG) self.run_state = 'F' assert self.run_state in ('C','F'), shutit_util.print_debug() return self.run_state else: # Task succeeded. self.shutit_obj.log('background task: ' + self.sendspec.send + ' succeeded with exit code: ' + self.return_value, level=logging.DEBUG) assert self.run_state in ('C',), shutit_util.print_debug() return self.run_state # Should never get here. assert False, shutit_util.print_debug()
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)
def finalize(self, shutit): """Finalizes the target, exiting for us back to the original shell and performing any repository work required. """ # Finish with the target target_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id('target_child') assert not target_child_pexpect_session.sendline(ShutItSendSpec(target_child_pexpect_session,'exit',ignore_background=True)), shutit_util.print_debug() host_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id('host_child') host_child = host_child_pexpect_session.pexpect_child shutit.set_default_shutit_pexpect_session(host_child_pexpect_session) shutit.set_default_shutit_pexpect_session_expect(shutit.expect_prompts['ORIGIN_ENV']) shutit.do_repository_work(shutit.repository['name'], docker_executable=shutit.host['docker_executable'], password=shutit.host['password']) # Final exits host_child.sendline('rm -f ' + shutit.build['cidfile']) # Ignore response, just send. host_child.sendline('exit') # Exit raw bash. Ignore response, just send. return True
def finalize(self, shutit): """Finalizes the target, exiting for us back to the original shell and performing any repository work required. """ # Finish with the target target_child_pexpect_session = shutit.get_shutit_pexpect_session_from_id('target_child') assert not target_child_pexpect_session.sendline(ShutItSendSpec(target_child_pexpect_session,'exit',ignore_background=True)), shutit_util.print_debug() return True