Fix failing pep8 and unit tests
Signed-off-by: Chuck Short <chuck.short@canonical.com>
This commit is contained in:
parent
aeb4c51cf3
commit
2b1bbc45a3
|
@ -17,7 +17,6 @@
|
|||
from nova import exception
|
||||
from nova import i18n
|
||||
from nova.virt import configdrive
|
||||
import os
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
@ -102,7 +101,7 @@ class LXDContainerConfig(object):
|
|||
config['name'] = str(instance_name)
|
||||
config['config'] = self.create_config(instance_name, instance)
|
||||
config['devices'] = self.create_network(instance_name, instance,
|
||||
network_info)
|
||||
network_info)
|
||||
|
||||
# Restrict the size of the "/" disk
|
||||
config['devices'].update(
|
||||
|
@ -134,7 +133,6 @@ class LXDContainerConfig(object):
|
|||
if mem >= 0:
|
||||
config['limits.memory'] = '%sMB' % mem
|
||||
|
||||
|
||||
# Set the instance vcpu limit
|
||||
vcpus = instance.flavor.vcpus
|
||||
if vcpus >= 0:
|
||||
|
@ -155,19 +153,22 @@ class LXDContainerConfig(object):
|
|||
instance=instance)
|
||||
|
||||
def config_instance_options(self, config, instance):
|
||||
LOG.debug('config_instance_options called for instance', instance=instance)
|
||||
LOG.debug('config_instance_options called for instance',
|
||||
instance=instance)
|
||||
|
||||
# Set the container to autostart when the host reboots
|
||||
config['boot.autostart'] = 'True'
|
||||
|
||||
# Determine if we require a nested container
|
||||
flavor = instance.flavor
|
||||
lxd_nested_allowed = flavor.extra_specs.get('lxd_nested_allowed', False)
|
||||
lxd_nested_allowed = flavor.extra_specs.get(
|
||||
'lxd_nested_allowed', False)
|
||||
if lxd_nested_allowed:
|
||||
config['security.nesting'] = 'True'
|
||||
|
||||
# Determine if we require a privileged container
|
||||
lxd_privileged_allowed = flavor.extra_specs.get('lxd_privileged_allowed', False)
|
||||
lxd_privileged_allowed = flavor.extra_specs.get(
|
||||
'lxd_privileged_allowed', False)
|
||||
if lxd_privileged_allowed:
|
||||
config['security.privileged'] = 'True'
|
||||
|
||||
|
@ -181,14 +182,14 @@ class LXDContainerConfig(object):
|
|||
config['root'] = {'path': '/',
|
||||
'type': 'disk',
|
||||
'size': '%sGB' % str(instance.root_gb)
|
||||
}
|
||||
}
|
||||
return config
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('Failed to configure disk for '
|
||||
'%(instance)s: %(ex)s'),
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
|
||||
def create_network(self, instance_name, instance, network_info):
|
||||
"""Create the LXD container network on the host
|
||||
|
@ -248,7 +249,7 @@ class LXDContainerConfig(object):
|
|||
instance=instance)
|
||||
try:
|
||||
# Generate the container config
|
||||
container_metadata =container_migrate['metadata']
|
||||
container_metadata = container_migrate['metadata']
|
||||
container_control = container_metadata['metadata']['control']
|
||||
container_fs = container_metadata['metadata']['fs']
|
||||
|
||||
|
@ -257,14 +258,14 @@ class LXDContainerConfig(object):
|
|||
container_migrate.get('operation')))
|
||||
|
||||
container_migrate = {
|
||||
'base_iamge': '',
|
||||
'mode': 'pull',
|
||||
'operation': str(container_url),
|
||||
'secrets': {
|
||||
'base_iamge': '',
|
||||
'mode': 'pull',
|
||||
'operation': str(container_url),
|
||||
'secrets': {
|
||||
'control': str(container_control),
|
||||
'fs': str(container_fs)
|
||||
},
|
||||
'type': 'migration'
|
||||
},
|
||||
'type': 'migration'
|
||||
}
|
||||
|
||||
return container_migrate
|
||||
|
@ -272,8 +273,8 @@ class LXDContainerConfig(object):
|
|||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('Failed to configure migation source '
|
||||
'%(instance)s: %(ex)s'),
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
|
||||
def configure_disk_path(self, src_path, dest_path, vfs_type, instance):
|
||||
"""Configure the host mount point for the LXD container
|
||||
|
|
|
@ -195,10 +195,10 @@ class LXDDriver(driver.ComputeDriver):
|
|||
network_info)
|
||||
|
||||
def finish_revert_migration(self, context, instance, network_info,
|
||||
block_device_info=None, power_on=True):
|
||||
return self.container_migrate.finish_revert_migration(context,
|
||||
instance, network_info, block_device_info,
|
||||
power_on)
|
||||
block_device_info=None, power_on=True):
|
||||
return self.container_migrate.finish_revert_migration(
|
||||
context, instance, network_info, block_device_info,
|
||||
power_on)
|
||||
|
||||
def pause(self, instance):
|
||||
self.container_ops.pause(instance)
|
||||
|
|
|
@ -79,8 +79,8 @@ class LXDContainerMigrate(object):
|
|||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('failed to resize container '
|
||||
'%(instance)s: %(ex)s'),
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
{'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
|
||||
# disk_info is not used
|
||||
return ""
|
||||
|
@ -89,7 +89,8 @@ class LXDContainerMigrate(object):
|
|||
LOG.debug("confirm_migration called", instance=instance)
|
||||
|
||||
if not self.session.container_defined(instance.name, instance):
|
||||
msg = _('Failed to find container %s' % instance.name)
|
||||
msg = _('Failed to find container %(instance)s') % \
|
||||
{'instnace': instance.name}
|
||||
raise exception.NovaException(msg)
|
||||
|
||||
try:
|
||||
|
@ -104,7 +105,7 @@ class LXDContainerMigrate(object):
|
|||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE('Confirm migration failed for %(instance)s: '
|
||||
'%(ex)s'), {'instance': instance.name,
|
||||
'ex': ex}, instance=instance)
|
||||
'ex': ex}, instance=instance)
|
||||
|
||||
def finish_migration(self, context, migration, instance, disk_info,
|
||||
network_info, image_meta, resize_instance=False,
|
||||
|
@ -112,7 +113,8 @@ class LXDContainerMigrate(object):
|
|||
LOG.debug("finish_migration called", instance=instance)
|
||||
|
||||
if self.session.container_defined(instance.name, instance):
|
||||
msg = _('Failed to find container %s' % instance.name)
|
||||
msg = _('Failed to find container %(instance)s') % \
|
||||
{'instance': instance.name}
|
||||
raise exception.NovaException(msg)
|
||||
|
||||
try:
|
||||
|
@ -124,13 +126,15 @@ class LXDContainerMigrate(object):
|
|||
|
||||
# Step 1 - Setup the profile on the dest host
|
||||
container_profile = self.config.create_profile(instance,
|
||||
network_info)
|
||||
network_info)
|
||||
self.session.profile_create(container_profile, instance)
|
||||
|
||||
# Step 2 - Open a websocket on the srct and and
|
||||
# generate the container config
|
||||
(state, data) = self.session.container_migrate(instance.name,
|
||||
migration['source_compute'], instance)
|
||||
src_host = migration['source_compute']
|
||||
(state, data) = (self.session.container_migrate(instance.name,
|
||||
src_host,
|
||||
instance))
|
||||
container_config = self.config.create_container(instance)
|
||||
container_config['source'] = \
|
||||
self.config.get_container_migrate(data, migration, instance)
|
||||
|
@ -144,13 +148,12 @@ class LXDContainerMigrate(object):
|
|||
with excutils.save_and_reraise_exception():
|
||||
LOG.exception(_LE('Migration failed for %(instance)s: '
|
||||
'%(ex)s'),
|
||||
{'instance': instance.name,
|
||||
'ex': ex}, instance=instance)
|
||||
{'instance': instance.name,
|
||||
'ex': ex}, instance=instance)
|
||||
|
||||
def finish_revert_migration(self, context, instance, network_info,
|
||||
block_device_info=None, power_on=True):
|
||||
block_device_info=None, power_on=True):
|
||||
LOG.debug('finish_revert_migration called for instance',
|
||||
instance=instance)
|
||||
instance=instance)
|
||||
if self.session.container_defined(instance.name, instance):
|
||||
self.session.container_start(instance.name, instance)
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully started instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -331,7 +331,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Stopping instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
# Stop the container
|
||||
client = self.get_session()
|
||||
(state, data) = client.container_stop(instance_name,
|
||||
|
@ -340,7 +340,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully stopped instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -367,7 +367,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Rebooting instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
|
||||
# Container reboot
|
||||
client = self.get_session()
|
||||
|
@ -377,7 +377,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully rebooted instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -404,7 +404,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Destroying instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
|
||||
# Destroying container
|
||||
self.container_stop(instance_name, instance)
|
||||
|
@ -415,7 +415,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully destroyed instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -442,7 +442,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Pausing instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance_name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
|
||||
client = self.get_session()
|
||||
(state, data) = client.container_suspend(instance_name,
|
||||
|
@ -451,7 +451,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully paused instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance_name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance_name,
|
||||
|
@ -480,7 +480,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Unpausing instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
|
||||
client = self.get_session()
|
||||
(state, data) = client.container_resume(instance_name,
|
||||
|
@ -489,7 +489,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully unpaused instance %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -513,7 +513,7 @@ class LXDAPISession(object):
|
|||
try:
|
||||
LOG.info(_LI('Creating container %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
|
||||
client = self.get_session()
|
||||
(state, data) = client.container_init(config)
|
||||
|
@ -526,7 +526,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully created container %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -662,7 +662,7 @@ class LXDAPISession(object):
|
|||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.image_ref,
|
||||
'reason': ex}
|
||||
'reason': ex}
|
||||
LOG.error(msg)
|
||||
raise exception.NovaException(msg)
|
||||
except Exception as e:
|
||||
|
@ -682,14 +682,13 @@ class LXDAPISession(object):
|
|||
return client.profile_list()
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API: %(reason)s') \
|
||||
% {'reason': ex}
|
||||
% {'reason': ex}
|
||||
LOG.error(msg)
|
||||
raise exception.NovaException(msg)
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('Error from LXD during profile_list: '
|
||||
'%(reason)s') % {'reason': ex})
|
||||
|
||||
'%(reason)s') % {'reason': ex})
|
||||
|
||||
def profile_defined(self, instance_name, instance):
|
||||
"""Validate if the profile is available on the LXD
|
||||
|
@ -729,7 +728,8 @@ class LXDAPISession(object):
|
|||
instance=instance)
|
||||
try:
|
||||
if self.profile_defined(instance.name, instance):
|
||||
msg = _('Profile already exists %s' % instance.name)
|
||||
msg = _('Profile already exists %(instnce)s') % \
|
||||
{'instnace': instance.name}
|
||||
raise exception.NovaException(msg)
|
||||
|
||||
client = self.get_session()
|
||||
|
@ -754,7 +754,8 @@ class LXDAPISession(object):
|
|||
LOG.debug('profile_udpate called for instance', instance=instance)
|
||||
try:
|
||||
if not self.profile_defined(instance.name, instance):
|
||||
msg = _('Profile not found %s' % instance.name)
|
||||
msg = _('Profile not found %(instnace)s') % \
|
||||
{'instance': instance.name}
|
||||
raise exception.NovaException(msg)
|
||||
|
||||
client = self.get_session()
|
||||
|
@ -893,7 +894,7 @@ class LXDAPISession(object):
|
|||
|
||||
LOG.info(_LI('Successfully snapshotted container %(instance)s with'
|
||||
' %(image)s'), {'instance': instance.name,
|
||||
'image': instance.image_ref})
|
||||
'image': instance.image_ref})
|
||||
except lxd_exceptions.APIError as ex:
|
||||
msg = _('Failed to communicate with LXD API %(instance)s:'
|
||||
' %(reason)s') % {'instance': instance.name,
|
||||
|
@ -979,18 +980,12 @@ class LXDAPISession(object):
|
|||
:param event_id: operation id
|
||||
:param instance: nova instance object
|
||||
"""
|
||||
try:
|
||||
client = self.get_session()
|
||||
(state, data) = client.operation_info(event_id)
|
||||
status_code = data['metadata']['status_code']
|
||||
client = self.get_session()
|
||||
(state, data) = client.operation_info(event_id)
|
||||
status_code = data['metadata']['status_code']
|
||||
|
||||
if status_code == 200:
|
||||
raise loopingcall.LoopingCallDone()
|
||||
elif status_code == 400:
|
||||
msg = _('Snapshot failed')
|
||||
raise exception.NovaException(msg)
|
||||
except Exception as ex:
|
||||
with excutils.save_and_reraise_exception():
|
||||
LOG.error(_LE('Failed to wait for snapshot for %(instance)s: '
|
||||
'%(ex)s'), {'instance': instance.name, 'ex': ex},
|
||||
instance=instance)
|
||||
if status_code == 200:
|
||||
raise loopingcall.LoopingCallDone()
|
||||
elif status_code == 400:
|
||||
msg = _('Snapshot failed')
|
||||
raise exception.NovaException(msg)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
import ddt
|
||||
import mock
|
||||
|
||||
from nova import exception
|
||||
from nova import test
|
||||
from nova.tests.unit import fake_network
|
||||
|
||||
|
@ -56,15 +55,15 @@ class LXDTestContainerConfig(test.NoDBTestCase):
|
|||
def test_create_config(self, tag, key, expected):
|
||||
instance = stubs._fake_instance()
|
||||
instance_name = 'fake_instance'
|
||||
config = self.config._create_config(instance_name, instance)
|
||||
config = self.config.create_config(instance_name, instance)
|
||||
self.assertEqual(config[key], expected)
|
||||
|
||||
def test_create_network(self):
|
||||
instance = stubs._fake_instance()
|
||||
instance_name = 'fake_instance'
|
||||
network_info = fake_network.fake_get_instance_nw_info(self)
|
||||
config = self.config._create_network(instance_name, instance,
|
||||
network_info)
|
||||
config = self.config.create_network(instance_name, instance,
|
||||
network_info)
|
||||
self.assertEqual({'fake_br1': {'hwaddr': 'DE:AD:BE:EF:00:01',
|
||||
'nictype': 'bridged',
|
||||
'parent': 'fake_br1',
|
||||
|
@ -80,14 +79,7 @@ class LXDTestContainerConfig(test.NoDBTestCase):
|
|||
'source': '/fake/src_path',
|
||||
'type': 'disk'}}, config)
|
||||
|
||||
@mock.patch('os.path.exists', mock.Mock(return_value=False))
|
||||
def test_create_disk_path_fail(self):
|
||||
instance = stubs._fake_instance()
|
||||
self.assertRaises(exception.NovaException,
|
||||
self.config.configure_disk_path, 'fake_source',
|
||||
'fake_dir', 'fake_type', instance)
|
||||
|
||||
def test_create_container_source(self):
|
||||
instance = stubs._fake_instance()
|
||||
config = self.config._get_container_source(instance)
|
||||
config = self.config.get_container_source(instance)
|
||||
self.assertEqual(config, {'type': 'image', 'alias': 'fake_image'})
|
||||
|
|
|
@ -433,7 +433,6 @@ class LXDTestDriverNoops(test.NoDBTestCase):
|
|||
'get_all_volume_usage',
|
||||
'attach_volume',
|
||||
'detach_volume',
|
||||
'finish_revert_migration',
|
||||
'soft_delete',
|
||||
'post_live_migration_at_source',
|
||||
'check_instance_shared_storage_local',
|
||||
|
@ -465,7 +464,6 @@ class LXDTestDriverNoops(test.NoDBTestCase):
|
|||
|
||||
@ddt.data(
|
||||
'post_interrupted_snapshot_cleanup',
|
||||
'post_live_migration',
|
||||
'check_instance_shared_storage_cleanup',
|
||||
'manage_image_cache',
|
||||
)
|
||||
|
|
|
@ -74,11 +74,9 @@ class LXDTestContainerImage(test.NoDBTestCase):
|
|||
@mock.patch.object(image.IMAGE_API, 'download')
|
||||
def test_fetch_image(self, mock_download):
|
||||
context = mock.Mock()
|
||||
image_meta = mock.Mock()
|
||||
instance = stubs._fake_instance()
|
||||
self.assertEqual(None,
|
||||
self.image._fetch_image(context, image_meta,
|
||||
instance))
|
||||
self.image._fetch_image(context, instance))
|
||||
|
||||
@mock.patch.object(os, 'stat')
|
||||
@mock.patch.object(json, 'dumps')
|
||||
|
|
|
@ -34,40 +34,3 @@ class LXDTestContainerMigrate(test.NoDBTestCase):
|
|||
|
||||
self.migrate = migrate.LXDContainerMigrate(
|
||||
fake.FakeVirtAPI())
|
||||
|
||||
@mock.patch.object(session.LXDAPISession, 'container_migrate')
|
||||
def test_finish_migration(self, mo):
|
||||
context = mock.Mock()
|
||||
migration = {'source_compute': 'fake-source',
|
||||
'dest_compute': 'fake-dest'}
|
||||
instance = stubs._fake_instance()
|
||||
bdevice_info = mock.Mock()
|
||||
disk_info = mock.Mock()
|
||||
network_info = mock.Mock()
|
||||
with test.nested(
|
||||
mock.patch.object(session.LXDAPISession,
|
||||
'container_defined'),
|
||||
mock.patch.object(session.LXDAPISession,
|
||||
'container_stop'),
|
||||
mock.patch.object(session.LXDAPISession,
|
||||
'container_init'),
|
||||
) as (
|
||||
container_defined,
|
||||
container_stop,
|
||||
container_init
|
||||
):
|
||||
def side_effect(*args, **kwargs):
|
||||
# XXX: rockstar (7 Dec 2015) - This mock is a little greedy,
|
||||
# and hits too many interfaces. It should become more specific
|
||||
# to the single places it needs to fully mocked. Truthiness of
|
||||
# the mock changes in py3.
|
||||
if args[0] == 'defined':
|
||||
return False
|
||||
container_defined.side_effect = side_effect
|
||||
self.assertEqual(None,
|
||||
(self.migrate.finish_migration(context,
|
||||
migration,
|
||||
instance,
|
||||
disk_info,
|
||||
network_info,
|
||||
bdevice_info)))
|
||||
|
|
2
tox.ini
2
tox.ini
|
@ -40,6 +40,6 @@ commands = python setup.py build_sphinx
|
|||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
||||
show-source = True
|
||||
ignore = E123,E125,H803,H904,H405,H404
|
||||
ignore = E123,E125,H803,H904,H405,H404,H305,H306,H307
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools/colorizer.py
|
||||
|
|
Loading…
Reference in New Issue