def shell(args): config = _load_config() common.env = config.stage_env() userCommand = args.userCommand if not userCommand: userCommand = ["/usr/bin/env", "PS1=\[\e[1;32m\]snapcraft:\w\$\[\e[0m\] ", "/bin/bash", "--norc"] common.run(userCommand)
def _wrap_exe(relexepath, args=None): snap_dir = common.get_snapdir() exepath = os.path.join(snap_dir, relexepath) wrappath = exepath + ".wrapper" shebang = None # TODO talk to original author if the exception to be captured here is # FileNotFoundError, the original code was a general catch all try: os.remove(wrappath) except FileNotFoundError: pass wrapexec = "$SNAP_APP_PATH/{}".format(relexepath) if not os.path.exists(exepath) and "/" not in relexepath: # If it doesn't exist it might be in the path logger.debug('Checking to see if "{}" is in the $PATH'.format(relexepath)) with tempfile.NamedTemporaryFile("w+") as tempf: script = "#!/bin/sh\n" + "{}\n".format(common.assemble_env()) + 'which "{}"\n'.format(relexepath) tempf.write(script) tempf.flush() common.run(["/bin/sh", tempf.name], cwd=snap_dir) wrapexec = relexepath else: with open(exepath, "rb") as exefile: # If the file has a she-bang, the path might be pointing to # the local 'parts' dir. Extract it so that _write_wrap_exe # will have a chance to rewrite it. if exefile.read(2) == b"#!": shebang = exefile.readline().strip().decode("utf-8") _write_wrap_exe(wrapexec, wrappath, shebang=shebang, args=args) return os.path.relpath(wrappath, snap_dir)
def _wrap_exe(relexepath): snap_dir = common.get_snapdir() exepath = os.path.join(snap_dir, relexepath) wrappath = exepath + '.wrapper' # TODO talk to original author if the exception to be captured here is # FileNotFoundError, the original code was a general catch all try: os.remove(wrappath) except FileNotFoundError: pass wrapexec = '$SNAP_APP_PATH/{}'.format(relexepath) if not os.path.exists(exepath) and '/' not in relexepath: # If it doesn't exist it might be in the path logger.debug('Checking to see if "{}" is in the $PATH'.format( relexepath)) with tempfile.NamedTemporaryFile('w+') as tempf: script = ('#!/bin/sh\n' + '{}\n'.format(common.assemble_env()) + 'which "{}"\n'.format(relexepath)) tempf.write(script) tempf.flush() common.run(['/bin/sh', tempf.name], cwd=snap_dir) wrapexec = relexepath _write_wrap_exe(wrapexec, wrappath) return os.path.relpath(wrappath, snap_dir)
def _wrap_exe(relexepath): snap_dir = common.get_snapdir() exepath = os.path.join(snap_dir, relexepath) wrappath = exepath + '.wrapper' # TODO talk to original author if the exception to be captured here is # FileNotFoundError, the original code was a general catch all try: os.remove(wrappath) except FileNotFoundError: pass wrapexec = '$SNAP_APP_PATH/{}'.format(relexepath) if not os.path.exists(exepath) and '/' not in relexepath: # If it doesn't exist it might be in the path logger.debug( 'Checking to see if "{}" is in the $PATH'.format(relexepath)) with tempfile.NamedTemporaryFile('w+') as tempf: script = ('#!/bin/sh\n' + '{}\n'.format(common.assemble_env()) + 'which "{}"\n'.format(relexepath)) tempf.write(script) tempf.flush() common.run(['/bin/sh', tempf.name], cwd=snap_dir) wrapexec = relexepath _write_wrap_exe(wrapexec, wrappath) return os.path.relpath(wrappath, snap_dir)
def shell(args): config = _load_config() common.env = config.stage_env() userCommand = args.userCommand if not userCommand: userCommand = ['/usr/bin/env', 'PS1=\[\e[1;32m\]snapcraft:\w\$\[\e[0m\] ', '/bin/bash', '--norc'] common.run(userCommand)
def _fix_xml_tools(root): xml2_config_path = os.path.join(root, 'usr', 'bin', 'xml2-config') if os.path.isfile(xml2_config_path): common.run( ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. format(root), xml2_config_path]) xslt_config_path = os.path.join(root, 'usr', 'bin', 'xslt-config') if os.path.isfile(xslt_config_path): common.run( ['sed', '-i', '-e', 's|prefix=/usr|prefix={}/usr|'. format(root), xslt_config_path])
def _find_bin(binary, basedir): # If it doesn't exist it might be in the path logger.debug('Checking that {!r} is in the $PATH'.format(binary)) script = ('#!/bin/sh\n' + '{}\n'.format(common.assemble_env()) + 'which "{}"\n'.format(binary)) with tempfile.NamedTemporaryFile('w+') as tempf: tempf.write(script) tempf.flush() try: common.run(['/bin/sh', tempf.name], cwd=basedir, stdout=subprocess.DEVNULL) except subprocess.CalledProcessError: raise CommandError(binary)
def run(self, cmd, cwd=None, **kwargs): if cwd is None: cwd = self.builddir if True: print(" ".join(cmd)) os.makedirs(cwd, exist_ok=True) return common.run(cmd, cwd=cwd, **kwargs)
def run(self, cmd, cwd=None, **kwargs): if cwd is None: cwd = self.builddir if True: print(' '.join(cmd)) os.makedirs(cwd, exist_ok=True) return common.run(cmd, cwd=cwd, **kwargs)
def _wrap_exe(command, basename=None): execparts = shlex.split(command) snap_dir = common.get_snapdir() exepath = os.path.join(snap_dir, execparts[0]) if basename: wrappath = os.path.join(snap_dir, basename) + '.wrapper' else: wrappath = exepath + '.wrapper' shebang = None if os.path.exists(wrappath): os.remove(wrappath) wrapexec = '$SNAP/{}'.format(execparts[0]) if not os.path.exists(exepath) and '/' not in execparts[0]: # If it doesn't exist it might be in the path logger.debug('Checking to see if {!r} is in the $PATH'.format( execparts[0])) with tempfile.NamedTemporaryFile('w+') as tempf: script = ('#!/bin/sh\n' + '{}\n'.format(common.assemble_env()) + 'which "{}"\n'.format(execparts[0])) tempf.write(script) tempf.flush() common.run(['/bin/sh', tempf.name], cwd=snap_dir) wrapexec = execparts[0] else: with open(exepath, 'rb') as exefile: # If the file has a she-bang, the path might be pointing to # the local 'parts' dir. Extract it so that _write_wrap_exe # will have a chance to rewrite it. if exefile.read(2) == b'#!': shebang = exefile.readline().strip().decode('utf-8') _write_wrap_exe(wrapexec, wrappath, shebang=shebang, args=execparts[1:]) return os.path.relpath(wrappath, snap_dir)
def _wrap_exe(relexepath, args=None): snap_dir = common.get_snapdir() exepath = os.path.join(snap_dir, relexepath) wrappath = exepath + '.wrapper' shebang = None # TODO talk to original author if the exception to be captured here is # FileNotFoundError, the original code was a general catch all try: os.remove(wrappath) except FileNotFoundError: pass wrapexec = '$SNAP_APP_PATH/{}'.format(relexepath) if not os.path.exists(exepath) and '/' not in relexepath: # If it doesn't exist it might be in the path logger.debug( 'Checking to see if "{}" is in the $PATH'.format(relexepath)) with tempfile.NamedTemporaryFile('w+') as tempf: script = ('#!/bin/sh\n' + '{}\n'.format(common.assemble_env()) + 'which "{}"\n'.format(relexepath)) tempf.write(script) tempf.flush() common.run(['/bin/sh', tempf.name], cwd=snap_dir) wrapexec = relexepath else: with open(exepath, 'rb') as exefile: # If the file has a she-bang, the path might be pointing to # the local 'parts' dir. Extract it so that _write_wrap_exe # will have a chance to rewrite it. if exefile.read(2) == b'#!': shebang = exefile.readline().strip().decode('utf-8') _write_wrap_exe(wrapexec, wrappath, shebang=shebang, args=args) return os.path.relpath(wrappath, snap_dir)
def assemble(args): args.cmd = 'snap' # With all the data in snapcraft.yaml, maybe it's not a good idea to call # snap(args) and just do a snappy build if assemble was explicitly called. snap(args) common.run(['snappy', 'build', common.get_snapdir()])
def run(args): # We are mostly making sure we are operating from the correct location. In # the future this could do more by using target attribute in snapcraft.yaml # to create the correct target image. _load_config() # Find the ssh key that ubuntu-device-flash would use so that we can use it # ourselves as well. This may not be the default key that the user has # configured. # See: https://bugs.launchpad.net/snapcraft/+bug/1486659 try: ssh_key = _find_latest_private_key() except LookupError: logger.error('You need to have an SSH key to use this command') logger.error('Please generate one with ssh-keygen(1)') return 1 else: logger.info('Using the following ssh key: %s', ssh_key) # Find available *.snap files to copy into the test VM snap_dir = os.path.join(os.getcwd()) # copy the snap with the largest version number into the test VM snaps = glob.glob(snap_dir + '/*.snap') snaps.sort() if not snaps: logger.error('There are no .snap files ready') logger.error('Perhaps you forgot to run "snapcraft assemble"') return 1 qemudir = os.path.join(os.getcwd(), 'image') qemu_img = os.path.join(qemudir, '15.04.img') if not os.path.exists(qemu_img): os.makedirs(qemudir, exist_ok=True) logger.info( 'Setting up virtual snappy environment, root access required') common.run([ 'sudo', 'ubuntu-device-flash', 'core', '15.04', '--developer-mode', '--enable-ssh', '-o', os.path.relpath(qemu_img, qemudir)], cwd=qemudir) qemu = None try: # Allow the developer to provide additional arguments to qemu. This # can be used, for example, to pass through USB devices from the host. # This can enable a lot of hardware-specific use cases directly inside # the snapcraft run workflow. # # For example: # $ export SNAPCRAFT_RUN_QEMU_ARGS=\ # "-usb -device usb-host,hostbus=1,hostaddr=10" # $ snapcraft run qemu_args = os.getenv('SNAPCRAFT_RUN_QEMU_ARGS') if qemu_args is not None: qemu_args = shlex.split(qemu_args) else: qemu_args = [] qemu = subprocess.Popen( ['kvm', '-m', '768', '-nographic', '-snapshot', '-redir', 'tcp:8022::22', qemu_img] + qemu_args, stdin=subprocess.PIPE) n = tempfile.NamedTemporaryFile() ssh_opts = [ # We want to login with the specified ssh identity (key) '-i', ssh_key, # We don't want strict host checking because it's a new VM with a # random key each time. '-oStrictHostKeyChecking=no', # We don't want to pollute the known_hosts file with new entries # all the time so let's use a temporary file for that '-oUserKnownHostsFile={}'.format(n.name), # Don't try keyboard interactive authentication, we're expecting to # login via the key and if that doesn't work then everything else # will fail anyway. '-oKbdInteractiveAuthentication=no', ] while True: ret_code = _call( ['ssh'] + ssh_opts + ['ubuntu@localhost', '-p', '8022', 'true']) if ret_code == 0: break print('Waiting for device') time.sleep(1) # copy the most recent snap into the test VM _check_call( ['scp'] + ssh_opts + [ '-P', '8022', snaps[-1], 'ubuntu@localhost:~/']) # install the snap _check_call( ['ssh'] + ssh_opts + ['ubuntu@localhost', '-p', '8022', 'sudo snappy install *.snap']) # "login" _call( ['ssh'] + ssh_opts + ['-p', '8022', 'ubuntu@localhost'], preexec_fn=os.setsid) finally: if qemu: qemu.kill()
def run(args): # We are mostly making sure we are operating from the correct location. In # the future this could do more by using target attribute in snapcraft.yaml # to create the correct target image. _load_config() # Find the ssh key that ubuntu-device-flash would use so that we can use it # ourselves as well. This may not be the default key that the user has # configured. # See: https://bugs.launchpad.net/snapcraft/+bug/1486659 try: ssh_key = _find_latest_private_key() except LookupError: logger.error('You need to have an SSH key to use this command') logger.error('Please generate one with ssh-keygen(1)') return 1 else: logger.info('Using the following ssh key: %s', ssh_key) # Find available *.snap files to copy into the test VM snap_dir = os.path.join(os.getcwd()) # copy the snap with the largest version number into the test VM snaps = glob.glob(snap_dir + '/*.snap') snaps.sort() if not snaps: logger.error('There are no .snap files ready') logger.error('Perhaps you forgot to run "snapcraft assemble"') return 1 qemudir = os.path.join(os.getcwd(), 'image') qemu_img = os.path.join(qemudir, '15.04.img') if not os.path.exists(qemu_img): os.makedirs(qemudir, exist_ok=True) logger.info( 'Setting up virtual snappy environment, root access required') common.run([ 'sudo', 'ubuntu-device-flash', 'core', '15.04', '--developer-mode', '--enable-ssh', '-o', os.path.relpath(qemu_img, qemudir)], cwd=qemudir) qemu = None try: # Allow the developer to provide additional arguments to qemu. This # can be used, for example, to pass through USB devices from the host. # This can enable a lot of hardware-specific use cases directly inside # the snapcraft run workflow. # # For example: # $ export SNAPCRAFT_RUN_QEMU_ARGS=\ # "-usb -device usb-host,hostbus=1,hostaddr=10" # $ snapcraft run qemu_args = os.getenv('SNAPCRAFT_RUN_QEMU_ARGS') if qemu_args is not None: qemu_args = shlex.split(qemu_args) else: qemu_args = [] qemu = subprocess.Popen( ['kvm', '-m', '768', '-nographic', '-snapshot', '-redir', 'tcp:8022::22', qemu_img] + qemu_args, stdin=subprocess.PIPE) n = tempfile.NamedTemporaryFile() ssh_opts = [ # We want to login with the specified ssh identity (key) '-i', ssh_key, # We don't want strict host checking because it's a new VM with a # random key each time. '-oStrictHostKeyChecking=no', # We don't want to pollute the known_hosts file with new entries # all the time so let's use a temporary file for that '-oUserKnownHostsFile={}'.format(n.name), # Don't try keyboard interactive authentication, we're expecting to # login via the key and if that doesn't work then everything else # will fail anyway. '-oKbdInteractiveAuthentication=no', ] while True: ret_code = _call( ['ssh'] + ssh_opts + ['ubuntu@localhost', '-p', '8022', 'true']) if ret_code == 0: break print('Waiting for device') time.sleep(1) # copy the most recent snap into the test VM _check_call( ['scp'] + ssh_opts + [ '-P', '8022', snaps[-1], 'ubuntu@localhost:~/']) # install the snap _check_call( ['ssh'] + ssh_opts + ['ubuntu@localhost', '-p', '8022', 'sudo snappy install *.snap']) # "login" _check_call( ['ssh'] + ssh_opts + ['-p', '8022', 'ubuntu@localhost'], preexec_fn=os.setsid) finally: if qemu: qemu.kill()