Merge lp:~zyga/snapcraft/fix-1486659 into lp:~snappy-dev/snapcraft/core

Proposed by Zygmunt Krynicki on 2015-08-26
Status: Merged
Approved by: Michael Vogt on 2015-08-26
Approved revision: 146
Merged at revision: 138
Proposed branch: lp:~zyga/snapcraft/fix-1486659
Merge into: lp:~snappy-dev/snapcraft/core
Diff against target: 125 lines (+84/-9)
1 file modified
snapcraft/cmds.py (+84/-9)
To merge this branch: bzr merge lp:~zyga/snapcraft/fix-1486659
Reviewer Review Type Date Requested Status
Michael Vogt 2015-08-26 Approve on 2015-08-26
Review via email: mp+269190@code.launchpad.net

Commit Message

Fix numerous issues in snapcraft run

Description of the Change

This branch fixes numerous related issues in snapcraft run. I would recommend to read the flow of commits one-by-one, in order.

To post a comment you must log in.
Michael Vogt (mvo) wrote :

Looks good, thanks!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'snapcraft/cmds.py'
2--- snapcraft/cmds.py 2015-08-26 09:11:57 +0000
3+++ snapcraft/cmds.py 2015-08-26 10:29:20 +0000
4@@ -158,7 +158,74 @@
5 common.run(['snappy', 'build', common.get_snapdir()])
6
7
8+def _find_latest_private_key():
9+ """
10+ Find the latest private key in ~/.ssh.
11+
12+ :returns:
13+ Path of the most-recently-modified private SSH key
14+ :raises LookupError:
15+ If no such key was found.
16+
17+ This function tries to mimic the logic found in ``ubuntu-device-flash``. It
18+ will look for the most recently modified private key in the users' SSH
19+ configuration directory.
20+ """
21+ candidates = []
22+ ssh_dir = os.path.expanduser('~/.ssh/')
23+ for filename in os.listdir(ssh_dir):
24+ # Skip public keys, we want the private key
25+ if filename.endswith('.pub'):
26+ continue
27+ ssh_key = os.path.join(ssh_dir, filename)
28+ # Skip non-files
29+ if not os.path.isfile(ssh_key):
30+ continue
31+ # Ensure that it is a real ssh key
32+ with open(ssh_key, 'rb') as stream:
33+ if stream.readline() != b'-----BEGIN RSA PRIVATE KEY-----\n':
34+ continue
35+ candidates.append(ssh_key)
36+ # Sort the keys by modification time, pick the most recent key
37+ candidates.sort(key=lambda f: os.stat(f).st_mtime, reverse=True)
38+ logger.debug("Available ssh public keys: %r", candidates)
39+ if not candidates:
40+ raise LookupError("Unable to find any private ssh key")
41+ return candidates[0]
42+
43+
44 def run(args):
45+ # Find the ssh key that ubuntu-device-flash would use so that we can use it
46+ # ourselves as well. This may not be the default key that the user has
47+ # configured.
48+ # See: https://bugs.launchpad.net/snapcraft/+bug/1486659
49+ try:
50+ ssh_key = _find_latest_private_key()
51+ except LookupError:
52+ logger.error("You need to have an SSH key to use this command")
53+ logger.error("Please generate one with ssh-keygen(1)")
54+ return 1
55+ else:
56+ logger.info("Using the following ssh key: %s", ssh_key)
57+
58+ # Find available *.snap files to copy into the test VM
59+ snap_dir = os.path.join(os.getcwd())
60+ # copy the snap with the largest version number into the test VM
61+ snaps = glob.glob(snap_dir + "/*.snap")
62+ snaps.sort()
63+ if not snaps:
64+ logger.error("There are no .snap files ready")
65+ logger.error("Perhaps you forgot to run 'snapcraft assemble'")
66+ return 1
67+
68+ def _call(args, **kwargs):
69+ logger.info('Running: %s', ' '.join(shlex.quote(arg) for arg in args))
70+ return subprocess.call(args, **kwargs)
71+
72+ def _check_call(args, **kwargs):
73+ logger.info('Running: %s', ' '.join(shlex.quote(arg) for arg in args))
74+ return subprocess.check_call(args, **kwargs)
75+
76 qemudir = os.path.join(os.getcwd(), "image")
77 qemu_img = os.path.join(qemudir, "15.04.img")
78 if not os.path.exists(qemu_img):
79@@ -177,29 +244,37 @@
80 stdin=subprocess.PIPE)
81 n = tempfile.NamedTemporaryFile()
82 ssh_opts = [
83+ # We want to login with the specified ssh identity (key)
84+ '-i', ssh_key,
85+ # We don't want strict host checking because it's a new VM with a
86+ # random key each time.
87 "-oStrictHostKeyChecking=no",
88- "-oUserKnownHostsFile=%s" % n.name
89+ # We don't want to pollute the known_hosts file with new entries
90+ # all the time so let's use a temporary file for that
91+ "-oUserKnownHostsFile=%s" % n.name,
92+ # Don't try keyboard interactive authentication, we're expecting to
93+ # login via the key and if that doesn't work then everything else
94+ # will fail anyway.
95+ "-oKbdInteractiveAuthentication=no",
96 ]
97 while True:
98- ret_code = subprocess.call(
99+ ret_code = _call(
100 ["ssh"] + ssh_opts +
101 ["ubuntu@localhost", "-p", "8022", "true"])
102 if ret_code == 0:
103 break
104 print("Waiting for device")
105 time.sleep(1)
106- snap_dir = os.path.join(os.getcwd(), "snap")
107- # copy the snap
108- snaps = glob.glob(snap_dir + "/*.snap")
109- subprocess.call(
110+ # copy the most recent snap into the test VM
111+ _check_call(
112 ["scp"] + ssh_opts + [
113- "-P", "8022", "-r"] + snaps + ["ubuntu@localhost:~/"])
114+ "-P", "8022", snaps[-1], "ubuntu@localhost:~/"])
115 # install the snap
116- ret_code = subprocess.call(
117+ _check_call(
118 ["ssh"] + ssh_opts +
119 ["ubuntu@localhost", "-p", "8022", "sudo snappy install *.snap"])
120 # "login"
121- subprocess.call(
122+ _check_call(
123 ["ssh"] + ssh_opts + ["-p", "8022", "ubuntu@localhost"],
124 preexec_fn=os.setsid)
125 finally:

Subscribers

People subscribed via source and target branches