Fix issues found by pylint 2.0
Resolve: - no-else-return - useless-object-inheritance - useless-return - consider-using-set-comprehension - consider-using-in - logging-not-lazy Ignore: - not-an-iterable - false possitives for asyncio coroutines Ignore all the above in qubespolicy/__init__.py, as the file will be moved to separate repository (core-qrexec) - it already has a copy there, don't desynchronize them.
This commit is contained in:
parent
f8d17012c3
commit
be2465c1f9
@ -6,6 +6,8 @@ ignore=tests
|
|||||||
# abstract-class-little-used: see http://www.logilab.org/ticket/111138
|
# abstract-class-little-used: see http://www.logilab.org/ticket/111138
|
||||||
# deprecated-method:
|
# deprecated-method:
|
||||||
# enable again after disabling py-3.4.3 asyncio.ensure_future compat hack
|
# enable again after disabling py-3.4.3 asyncio.ensure_future compat hack
|
||||||
|
# not-an-iterable:
|
||||||
|
# a lot of false possitives for asyncio (yield from (some coroutine))
|
||||||
disable=
|
disable=
|
||||||
abstract-class-little-used,
|
abstract-class-little-used,
|
||||||
bad-continuation,
|
bad-continuation,
|
||||||
@ -18,6 +20,7 @@ disable=
|
|||||||
locally-enabled,
|
locally-enabled,
|
||||||
logging-format-interpolation,
|
logging-format-interpolation,
|
||||||
missing-docstring,
|
missing-docstring,
|
||||||
|
not-an-iterable,
|
||||||
star-args,
|
star-args,
|
||||||
wrong-import-order
|
wrong-import-order
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ __license__ = 'GPLv2 or later'
|
|||||||
__version__ = 'R3'
|
__version__ = 'R3'
|
||||||
|
|
||||||
|
|
||||||
class Label(object):
|
class Label:
|
||||||
'''Label definition for virtual machines
|
'''Label definition for virtual machines
|
||||||
|
|
||||||
Label specifies colour of the padlock displayed next to VM's name.
|
Label specifies colour of the padlock displayed next to VM's name.
|
||||||
@ -134,7 +134,7 @@ class Label(object):
|
|||||||
self.icon_dispvm) + ".png"
|
self.icon_dispvm) + ".png"
|
||||||
|
|
||||||
|
|
||||||
class property(object): # pylint: disable=redefined-builtin,invalid-name
|
class property: # pylint: disable=redefined-builtin,invalid-name
|
||||||
'''Qubes property.
|
'''Qubes property.
|
||||||
|
|
||||||
This class holds one property that can be saved to and loaded from
|
This class holds one property that can be saved to and loaded from
|
||||||
@ -350,11 +350,10 @@ class property(object): # pylint: disable=redefined-builtin,invalid-name
|
|||||||
raise qubes.exc.QubesValueError
|
raise qubes.exc.QubesValueError
|
||||||
if self.type is bool:
|
if self.type is bool:
|
||||||
return self.bool(None, None, untrusted_newvalue)
|
return self.bool(None, None, untrusted_newvalue)
|
||||||
else:
|
try:
|
||||||
try:
|
return self.type(untrusted_newvalue)
|
||||||
return self.type(untrusted_newvalue)
|
except ValueError:
|
||||||
except ValueError:
|
raise qubes.exc.QubesValueError
|
||||||
raise qubes.exc.QubesValueError
|
|
||||||
else:
|
else:
|
||||||
# 'str' or not specified type
|
# 'str' or not specified type
|
||||||
try:
|
try:
|
||||||
|
@ -97,7 +97,7 @@ def apply_filters(iterable, filters):
|
|||||||
return iterable
|
return iterable
|
||||||
|
|
||||||
|
|
||||||
class AbstractQubesAPI(object):
|
class AbstractQubesAPI:
|
||||||
'''Common code for Qubes Management Protocol handling
|
'''Common code for Qubes Management Protocol handling
|
||||||
|
|
||||||
Different interfaces can expose different API call sets, however they share
|
Different interfaces can expose different API call sets, however they share
|
||||||
|
@ -44,7 +44,7 @@ import qubes.vm.adminvm
|
|||||||
import qubes.vm.qubesvm
|
import qubes.vm.qubesvm
|
||||||
|
|
||||||
|
|
||||||
class QubesMgmtEventsDispatcher(object):
|
class QubesMgmtEventsDispatcher:
|
||||||
def __init__(self, filters, send_event):
|
def __init__(self, filters, send_event):
|
||||||
self.filters = filters
|
self.filters = filters
|
||||||
self.send_event = send_event
|
self.send_event = send_event
|
||||||
|
56
qubes/app.py
56
qubes/app.py
@ -66,7 +66,7 @@ import qubes.vm.qubesvm
|
|||||||
import qubes.vm.templatevm
|
import qubes.vm.templatevm
|
||||||
# pylint: enable=wrong-import-position
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
class VirDomainWrapper(object):
|
class VirDomainWrapper:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
def __init__(self, connection, vm):
|
def __init__(self, connection, vm):
|
||||||
@ -97,7 +97,7 @@ class VirDomainWrapper(object):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class VirConnectWrapper(object):
|
class VirConnectWrapper:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
def __init__(self, uri):
|
def __init__(self, uri):
|
||||||
@ -134,7 +134,7 @@ class VirConnectWrapper(object):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
class VMMConnection(object):
|
class VMMConnection:
|
||||||
'''Connection to Virtual Machine Manager (libvirt)'''
|
'''Connection to Virtual Machine Manager (libvirt)'''
|
||||||
|
|
||||||
def __init__(self, offline_mode=None):
|
def __init__(self, offline_mode=None):
|
||||||
@ -229,7 +229,7 @@ class VMMConnection(object):
|
|||||||
self._xc = None # and pray it will get garbage-collected
|
self._xc = None # and pray it will get garbage-collected
|
||||||
|
|
||||||
|
|
||||||
class QubesHost(object):
|
class QubesHost:
|
||||||
'''Basic information about host machine
|
'''Basic information about host machine
|
||||||
|
|
||||||
:param qubes.Qubes app: Qubes application context (must have \
|
:param qubes.Qubes app: Qubes application context (must have \
|
||||||
@ -363,7 +363,7 @@ class QubesHost(object):
|
|||||||
return (current_time, current)
|
return (current_time, current)
|
||||||
|
|
||||||
|
|
||||||
class VMCollection(object):
|
class VMCollection:
|
||||||
'''A collection of Qubes VMs
|
'''A collection of Qubes VMs
|
||||||
|
|
||||||
VMCollection supports ``in`` operator. You may test for ``qid``, ``name``
|
VMCollection supports ``in`` operator. You may test for ``qid``, ``name``
|
||||||
@ -493,7 +493,7 @@ class VMCollection(object):
|
|||||||
self.app.fire_event('domain-delete', vm=vm)
|
self.app.fire_event('domain-delete', vm=vm)
|
||||||
|
|
||||||
def __contains__(self, key):
|
def __contains__(self, key):
|
||||||
return any((key == vm or key == vm.qid or key == vm.name)
|
return any((key in (vm, vm.qid, vm.name))
|
||||||
for vm in self)
|
for vm in self)
|
||||||
|
|
||||||
|
|
||||||
@ -557,32 +557,32 @@ def _default_pool(app):
|
|||||||
'''
|
'''
|
||||||
if 'default' in app.pools:
|
if 'default' in app.pools:
|
||||||
return app.pools['default']
|
return app.pools['default']
|
||||||
else:
|
|
||||||
if 'DEFAULT_LVM_POOL' in os.environ:
|
|
||||||
thin_pool = os.environ['DEFAULT_LVM_POOL']
|
|
||||||
for pool in app.pools.values():
|
|
||||||
if pool.config.get('driver', None) != 'lvm_thin':
|
|
||||||
continue
|
|
||||||
if pool.config['thin_pool'] == thin_pool:
|
|
||||||
return pool
|
|
||||||
# no DEFAULT_LVM_POOL, or pool not defined
|
|
||||||
root_volume_group, root_thin_pool = \
|
|
||||||
qubes.storage.DirectoryThinPool.thin_pool('/')
|
|
||||||
if root_thin_pool:
|
|
||||||
for pool in app.pools.values():
|
|
||||||
if pool.config.get('driver', None) != 'lvm_thin':
|
|
||||||
continue
|
|
||||||
if (pool.config['volume_group'] == root_volume_group and
|
|
||||||
pool.config['thin_pool'] == root_thin_pool):
|
|
||||||
return pool
|
|
||||||
|
|
||||||
# not a thin volume? look for file pools
|
if 'DEFAULT_LVM_POOL' in os.environ:
|
||||||
|
thin_pool = os.environ['DEFAULT_LVM_POOL']
|
||||||
for pool in app.pools.values():
|
for pool in app.pools.values():
|
||||||
if pool.config.get('driver', None) not in ('file', 'file-reflink'):
|
if pool.config.get('driver', None) != 'lvm_thin':
|
||||||
continue
|
continue
|
||||||
if pool.config['dir_path'] == qubes.config.qubes_base_dir:
|
if pool.config['thin_pool'] == thin_pool:
|
||||||
return pool
|
return pool
|
||||||
raise AttributeError('Cannot determine default storage pool')
|
# no DEFAULT_LVM_POOL, or pool not defined
|
||||||
|
root_volume_group, root_thin_pool = \
|
||||||
|
qubes.storage.DirectoryThinPool.thin_pool('/')
|
||||||
|
if root_thin_pool:
|
||||||
|
for pool in app.pools.values():
|
||||||
|
if pool.config.get('driver', None) != 'lvm_thin':
|
||||||
|
continue
|
||||||
|
if (pool.config['volume_group'] == root_volume_group and
|
||||||
|
pool.config['thin_pool'] == root_thin_pool):
|
||||||
|
return pool
|
||||||
|
|
||||||
|
# not a thin volume? look for file pools
|
||||||
|
for pool in app.pools.values():
|
||||||
|
if pool.config.get('driver', None) not in ('file', 'file-reflink'):
|
||||||
|
continue
|
||||||
|
if pool.config['dir_path'] == qubes.config.qubes_base_dir:
|
||||||
|
return pool
|
||||||
|
raise AttributeError('Cannot determine default storage pool')
|
||||||
|
|
||||||
def _setter_pool(app, prop, value):
|
def _setter_pool(app, prop, value):
|
||||||
if isinstance(value, qubes.storage.Pool):
|
if isinstance(value, qubes.storage.Pool):
|
||||||
|
@ -75,7 +75,7 @@ class BackupCanceledError(qubes.exc.QubesException):
|
|||||||
self.tmpdir = tmpdir
|
self.tmpdir = tmpdir
|
||||||
|
|
||||||
|
|
||||||
class BackupHeader(object):
|
class BackupHeader:
|
||||||
'''Structure describing backup-header file included as the first file in
|
'''Structure describing backup-header file included as the first file in
|
||||||
backup archive
|
backup archive
|
||||||
'''
|
'''
|
||||||
@ -123,7 +123,7 @@ class BackupHeader(object):
|
|||||||
f_header.write("{!s}={!s}\n".format(key, getattr(self, attr)))
|
f_header.write("{!s}={!s}\n".format(key, getattr(self, attr)))
|
||||||
|
|
||||||
|
|
||||||
class SendWorker(object):
|
class SendWorker:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, queue, base_dir, backup_stdout):
|
def __init__(self, queue, base_dir, backup_stdout):
|
||||||
super(SendWorker, self).__init__()
|
super(SendWorker, self).__init__()
|
||||||
@ -147,6 +147,7 @@ class SendWorker(object):
|
|||||||
# verified before untaring.
|
# verified before untaring.
|
||||||
tar_final_cmd = ["tar", "-cO", "--posix",
|
tar_final_cmd = ["tar", "-cO", "--posix",
|
||||||
"-C", self.base_dir, filename]
|
"-C", self.base_dir, filename]
|
||||||
|
# pylint: disable=not-an-iterable
|
||||||
final_proc = yield from asyncio.create_subprocess_exec(
|
final_proc = yield from asyncio.create_subprocess_exec(
|
||||||
*tar_final_cmd,
|
*tar_final_cmd,
|
||||||
stdout=self.backup_stdout)
|
stdout=self.backup_stdout)
|
||||||
@ -182,6 +183,7 @@ def launch_proc_with_pty(args, stdin=None, stdout=None, stderr=None, echo=True):
|
|||||||
termios_p[3] &= ~termios.ECHO
|
termios_p[3] &= ~termios.ECHO
|
||||||
termios.tcsetattr(ctty_fd, termios.TCSANOW, termios_p)
|
termios.tcsetattr(ctty_fd, termios.TCSANOW, termios_p)
|
||||||
(pty_master, pty_slave) = os.openpty()
|
(pty_master, pty_slave) = os.openpty()
|
||||||
|
# pylint: disable=not-an-iterable
|
||||||
p = yield from asyncio.create_subprocess_exec(*args,
|
p = yield from asyncio.create_subprocess_exec(*args,
|
||||||
stdin=stdin,
|
stdin=stdin,
|
||||||
stdout=stdout,
|
stdout=stdout,
|
||||||
@ -227,7 +229,7 @@ def launch_scrypt(action, input_name, output_name, passphrase):
|
|||||||
return p
|
return p
|
||||||
|
|
||||||
|
|
||||||
class Backup(object):
|
class Backup:
|
||||||
'''Backup operation manager. Usage:
|
'''Backup operation manager. Usage:
|
||||||
|
|
||||||
>>> app = qubes.Qubes()
|
>>> app = qubes.Qubes()
|
||||||
@ -250,7 +252,7 @@ class Backup(object):
|
|||||||
|
|
||||||
'''
|
'''
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class FileToBackup(object):
|
class FileToBackup:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, file_path, subdir=None, name=None, size=None):
|
def __init__(self, file_path, subdir=None, name=None, size=None):
|
||||||
if size is None:
|
if size is None:
|
||||||
@ -280,7 +282,7 @@ class Backup(object):
|
|||||||
if name is not None:
|
if name is not None:
|
||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
class VMToBackup(object):
|
class VMToBackup:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, vm, files, subdir):
|
def __init__(self, vm, files, subdir):
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
@ -637,6 +639,7 @@ class Backup(object):
|
|||||||
|
|
||||||
# Pipe: tar-sparse | scrypt | tar | backup_target
|
# Pipe: tar-sparse | scrypt | tar | backup_target
|
||||||
# TODO: log handle stderr
|
# TODO: log handle stderr
|
||||||
|
# pylint: disable=not-an-iterable
|
||||||
tar_sparse = yield from asyncio.create_subprocess_exec(
|
tar_sparse = yield from asyncio.create_subprocess_exec(
|
||||||
*tar_cmdline, stdout=subprocess.PIPE)
|
*tar_cmdline, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class DeviceAlreadyAttached(qubes.exc.QubesException, KeyError):
|
|||||||
'''Trying to attach already attached device'''
|
'''Trying to attach already attached device'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class DeviceInfo(object):
|
class DeviceInfo:
|
||||||
''' Holds all information about a device '''
|
''' Holds all information about a device '''
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, backend_domain, ident, description=None,
|
def __init__(self, backend_domain, ident, description=None,
|
||||||
@ -117,7 +117,7 @@ class DeviceInfo(object):
|
|||||||
return '{!s}:{!s}'.format(self.backend_domain, self.ident)
|
return '{!s}:{!s}'.format(self.backend_domain, self.ident)
|
||||||
|
|
||||||
|
|
||||||
class DeviceAssignment(object): # pylint: disable=too-few-public-methods
|
class DeviceAssignment: # pylint: disable=too-few-public-methods
|
||||||
''' Maps a device to a frontend_domain. '''
|
''' Maps a device to a frontend_domain. '''
|
||||||
|
|
||||||
def __init__(self, backend_domain, ident, options=None, persistent=False,
|
def __init__(self, backend_domain, ident, options=None, persistent=False,
|
||||||
@ -158,7 +158,7 @@ class DeviceAssignment(object): # pylint: disable=too-few-public-methods
|
|||||||
return self.backend_domain.devices[self.bus][self.ident]
|
return self.backend_domain.devices[self.bus][self.ident]
|
||||||
|
|
||||||
|
|
||||||
class DeviceCollection(object):
|
class DeviceCollection:
|
||||||
'''Bag for devices.
|
'''Bag for devices.
|
||||||
|
|
||||||
Used as default value for :py:meth:`DeviceManager.__missing__` factory.
|
Used as default value for :py:meth:`DeviceManager.__missing__` factory.
|
||||||
@ -357,8 +357,7 @@ class DeviceCollection(object):
|
|||||||
if persistent is True:
|
if persistent is True:
|
||||||
# don't break app.save()
|
# don't break app.save()
|
||||||
return self._set
|
return self._set
|
||||||
else:
|
raise
|
||||||
raise
|
|
||||||
result = set()
|
result = set()
|
||||||
for dev, options in devices:
|
for dev, options in devices:
|
||||||
if dev in self._set and not persistent:
|
if dev in self._set and not persistent:
|
||||||
@ -433,7 +432,7 @@ class UnknownDevice(DeviceInfo):
|
|||||||
frontend_domain)
|
frontend_domain)
|
||||||
|
|
||||||
|
|
||||||
class PersistentCollection(object):
|
class PersistentCollection:
|
||||||
|
|
||||||
''' Helper object managing persistent `DeviceAssignment`s.
|
''' Helper object managing persistent `DeviceAssignment`s.
|
||||||
'''
|
'''
|
||||||
|
@ -48,7 +48,7 @@ SUBCOMMANDS_TITLE = 'COMMANDS'
|
|||||||
OPTIONS_TITLE = 'OPTIONS'
|
OPTIONS_TITLE = 'OPTIONS'
|
||||||
|
|
||||||
|
|
||||||
class GithubTicket(object):
|
class GithubTicket:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
self.number = data['number']
|
self.number = data['number']
|
||||||
@ -418,7 +418,7 @@ def parse_event(env, sig, signode):
|
|||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
def break_to_pdb(app, *dummy):
|
def break_to_pdb(app, *_dummy):
|
||||||
if not app.config.break_to_pdb:
|
if not app.config.break_to_pdb:
|
||||||
return
|
return
|
||||||
import pdb
|
import pdb
|
||||||
|
@ -94,7 +94,7 @@ class EmitterMeta(type):
|
|||||||
cls.__handlers__[event].add(attr)
|
cls.__handlers__[event].add(attr)
|
||||||
|
|
||||||
|
|
||||||
class Emitter(object, metaclass=EmitterMeta):
|
class Emitter(metaclass=EmitterMeta):
|
||||||
'''Subject that can emit events.
|
'''Subject that can emit events.
|
||||||
|
|
||||||
By default all events are disabled not to interfere with loading from XML.
|
By default all events are disabled not to interfere with loading from XML.
|
||||||
|
@ -29,7 +29,7 @@ import pkg_resources
|
|||||||
import qubes.events
|
import qubes.events
|
||||||
|
|
||||||
|
|
||||||
class Extension(object):
|
class Extension:
|
||||||
'''Base class for all extensions
|
'''Base class for all extensions
|
||||||
''' # pylint: disable=too-few-public-methods
|
''' # pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ import qubes
|
|||||||
import qubes.vm.qubesvm
|
import qubes.vm.qubesvm
|
||||||
|
|
||||||
|
|
||||||
class RuleOption(object):
|
class RuleOption:
|
||||||
def __init__(self, untrusted_value):
|
def __init__(self, untrusted_value):
|
||||||
# subset of string.punctuation
|
# subset of string.punctuation
|
||||||
safe_set = string.ascii_letters + string.digits + \
|
safe_set = string.ascii_letters + string.digits + \
|
||||||
@ -208,7 +208,7 @@ class Expire(RuleOption):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rule(self):
|
def rule(self):
|
||||||
return None
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_rule(self):
|
def api_rule(self):
|
||||||
@ -232,7 +232,7 @@ class Comment(RuleOption):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def rule(self):
|
def rule(self):
|
||||||
return None
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_rule(self):
|
def api_rule(self):
|
||||||
@ -449,7 +449,7 @@ class Rule(qubes.PropertyHolder):
|
|||||||
return hash(self.api_rule)
|
return hash(self.api_rule)
|
||||||
|
|
||||||
|
|
||||||
class Firewall(object):
|
class Firewall:
|
||||||
def __init__(self, vm, load=True):
|
def __init__(self, vm, load=True):
|
||||||
assert hasattr(vm, 'firewall_conf')
|
assert hasattr(vm, 'firewall_conf')
|
||||||
self.vm = vm
|
self.vm = vm
|
||||||
|
@ -26,7 +26,7 @@ import textwrap
|
|||||||
|
|
||||||
import lxml.etree
|
import lxml.etree
|
||||||
|
|
||||||
class Element(object):
|
class Element:
|
||||||
def __init__(self, schema, xml):
|
def __init__(self, schema, xml):
|
||||||
self.schema = schema
|
self.schema = schema
|
||||||
self.xml = xml
|
self.xml = xml
|
||||||
@ -157,7 +157,7 @@ class Element(object):
|
|||||||
write_rst_table(stream, childtable, ('element', 'number'))
|
write_rst_table(stream, childtable, ('element', 'number'))
|
||||||
|
|
||||||
|
|
||||||
class Schema(object):
|
class Schema:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
nsmap = {
|
nsmap = {
|
||||||
'rng': 'http://relaxng.org/ns/structure/1.0',
|
'rng': 'http://relaxng.org/ns/structure/1.0',
|
||||||
|
@ -47,7 +47,7 @@ class StoragePoolException(qubes.exc.QubesException):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class BlockDevice(object):
|
class BlockDevice:
|
||||||
''' Represents a storage block device. '''
|
''' Represents a storage block device. '''
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
def __init__(self, path, name, script=None, rw=True, domain=None,
|
def __init__(self, path, name, script=None, rw=True, domain=None,
|
||||||
@ -62,7 +62,7 @@ class BlockDevice(object):
|
|||||||
self.devtype = devtype
|
self.devtype = devtype
|
||||||
|
|
||||||
|
|
||||||
class Volume(object):
|
class Volume:
|
||||||
''' Encapsulates all data about a volume for serialization to qubes.xml and
|
''' Encapsulates all data about a volume for serialization to qubes.xml and
|
||||||
libvirt config.
|
libvirt config.
|
||||||
|
|
||||||
@ -334,14 +334,14 @@ class Volume(object):
|
|||||||
msg = msg.format(str(self.__class__.__name__), method_name)
|
msg = msg.format(str(self.__class__.__name__), method_name)
|
||||||
return NotImplementedError(msg)
|
return NotImplementedError(msg)
|
||||||
|
|
||||||
class Storage(object):
|
class Storage:
|
||||||
''' Class for handling VM virtual disks.
|
''' Class for handling VM virtual disks.
|
||||||
|
|
||||||
This is base class for all other implementations, mostly with Xen on Linux
|
This is base class for all other implementations, mostly with Xen on Linux
|
||||||
in mind.
|
in mind.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
AVAILABLE_FRONTENDS = set(['xvd' + c for c in string.ascii_lowercase])
|
AVAILABLE_FRONTENDS = {'xvd' + c for c in string.ascii_lowercase}
|
||||||
|
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
#: Domain for which we manage storage
|
#: Domain for which we manage storage
|
||||||
@ -655,9 +655,9 @@ class Storage(object):
|
|||||||
''' Used device names '''
|
''' Used device names '''
|
||||||
xml = self.vm.libvirt_domain.XMLDesc()
|
xml = self.vm.libvirt_domain.XMLDesc()
|
||||||
parsed_xml = lxml.etree.fromstring(xml)
|
parsed_xml = lxml.etree.fromstring(xml)
|
||||||
return set([target.get('dev', None)
|
return {target.get('dev', None)
|
||||||
for target in parsed_xml.xpath(
|
for target in parsed_xml.xpath(
|
||||||
"//domain/devices/disk/target")])
|
"//domain/devices/disk/target")}
|
||||||
|
|
||||||
def export(self, volume):
|
def export(self, volume):
|
||||||
''' Helper function to export volume (pool.export(volume))'''
|
''' Helper function to export volume (pool.export(volume))'''
|
||||||
@ -688,7 +688,7 @@ class Storage(object):
|
|||||||
return self.vm.volumes[volume].import_data_end(success=success)
|
return self.vm.volumes[volume].import_data_end(success=success)
|
||||||
|
|
||||||
|
|
||||||
class VolumesCollection(object):
|
class VolumesCollection:
|
||||||
'''Convenient collection wrapper for pool.get_volume and
|
'''Convenient collection wrapper for pool.get_volume and
|
||||||
pool.list_volumes
|
pool.list_volumes
|
||||||
'''
|
'''
|
||||||
@ -706,8 +706,7 @@ class VolumesCollection(object):
|
|||||||
if isinstance(item, Volume):
|
if isinstance(item, Volume):
|
||||||
if item.pool == self._pool:
|
if item.pool == self._pool:
|
||||||
return self[item.vid]
|
return self[item.vid]
|
||||||
else:
|
raise KeyError(item)
|
||||||
raise KeyError(item)
|
|
||||||
try:
|
try:
|
||||||
return self._pool.get_volume(item)
|
return self._pool.get_volume(item)
|
||||||
except NotImplementedError:
|
except NotImplementedError:
|
||||||
@ -740,7 +739,7 @@ class VolumesCollection(object):
|
|||||||
return [vol for vol in self]
|
return [vol for vol in self]
|
||||||
|
|
||||||
|
|
||||||
class Pool(object):
|
class Pool:
|
||||||
''' A Pool is used to manage different kind of volumes (File
|
''' A Pool is used to manage different kind of volumes (File
|
||||||
based/LVM/Btrfs/...).
|
based/LVM/Btrfs/...).
|
||||||
|
|
||||||
@ -760,7 +759,7 @@ class Pool(object):
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
if isinstance(other, Pool):
|
if isinstance(other, Pool):
|
||||||
return self.name == other.name
|
return self.name == other.name
|
||||||
elif isinstance(other, str):
|
if isinstance(other, str):
|
||||||
return self.name == other
|
return self.name == other
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
@ -829,12 +828,12 @@ class Pool(object):
|
|||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
''' Storage pool size in bytes, or None if unknown '''
|
''' Storage pool size in bytes, or None if unknown '''
|
||||||
return None
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def usage(self):
|
def usage(self):
|
||||||
''' Space used in the pool in bytes, or None if unknown '''
|
''' Space used in the pool in bytes, or None if unknown '''
|
||||||
return None
|
pass
|
||||||
|
|
||||||
def _not_implemented(self, method_name):
|
def _not_implemented(self, method_name):
|
||||||
''' Helper for emitting helpful `NotImplementedError` exceptions '''
|
''' Helper for emitting helpful `NotImplementedError` exceptions '''
|
||||||
@ -898,7 +897,7 @@ def search_pool_containing_dir(pools, dir_path):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class VmCreationManager(object):
|
class VmCreationManager:
|
||||||
''' A `ContextManager` which cleans up if volume creation fails.
|
''' A `ContextManager` which cleans up if volume creation fails.
|
||||||
''' # pylint: disable=too-few-public-methods
|
''' # pylint: disable=too-few-public-methods
|
||||||
def __init__(self, vm):
|
def __init__(self, vm):
|
||||||
|
@ -356,9 +356,9 @@ class FileVolume(qubes.storage.Volume):
|
|||||||
def script(self):
|
def script(self):
|
||||||
if not self.snap_on_start and not self.save_on_stop:
|
if not self.snap_on_start and not self.save_on_stop:
|
||||||
return None
|
return None
|
||||||
elif not self.snap_on_start and self.save_on_stop:
|
if not self.snap_on_start and self.save_on_stop:
|
||||||
return 'block-origin'
|
return 'block-origin'
|
||||||
elif self.snap_on_start:
|
if self.snap_on_start:
|
||||||
return 'block-snapshot'
|
return 'block-snapshot'
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ def get_timezone():
|
|||||||
if os.path.islink('/etc/localtime'):
|
if os.path.islink('/etc/localtime'):
|
||||||
return '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
|
return '/'.join(os.readlink('/etc/localtime').split('/')[-2:])
|
||||||
# <=fc17
|
# <=fc17
|
||||||
elif os.path.exists('/etc/sysconfig/clock'):
|
if os.path.exists('/etc/sysconfig/clock'):
|
||||||
clock_config = open('/etc/sysconfig/clock', "r")
|
clock_config = open('/etc/sysconfig/clock', "r")
|
||||||
clock_config_lines = clock_config.readlines()
|
clock_config_lines = clock_config.readlines()
|
||||||
clock_config.close()
|
clock_config.close()
|
||||||
@ -50,18 +50,17 @@ def get_timezone():
|
|||||||
line_match = zone_re.match(line)
|
line_match = zone_re.match(line)
|
||||||
if line_match:
|
if line_match:
|
||||||
return line_match.group(1)
|
return line_match.group(1)
|
||||||
else:
|
# last resort way, some applications makes /etc/localtime
|
||||||
# last resort way, some applications makes /etc/localtime
|
# hardlink instead of symlink...
|
||||||
# hardlink instead of symlink...
|
tz_info = os.stat('/etc/localtime')
|
||||||
tz_info = os.stat('/etc/localtime')
|
if not tz_info:
|
||||||
if not tz_info:
|
return None
|
||||||
return None
|
if tz_info.st_nlink > 1:
|
||||||
if tz_info.st_nlink > 1:
|
p = subprocess.Popen(['find', '/usr/share/zoneinfo',
|
||||||
p = subprocess.Popen(['find', '/usr/share/zoneinfo',
|
'-inum', str(tz_info.st_ino), '-print', '-quit'],
|
||||||
'-inum', str(tz_info.st_ino), '-print', '-quit'],
|
stdout=subprocess.PIPE)
|
||||||
stdout=subprocess.PIPE)
|
tz_path = p.communicate()[0].strip()
|
||||||
tz_path = p.communicate()[0].strip()
|
return tz_path.replace(b'/usr/share/zoneinfo/', b'')
|
||||||
return tz_path.replace('/usr/share/zoneinfo/', '')
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -132,9 +131,9 @@ def size_to_human(size):
|
|||||||
"""Humane readable size, with 1/10 precision"""
|
"""Humane readable size, with 1/10 precision"""
|
||||||
if size < 1024:
|
if size < 1024:
|
||||||
return str(size)
|
return str(size)
|
||||||
elif size < 1024 * 1024:
|
if size < 1024 * 1024:
|
||||||
return str(round(size / 1024.0, 1)) + ' KiB'
|
return str(round(size / 1024.0, 1)) + ' KiB'
|
||||||
elif size < 1024 * 1024 * 1024:
|
if size < 1024 * 1024 * 1024:
|
||||||
return str(round(size / (1024.0 * 1024), 1)) + ' MiB'
|
return str(round(size / (1024.0 * 1024), 1)) + ' MiB'
|
||||||
|
|
||||||
return str(round(size / (1024.0 * 1024 * 1024), 1)) + ' GiB'
|
return str(round(size / (1024.0 * 1024 * 1024), 1)) + ' GiB'
|
||||||
@ -181,6 +180,6 @@ def match_vm_name_with_special(vm, name):
|
|||||||
or @type:...'''
|
or @type:...'''
|
||||||
if name.startswith('@tag:'):
|
if name.startswith('@tag:'):
|
||||||
return name[len('@tag:'):] in vm.tags
|
return name[len('@tag:'):] in vm.tags
|
||||||
elif name.startswith('@type:'):
|
if name.startswith('@type:'):
|
||||||
return name[len('@type:'):] == vm.__class__.__name__
|
return name[len('@type:'):] == vm.__class__.__name__
|
||||||
return name == vm.name
|
return name == vm.name
|
||||||
|
@ -568,10 +568,9 @@ class VMProperty(qubes.property):
|
|||||||
if self.allow_none:
|
if self.allow_none:
|
||||||
super(VMProperty, self).__set__(instance, value)
|
super(VMProperty, self).__set__(instance, value)
|
||||||
return
|
return
|
||||||
else:
|
raise ValueError(
|
||||||
raise ValueError(
|
'Property {!r} does not allow setting to {!r}'.format(
|
||||||
'Property {!r} does not allow setting to {!r}'.format(
|
self.__name__, value))
|
||||||
self.__name__, value))
|
|
||||||
|
|
||||||
app = instance if isinstance(instance, qubes.Qubes) else instance.app
|
app = instance if isinstance(instance, qubes.Qubes) else instance.app
|
||||||
|
|
||||||
|
@ -147,12 +147,11 @@ class AdminVM(qubes.vm.BaseVM):
|
|||||||
if self.app.vmm.offline_mode:
|
if self.app.vmm.offline_mode:
|
||||||
# default value passed on xen cmdline
|
# default value passed on xen cmdline
|
||||||
return 4096
|
return 4096
|
||||||
else:
|
try:
|
||||||
try:
|
return self.app.vmm.libvirt_conn.getInfo()[1]
|
||||||
return self.app.vmm.libvirt_conn.getInfo()[1]
|
except libvirt.libvirtError as e:
|
||||||
except libvirt.libvirtError as e:
|
self.log.warning('Failed to get memory limit for dom0: %s', e)
|
||||||
self.log.warning('Failed to get memory limit for dom0: %s', e)
|
return 4096
|
||||||
return 4096
|
|
||||||
|
|
||||||
def verify_files(self):
|
def verify_files(self):
|
||||||
'''Always :py:obj:`True`
|
'''Always :py:obj:`True`
|
||||||
@ -181,7 +180,7 @@ class AdminVM(qubes.vm.BaseVM):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def icon_path(self):
|
def icon_path(self):
|
||||||
return None
|
pass
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def untrusted_qdb(self):
|
def untrusted_qdb(self):
|
||||||
|
@ -518,10 +518,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
except libvirt.libvirtError as e:
|
except libvirt.libvirtError as e:
|
||||||
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
||||||
return -1
|
return -1
|
||||||
else:
|
self.log.exception('libvirt error code: {!r}'.format(
|
||||||
self.log.exception('libvirt error code: {!r}'.format(
|
e.get_error_code()))
|
||||||
e.get_error_code()))
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
@qubes.stateless_property
|
@qubes.stateless_property
|
||||||
def stubdom_xid(self):
|
def stubdom_xid(self):
|
||||||
@ -1575,8 +1574,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
except libvirt.libvirtError as e:
|
except libvirt.libvirtError as e:
|
||||||
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
||||||
return 'Halted'
|
return 'Halted'
|
||||||
else:
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
libvirt_domain = self.libvirt_domain
|
libvirt_domain = self.libvirt_domain
|
||||||
if libvirt_domain is None:
|
if libvirt_domain is None:
|
||||||
@ -1587,19 +1585,17 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
# pylint: disable=line-too-long
|
# pylint: disable=line-too-long
|
||||||
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED:
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PAUSED:
|
||||||
return "Paused"
|
return "Paused"
|
||||||
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_CRASHED:
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_CRASHED:
|
||||||
return "Crashed"
|
return "Crashed"
|
||||||
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTDOWN:
|
||||||
return "Halting"
|
return "Halting"
|
||||||
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTOFF:
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_SHUTOFF:
|
||||||
return "Dying"
|
return "Dying"
|
||||||
elif libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED: # nopep8
|
if libvirt_domain.state()[0] == libvirt.VIR_DOMAIN_PMSUSPENDED: # nopep8
|
||||||
return "Suspended"
|
return "Suspended"
|
||||||
else:
|
if not self.is_fully_usable():
|
||||||
if not self.is_fully_usable():
|
return "Transient"
|
||||||
return "Transient"
|
return "Running"
|
||||||
|
|
||||||
return "Running"
|
|
||||||
|
|
||||||
return 'Halted'
|
return 'Halted'
|
||||||
except libvirt.libvirtError as e:
|
except libvirt.libvirtError as e:
|
||||||
@ -1639,8 +1635,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
except libvirt.libvirtError as e:
|
except libvirt.libvirtError as e:
|
||||||
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN:
|
||||||
return False
|
return False
|
||||||
else:
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
return bool(self.libvirt_domain.isActive())
|
return bool(self.libvirt_domain.isActive())
|
||||||
|
|
||||||
@ -1662,7 +1657,7 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
:py:obj:`False` otherwise.
|
:py:obj:`False` otherwise.
|
||||||
:rtype: bool
|
:rtype: bool
|
||||||
'''
|
'''
|
||||||
if self.xid < 0:
|
if self.xid < 0: # pylint: disable=comparison-with-callable
|
||||||
return False
|
return False
|
||||||
return os.path.exists('/var/run/qubes/qrexec.%s' % self.name)
|
return os.path.exists('/var/run/qubes/qrexec.%s' % self.name)
|
||||||
|
|
||||||
@ -1706,10 +1701,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
libvirt.VIR_ERR_INTERNAL_ERROR):
|
libvirt.VIR_ERR_INTERNAL_ERROR):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
else:
|
self.log.exception(
|
||||||
self.log.exception(
|
'libvirt error code: {!r}'.format(e.get_error_code()))
|
||||||
'libvirt error code: {!r}'.format(e.get_error_code()))
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
def get_mem_static_max(self):
|
def get_mem_static_max(self):
|
||||||
'''Get maximum memory available to VM.
|
'''Get maximum memory available to VM.
|
||||||
@ -1733,10 +1727,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
libvirt.VIR_ERR_INTERNAL_ERROR):
|
libvirt.VIR_ERR_INTERNAL_ERROR):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
else:
|
self.log.exception(
|
||||||
self.log.exception(
|
'libvirt error code: {!r}'.format(e.get_error_code()))
|
||||||
'libvirt error code: {!r}'.format(e.get_error_code()))
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
def get_cputime(self):
|
def get_cputime(self):
|
||||||
'''Get total CPU time burned by this domain since start.
|
'''Get total CPU time burned by this domain since start.
|
||||||
@ -1772,10 +1765,9 @@ class QubesVM(qubes.vm.mix.net.NetVMMixin, qubes.vm.BaseVM):
|
|||||||
libvirt.VIR_ERR_INTERNAL_ERROR):
|
libvirt.VIR_ERR_INTERNAL_ERROR):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
else:
|
self.log.exception(
|
||||||
self.log.exception(
|
'libvirt error code: {!r}'.format(e.get_error_code()))
|
||||||
'libvirt error code: {!r}'.format(e.get_error_code()))
|
raise
|
||||||
raise
|
|
||||||
|
|
||||||
# miscellanous
|
# miscellanous
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
# You should have received a copy of the GNU Lesser General Public
|
# You should have received a copy of the GNU Lesser General Public
|
||||||
# License along with this library; if not, see <https://www.gnu.org/licenses/>.
|
# License along with this library; if not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=no-else-return,useless-object-inheritance,try-except-raise
|
||||||
|
|
||||||
''' Qrexec policy parser and evaluator '''
|
''' Qrexec policy parser and evaluator '''
|
||||||
import enum
|
import enum
|
||||||
import itertools
|
import itertools
|
||||||
|
@ -33,7 +33,7 @@ import qubespolicy.rpcconfirmation
|
|||||||
import qubespolicy.policycreateconfirmation
|
import qubespolicy.policycreateconfirmation
|
||||||
# pylint: enable=wrong-import-position
|
# pylint: enable=wrong-import-position
|
||||||
|
|
||||||
class PolicyAgent(object):
|
class PolicyAgent:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
dbus = """
|
dbus = """
|
||||||
<node>
|
<node>
|
||||||
|
@ -72,12 +72,12 @@ def main(args=None):
|
|||||||
if not log.handlers:
|
if not log.handlers:
|
||||||
handler = logging.handlers.SysLogHandler(address='/dev/log')
|
handler = logging.handlers.SysLogHandler(address='/dev/log')
|
||||||
log.addHandler(handler)
|
log.addHandler(handler)
|
||||||
log_prefix = 'qrexec: {}: {} -> {}: '.format(
|
log_prefix = 'qrexec: {}: {} -> {}:'.format(
|
||||||
args.service_name, args.domain, args.target)
|
args.service_name, args.domain, args.target)
|
||||||
try:
|
try:
|
||||||
system_info = qubespolicy.get_system_info()
|
system_info = qubespolicy.get_system_info()
|
||||||
except qubespolicy.QubesMgmtException as e:
|
except qubespolicy.QubesMgmtException as e:
|
||||||
log.error(log_prefix + 'error getting system info: ' + str(e))
|
log.error('%s error getting system info: %s', log_prefix, str(e))
|
||||||
return 1
|
return 1
|
||||||
try:
|
try:
|
||||||
try:
|
try:
|
||||||
@ -130,13 +130,13 @@ def main(args=None):
|
|||||||
action.handle_user_response(True, response)
|
action.handle_user_response(True, response)
|
||||||
else:
|
else:
|
||||||
action.handle_user_response(False)
|
action.handle_user_response(False)
|
||||||
log.info(log_prefix + 'allowed to {}'.format(action.target))
|
log.info('%s allowed to %s', log_prefix, action.target)
|
||||||
action.execute(caller_ident)
|
action.execute(caller_ident)
|
||||||
except qubespolicy.PolicySyntaxError as e:
|
except qubespolicy.PolicySyntaxError as e:
|
||||||
log.error(log_prefix + 'error loading policy: ' + str(e))
|
log.error('%s error loading policy: %s', log_prefix, str(e))
|
||||||
return 1
|
return 1
|
||||||
except qubespolicy.AccessDenied as e:
|
except qubespolicy.AccessDenied as e:
|
||||||
log.info(log_prefix + 'denied: ' + str(e))
|
log.info('%s denied: %s', log_prefix, str(e))
|
||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
# pylint: enable=import-error
|
# pylint: enable=import-error
|
||||||
|
|
||||||
class PolicyCreateConfirmationWindow(object):
|
class PolicyCreateConfirmationWindow:
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
_source_file = pkg_resources.resource_filename('qubespolicy',
|
_source_file = pkg_resources.resource_filename('qubespolicy',
|
||||||
os.path.join('glade', "PolicyCreateConfirmationWindow.glade"))
|
os.path.join('glade', "PolicyCreateConfirmationWindow.glade"))
|
||||||
|
Loading…
Reference in New Issue
Block a user