Skip to content

Commit 209fd42

Browse files
committed
Blacken qvm-start
1 parent 55bb4aa commit 209fd42

1 file changed

Lines changed: 108 additions & 75 deletions

File tree

qubesadmin/tools/qvm_start.py

Lines changed: 108 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
# You should have received a copy of the GNU Lesser General Public License along
1919
# with this program; if not, see <http://www.gnu.org/licenses/>.
2020

21-
'''qvm-start - start a domain'''
21+
"""qvm-start - start a domain"""
2222
import asyncio
2323
import argparse
2424
import string
@@ -32,20 +32,22 @@
3232
import qubesadmin.exc
3333
import qubesadmin.tools
3434

35+
3536
class DriveAction(argparse.Action):
36-
'''Action for argument parser that stores drive image path.'''
37+
"""Action for argument parser that stores drive image path."""
3738

3839
# pylint: disable=redefined-builtin
39-
def __init__(self,
40-
option_strings,
41-
dest='drive',
42-
*,
43-
prefix='cdrom:',
44-
metavar='IMAGE',
45-
required=False,
46-
help='Attach drive'):
47-
super().__init__(option_strings, dest,
48-
metavar=metavar, help=help)
40+
def __init__(
41+
self,
42+
option_strings,
43+
dest="drive",
44+
*,
45+
prefix="cdrom:",
46+
metavar="IMAGE",
47+
required=False,
48+
help="Attach drive",
49+
):
50+
super().__init__(option_strings, dest, metavar=metavar, help=help)
4951
self.prefix = prefix
5052

5153
def __call__(self, parser, namespace, values, option_string=None):
@@ -54,30 +56,50 @@ def __call__(self, parser, namespace, values, option_string=None):
5456

5557

5658
parser = qubesadmin.tools.QubesArgumentParser(
57-
description='start a domain', vmname_nargs='+')
59+
description="start a domain", vmname_nargs="+"
60+
)
5861

59-
parser.add_argument('--skip-if-running',
60-
action='store_true', default=False,
61-
help='Do not fail if the qube is already runnning')
62+
parser.add_argument(
63+
"--skip-if-running",
64+
action="store_true",
65+
default=False,
66+
help="Do not fail if the qube is already runnning",
67+
)
6268

6369
parser_drive = parser.add_mutually_exclusive_group()
6470

65-
parser_drive.add_argument('--drive', metavar='DRIVE',
66-
help='temporarily attach specified drive as CD/DVD or hard disk (can be'
67-
' specified with prefix "hd:" or "cdrom:", default is cdrom)')
68-
69-
parser_drive.add_argument('--hddisk',
70-
action=DriveAction, dest='drive', prefix='hd:',
71-
help='temporarily attach specified drive as hard disk')
72-
73-
parser_drive.add_argument('--cdrom', metavar='IMAGE',
74-
action=DriveAction, dest='drive', prefix='cdrom:',
75-
help='temporarily attach specified drive as CD/DVD')
76-
77-
parser_drive.add_argument('--install-windows-tools',
78-
action='store_const', dest='drive', default=False,
79-
const='cdrom:dom0:/usr/lib/qubes/qubes-windows-tools.iso',
80-
help='temporarily attach Windows tools CDROM to the domain')
71+
parser_drive.add_argument(
72+
"--drive",
73+
metavar="DRIVE",
74+
help="temporarily attach specified drive as CD/DVD or hard disk (can be"
75+
' specified with prefix "hd:" or "cdrom:", default is cdrom)',
76+
)
77+
78+
parser_drive.add_argument(
79+
"--hddisk",
80+
action=DriveAction,
81+
dest="drive",
82+
prefix="hd:",
83+
help="temporarily attach specified drive as hard disk",
84+
)
85+
86+
parser_drive.add_argument(
87+
"--cdrom",
88+
metavar="IMAGE",
89+
action=DriveAction,
90+
dest="drive",
91+
prefix="cdrom:",
92+
help="temporarily attach specified drive as CD/DVD",
93+
)
94+
95+
parser_drive.add_argument(
96+
"--install-windows-tools",
97+
action="store_const",
98+
dest="drive",
99+
default=False,
100+
const="cdrom:dom0:/usr/lib/qubes/qubes-windows-tools.iso",
101+
help="temporarily attach Windows tools CDROM to the domain",
102+
)
81103

82104

83105
def get_drive_assignment(app, drive_str):
@@ -93,75 +115,86 @@ def get_drive_assignment(app, drive_str):
93115
:param drive_str: drive argument
94116
:return: DeviceAssignment matching *drive_str*
95117
"""
96-
devtype = 'cdrom'
97-
if drive_str.startswith('cdrom:'):
98-
devtype = 'cdrom'
99-
drive_str = drive_str[len('cdrom:'):]
100-
elif drive_str.startswith('hd:'):
101-
devtype = 'disk'
102-
drive_str = drive_str[len('hd:'):]
118+
devtype = "cdrom"
119+
if drive_str.startswith("cdrom:"):
120+
devtype = "cdrom"
121+
drive_str = drive_str[len("cdrom:") :]
122+
elif drive_str.startswith("hd:"):
123+
devtype = "disk"
124+
drive_str = drive_str[len("hd:") :]
103125

104126
try:
105-
backend_domain_name, port_id = drive_str.split(':', 1)
127+
backend_domain_name, port_id = drive_str.split(":", 1)
106128
except ValueError:
107-
raise ValueError("Incorrect image name: image must be in the format "
108-
"of VMNAME:full_path, for example "
109-
"dom0:/home/user/test.iso")
129+
raise ValueError(
130+
"Incorrect image name: image must be in the format "
131+
"of VMNAME:full_path, for example "
132+
"dom0:/home/user/test.iso"
133+
)
110134
try:
111135
backend_domain = app.domains[backend_domain_name]
112136
except KeyError:
113137
raise qubesadmin.exc.QubesVMNotFoundError(
114-
'No such VM: %s', backend_domain_name)
115-
if port_id.startswith('/'):
138+
"No such VM: %s", backend_domain_name
139+
)
140+
if port_id.startswith("/"):
116141
# it is a path - if we're running in dom0, try to call losetup to
117142
# export the device, otherwise reject
118-
if app.qubesd_connection_type == 'qrexec':
143+
if app.qubesd_connection_type == "qrexec":
119144
raise qubesadmin.exc.QubesException(
120-
'Existing block device identifier needed when running from '
121-
'outside of dom0 (see qvm-block)')
145+
"Existing block device identifier needed when running from "
146+
"outside of dom0 (see qvm-block)"
147+
)
122148
try:
123-
if backend_domain.klass == 'AdminVM':
149+
if backend_domain.klass == "AdminVM":
124150
loop_name = subprocess.check_output(
125-
['sudo', 'losetup', '-f', '--show', port_id])
151+
["sudo", "losetup", "-f", "--show", port_id]
152+
)
126153
loop_name = loop_name.strip()
127154
else:
128155
untrusted_loop_name, _ = backend_domain.run_with_args(
129-
'losetup', '-f', '--show', port_id,
130-
user='root')
156+
"losetup", "-f", "--show", port_id, user="root"
157+
)
131158
untrusted_loop_name = untrusted_loop_name.strip()
132-
allowed_chars = string.ascii_lowercase + string.digits + '/'
133-
allowed_chars = allowed_chars.encode('ascii')
159+
allowed_chars = string.ascii_lowercase + string.digits + "/"
160+
allowed_chars = allowed_chars.encode("ascii")
134161
if not all(c in allowed_chars for c in untrusted_loop_name):
135162
raise qubesadmin.exc.QubesException(
136-
'Invalid loop device name received from {}'.format(
137-
backend_domain.name))
163+
"Invalid loop device name received from {}".format(
164+
backend_domain.name
165+
)
166+
)
138167
loop_name = untrusted_loop_name
139168
del untrusted_loop_name
140169
except subprocess.CalledProcessError:
141170
raise qubesadmin.exc.QubesException(
142-
'Failed to setup loop device for %s', port_id)
143-
assert loop_name.startswith(b'/dev/loop')
144-
port_id = loop_name.decode().split('/')[2]
171+
"Failed to setup loop device for %s", port_id
172+
)
173+
assert loop_name.startswith(b"/dev/loop")
174+
port_id = loop_name.decode().split("/")[2]
145175
# wait for device to appear
146176
# FIXME: convert this to waiting for event
147177
timeout = 10
148178
while isinstance(
149-
backend_domain.devices['block'][port_id], UnknownDevice
179+
backend_domain.devices["block"][port_id], UnknownDevice
150180
):
151181
if timeout == 0:
152182
raise qubesadmin.exc.QubesException(
153-
'Timeout waiting for {}:{} device to appear'.format(
154-
backend_domain.name, port_id))
183+
"Timeout waiting for {}:{} device to appear".format(
184+
backend_domain.name, port_id
185+
)
186+
)
155187
timeout -= 1
156188
time.sleep(1)
157189

158-
options = {
159-
'devtype': devtype,
160-
'read-only': devtype == 'cdrom'
161-
}
190+
options = {"devtype": devtype, "read-only": devtype == "cdrom"}
162191
assignment = DeviceAssignment.new(
163-
backend_domain=backend_domain, port_id=port_id, devclass='block',
164-
options=options, mode="required")
192+
backend_domain=backend_domain,
193+
port_id=port_id,
194+
devclass="block",
195+
options=options,
196+
mode="required",
197+
)
165198

166199
return assignment
167200

@@ -181,7 +214,7 @@ def startup(domain, args=None):
181214
if args.drive:
182215
drive_assignment = get_drive_assignment(args.app, args.drive)
183216
try:
184-
domain.devices['block'].assign(drive_assignment)
217+
domain.devices["block"].assign(drive_assignment)
185218
except Exception:
186219
drive_assignment = None
187220
raise
@@ -190,11 +223,11 @@ def startup(domain, args=None):
190223

191224
if drive_assignment:
192225
# don't reconnect this device after VM reboot
193-
domain.devices['block'].unassign(drive_assignment)
226+
domain.devices["block"].unassign(drive_assignment)
194227
except (IOError, OSError, qubesadmin.exc.QubesException, ValueError) as e:
195228
if drive_assignment:
196229
try:
197-
domain.devices['block'].detach(drive_assignment)
230+
domain.devices["block"].detach(drive_assignment)
198231
except qubesadmin.exc.QubesException:
199232
pass
200233
raise e
@@ -213,19 +246,19 @@ async def run_async(args=None, app=None):
213246
if isinstance(res, BaseException):
214247
exit_code = 1
215248
parser.print_error(
216-
'Starting qube failed: {}: {}'.format(qube.name, str(res))
249+
"Starting qube failed: {}: {}".format(qube.name, str(res))
217250
)
218251
return exit_code
219252

220253

221254
def main(args=None, app=None):
222-
'''Main routine of :program:`qvm-start`.
255+
"""Main routine of :program:`qvm-start`.
223256
224257
:param list args: Optional arguments to override those delivered from \
225258
command line.
226-
'''
259+
"""
227260
return asyncio.run(run_async(args=args, app=app))
228261

229262

230-
if __name__ == '__main__':
263+
if __name__ == "__main__":
231264
sys.exit(main())

0 commit comments

Comments
 (0)