def process(args): verbose(f"Run script '{args.script}'") if args.script == 'all': script = get_value_with_default( ['scripts', 'all'], ['fetch --force', 'init --rebuild-conf', 'build']) else: script = get_value_with_default(['scripts', args.script]) if script == None or not isinstance(script, list): print(f"Script '{args.script}' not found") sys.exit(1) for step in script: command = _compose_command_prefix(args) command.extend(shlex.split(potentially_replace_by_var(step))) verbose(f"Run step {' '.join(command)}") if dryrun(): print(f"dry: {' '.join(command)}") else: try: proc = subprocess.Popen(command, check=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) while proc.returncode is None: # handle output by direct access to stdout and stderr for line in process.stdout: print(line) # set returncode if the process has exited process.poll() except subprocess.CalledProcessError as err: print(f"Error in processing step {err}") sys.exit(1) verbose(f"Script '{args.script}' successfully finished")
def run_interactive_build_command(self, command): verbose(f"Docker host - run interactive command '{command}'") if dryrun(): print(f"dry: (interactive-in-container) {command}") else: try: socket = self.container.exec_run( cmd=command, tty=True, stdin=True, socket=True, demux=False, workdir=self.config.project_dir_container) socket.output._sock.send(b'export PSADD="(c*r)"\n') while True: r, w, e = select.select([sys.stdin, socket.output._sock], [], [sys.stdin, socket.output._sock]) if sys.stdin in r: d = os.read(sys.stdin.fileno(), 10240) socket.output._sock.send(d) elif socket.output._sock in r: data = socket.output._sock.recv(16384) os.write(sys.stdout.fileno(), data) if sys.stdin in e or socket.output._sock in e: break # leave the loop except Exception as err: verbose(f"Exception: {err}")
def start_container(self): if dryrun(): print(f"dry: Start container: {self.container_name}") else: verbose(f"Docker container status: {self.container.status}") if self.container.status != "running": verbose(f"Start docker container") self.container.start()
def build_privatized_docker_image(self): if dryrun(): print(f"dry: Build or get privatized docker image: " \ f"{self.config.privatized_image}") else: try: image_label = self.config.privatized_image + ":latest" image = self.docker.images.get(image_label) verbose(f"Privatized image {image_label} exists" \ " - no need to build") except docker.errors.ImageNotFound as _err: self._build_privatized_docker_image()
def _build_privatized_docker_image(self): verbose("Build privatized docker image") privatized_docker_image = self.config.get_privatized_image() yocto_docker_image = self.config.get_image() dir = create_dir_and_dockerfile(yocto_docker_image, self.yocto_user_home) if dryrun(): with open(os.path.join(dir, "Dockerfile"), "r") as f: print("dry: privatizing Dockerfile" + f.read()) run_cmd(["docker", "build", "-t", privatized_docker_image, dir]) os.remove(os.path.join(dir, "Dockerfile")) # cleanup Dockerfile os.rmdir(dir) # cleanup temporary directory
def run_context(self, command): if dryrun(): print(f"dry - Run build command: {command}") else: try: self.process = subprocess.Popen( "bash", stdin=subprocess.PIPE, stderr=subprocess.STDOUT, ) verbose(f"Start Bash session: Pid {self.process.pid}") self.inject_command(command) self.process.communicate() except subprocess.SubprocessError: pass verbose(f"Stop bash session: Pid {self.process.pid}")
def create_container(self): containers = self.docker.containers.list( all=True, filters={"name": self.container_name}) if len(containers) == 1: verbose(f"Container already exists, reusing ...") self.container = containers[0] return verbose("Create docker container") if dryrun(): print(f"dry: Build container: {self.container_name}") else: volumes = { os.getcwd(): { "mode": "rw", "bind": self.config.project_dir_container, }, abs_path(self.config.cache_dir_host): { "mode": "rw", "bind": self.config.cache_dir_container, }, } local_ssh_dir = os.path.join(Path.home(), ".ssh") if os.path.isdir(local_ssh_dir): # only if host (local) user has ssh configured inject volumes[local_ssh_dir] = { "mode": "ro", "bind": os.path.join(self.yocto_user_home, ".ssh"), } if self.config.publish_dir_host != "" and os.path.isdir( self.config.publish_dir_host): # only if host (local) is configured and exists configure volumes[abs_path(self.config.publish_dir_host)] = { "mode": "rw", "bind": self.config.publish_dir_container, } self.container = self.docker.containers.create( detach=True, # Inject an infinite loop command command="bash -c 'while true; do sleep 1; done'", user=os.getuid(), read_only=False, # otherwise /tmp is not writeable name=self.container_name, image=self.config.privatized_image, volumes=volumes, ) verbose(f"Docker container created: {self.container}")
def handle(self): """ Update site.conf if overwrite and file available Create site.conf if source file available """ dest_config_dir = os.path.join(os.getcwd(), self.build_dir, "conf") dest_site_conf_file = os.path.join(dest_config_dir, "site.conf") if not os.path.isfile(dest_site_conf_file): # site.conf file does not exit (Create scenario) src_site_conf_file = os.path.join(os.getcwd(), self.sitefile) if os.path.isfile(src_site_conf_file): verbose(f"Create site.conf from: {src_site_conf_file}") if dryrun(): print( f"copy {src_site_conf_file} to {dest_site_conf_file}") else: os.makedirs(dest_config_dir, exist_ok=True) copyfile(src_site_conf_file, dest_site_conf_file)
def run_batch_command(self, command): if isinstance(command, list): cmd_fmt = ' '.join(command) else: cmd_fmt = command verbose(f"Docker host - run batch command '{cmd_fmt}'") if dryrun(): print(f"dry: (batch-in-container) {cmd_fmt}") else: socket = self.container.exec_run( cmd=command, stream=True, demux=True, workdir=self.config.project_dir_container) for (stdout, stderr) in socket.output: if stdout: sys.stdout.buffer.write(b'... ') sys.stdout.buffer.write(stdout) if stderr: sys.stderr.buffer.write(b'+++ ') sys.stderr.buffer.write(stderr)
def remove_container(self): if dryrun(): print(f"dry: Remove container: {self.container_name}") else: self.container.remove(force=True) # force for just to be sure
def stop_container(self): if dryrun(): print(f"dry: Stop container: {self.container_name}") else: verbose(f"Docker stop container") self.container.stop()