Merge ~jocave/checkbox-support:add-snap-connect-script into checkbox-support:master

Proposed by Jonathan Cave
Status: Merged
Approved by: Jonathan Cave
Approved revision: 3e1a43b7d95af67d5b2689f8d5a7e58721442960
Merged at revision: 87cf772f3b95fb543f86111b0a857fcca94aaebc
Proposed branch: ~jocave/checkbox-support:add-snap-connect-script
Merge into: checkbox-support:master
Diff against target: 148 lines (+131/-0)
2 files modified
checkbox_support/scripts/snap_connect.py (+129/-0)
setup.py (+2/-0)
Reviewer Review Type Date Requested Status
Devices Certification Bot Needs Fixing
Paul Larson Approve
Review via email: mp+355450@code.launchpad.net

Description of the change

Create reusable version of snap_connect.py script that has previously been copied throughout project specific providers.

Tested in plano project.

To post a comment you must log in.
Revision history for this message
Paul Larson (pwlars) wrote :

+1

review: Approve
Revision history for this message
Devices Certification Bot (ce-certification-qa) wrote :

The merge was fine but running tests failed.

[trusty] starting container
[trusty] (timing) 0.00user 0.03system 0:30.34elapsed 0%CPU (0avgtext+0avgdata 5020maxresident)k
[trusty] (timing) 0inputs+80outputs (0major+1163minor)pagefaults 0swaps
[trusty] provisioning container
[trusty] (timing) 72.01user 104.30system 8:40.70elapsed 33%CPU (0avgtext+0avgdata 68700maxresident)k
[trusty] (timing) 8inputs+1609704outputs (16major+1279757minor)pagefaults 0swaps
[trusty-testing] Starting tests...
Found a test script: ./requirements/container-tests-checkbox-support
[trusty-testing] container-tests-checkbox-support: PASS
[trusty-testing] (timing) 14.23user 0.10system 0:44.61elapsed 32%CPU (0avgtext+0avgdata 129388maxresident)k
[trusty-testing] (timing) 0inputs+904outputs (0major+127407minor)pagefaults 0swaps
[trusty-testing] Fixing file permissions in source directory
[trusty-testing] Destroying container
Name: trusty-testing
State: STOPPED
[xenial] starting container
[xenial] Unable to start ephemeral container!
[xenial] stdout:
[xenial] stderr: https://paste.ubuntu.com/p/BBnS2RfMXN/
[xenial] NOTE: unable to execute tests, marked as failed
[xenial] Destroying failed container to reclaim resources
Destroyed container xenial-testing
[bionic] starting container
[bionic] (timing) 0.00user 0.01system 0:30.40elapsed 0%CPU (0avgtext+0avgdata 4996maxresident)k
[bionic] (timing) 0inputs+80outputs (0major+1163minor)pagefaults 0swaps
[bionic] provisioning container
[bionic] (timing) 37.15user 16.74system 6:51.66elapsed 13%CPU (0avgtext+0avgdata 89416maxresident)k
[bionic] (timing) 0inputs+2193096outputs (0major+1956724minor)pagefaults 0swaps
[bionic-testing] Starting tests...
Found a test script: ./requirements/container-tests-checkbox-support
[bionic-testing] container-tests-checkbox-support: PASS
[bionic-testing] (timing) 12.57user 0.18system 0:45.42elapsed 28%CPU (0avgtext+0avgdata 130904maxresident)k
[bionic-testing] (timing) 0inputs+2832outputs (0major+134360minor)pagefaults 0swaps
[bionic-testing] Fixing file permissions in source directory
[bionic-testing] Destroying container
Name: bionic-testing
State: STOPPED

review: Needs Fixing

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/checkbox_support/scripts/snap_connect.py b/checkbox_support/scripts/snap_connect.py
2new file mode 100644
3index 0000000..7e8fac0
4--- /dev/null
5+++ b/checkbox_support/scripts/snap_connect.py
6@@ -0,0 +1,129 @@
7+#!/usr/bin/env python3
8+# Copyright 2017 Canonical Ltd.
9+# All rights reserved.
10+#
11+# Written by:
12+# Jonathan Cave <jonathan.cave@canonical.com>
13+# Maciej Kisielewski <maciej.kisielewski@canonical.com>
14+
15+"""
16+This program connects snap plugs and lists connections between snaps.
17+
18+The syntax of program parameters is A:B:C, where :
19+
20+ A - plug to be connected
21+ B - target snap (snap the plug will connect to)
22+ C - target slot (slot to connect to)
23+
24+ Note that originating snap is implied. $SNAP_NAME is used.
25+
26+Example:
27+ $ sudo ./snap_connect.py udisks2:udisks2:service
28+
29+running
30+ $ sudo ./snap_connect.py A:B:C
31+is equivalent to:
32+ $ snap connect $SNAP_NAME:A B:C
33+
34+ Note that the program needs sudo if asked to connect plugs.
35+"""
36+
37+import argparse
38+import json
39+import logging
40+import requests_unixsocket
41+import os
42+import sys
43+import time
44+from collections import namedtuple
45+
46+
47+Connection = namedtuple(
48+ 'Connection',
49+ ['target_snap', 'target_slot', 'plug_snap', 'plug_plug'])
50+
51+
52+class BadRequest(Exception):
53+ pass
54+
55+
56+def main():
57+ parser = argparse.ArgumentParser()
58+ parser.add_argument(
59+ 'connections', nargs='+', default=[],
60+ metavar='plug:target_snap:target_slot')
61+ args = parser.parse_args()
62+ api = SnapdAPI()
63+
64+ for conn in [spec.split(':') for spec in args.connections]:
65+ if len(conn) != 3:
66+ raise SystemExit("Bad connection description")
67+ assert os.environ['SNAP_NAME']
68+ snap = os.environ['SNAP_NAME']
69+ existing_connections = api.get_connections()
70+ new_connection = Connection(
71+ target_snap=conn[1], target_slot=conn[2],
72+ plug_snap=snap, plug_plug=conn[0])
73+ if new_connection not in existing_connections:
74+ try:
75+ api.connect(new_connection)
76+ except BadRequest as exc:
77+ logging.warning("Failed to connect %s to %s. %s" % (
78+ conn[0], conn[1], exc))
79+
80+
81+class SnapdAPI():
82+ """Based on https://github.com/snapcore/snapd/wiki/REST-API"""
83+ SNAPD_BASE_URL = 'http+unix://%2Frun%2Fsnapd.socket'
84+
85+ def __init__(self):
86+ self.session = requests_unixsocket.Session()
87+
88+ def get_connections(self):
89+ data = self._get('/v2/interfaces')
90+ connections = []
91+ if 'plugs' in data:
92+ for plug in data['plugs']:
93+ if 'connections' in plug:
94+ for con in plug['connections']:
95+ connections.append(Connection(
96+ con['snap'], con['slot'],
97+ plug['snap'], plug['plug']))
98+ return connections
99+
100+ def connect(self, con):
101+ json_data = json.dumps({
102+ 'action': 'connect',
103+ 'slots': [{'snap': con.target_snap, 'slot': con.target_slot}],
104+ 'plugs': [{'snap': con.plug_snap, 'plug': con.plug_plug}]
105+ })
106+ res = self._post('/v2/interfaces', json_data)
107+ ready = False
108+ while not ready:
109+ # busy wait until snapd reports connection job as finised
110+ time.sleep(0.5)
111+ con_res = self._get('/v2/changes/{}'.format(res['change']))
112+ ready = con_res['ready']
113+
114+ def _get(self, path):
115+ res = self.session.get(self.SNAPD_BASE_URL + path)
116+ if not res.ok:
117+ logging.error("Got error %i attempting to access %s",
118+ res.status_code, path)
119+ sys.exit(1)
120+ return res.json()['result']
121+
122+ def _post(self, path, data=None):
123+ res = self.session.post(self.SNAPD_BASE_URL + path, data=data)
124+ if not res.ok:
125+ full_res = json.loads(res.text)
126+ if res.status_code == 400:
127+ raise BadRequest(full_res['result']['message'])
128+ logging.error("Got error %i attempting to access %s",
129+ res.status_code, path)
130+ sys.exit(1)
131+ return res.json()
132+
133+
134+if __name__ == '__main__':
135+ main()
136diff --git a/setup.py b/setup.py
137index df2923a..c2517fd 100755
138--- a/setup.py
139+++ b/setup.py
140@@ -88,6 +88,8 @@ setup(
141 "checkbox_support.scripts.snap_configuration:main"),
142 ("checkbox-support-nmea_test="
143 "checkbox_support.scripts.nmea_test:main"),
144+ ("checkbox-support-snap_connect="
145+ "checkbox_support.scripts.snap_connect:main"),
146 ],
147 },
148 )

Subscribers

People subscribed via source and target branches