rework imports: import module instead of object

rework imports: import module instead of object
http://docs.openstack.org/developer/hacking/#imports

Move retry to decorators and warn, if called from old place
Fix __deepcopy__ special method

Change-Id: Ib958ea40cffbc508e3ab179bce9b300423b2fac1
This commit is contained in:
Alexey Stepanov 2016-09-21 15:07:55 +03:00
parent 92076644eb
commit aa6bc9caf1
44 changed files with 237 additions and 201 deletions

View File

@ -15,13 +15,12 @@
import os
import time
import logging.config
from devops.settings import LOGS_DIR
from devops.settings import LOGS_SIZE
from devops import settings
__version__ = '3.0.2'
if not os.path.exists(LOGS_DIR):
os.makedirs(LOGS_DIR)
if not os.path.exists(settings.LOGS_DIR):
os.makedirs(settings.LOGS_DIR)
LOGGER_SETTINGS = {
'version': 1,
@ -46,10 +45,10 @@ LOGGER_SETTINGS = {
'class': 'logging.handlers.RotatingFileHandler',
'level': 'DEBUG',
'formatter': 'default',
'filename': os.path.join(LOGS_DIR, 'devops.log'),
'filename': os.path.join(settings.LOGS_DIR, 'devops.log'),
'encoding': 'utf8',
'mode': 'a',
'maxBytes': LOGS_SIZE,
'maxBytes': settings.LOGS_SIZE,
'backupCount': 5,
},
},

View File

@ -111,7 +111,8 @@ class DevopsEnvironment(object):
raise error.DevopsError(
'Environment {!r} has no admin node'.format(self._env.name))
def get_admin_login(self):
@staticmethod
def get_admin_login():
return settings.SSH_CREDENTIALS['login']
def get_admin_ip(self):

View File

@ -144,9 +144,6 @@ class IpmiClient(object):
args = " ".join(cmd).split(" ")
ipmi_cmd.extend(args)
out = None
err = None
code = None
args = " ".join(ipmi_cmd).split(" ")
try:

View File

@ -30,8 +30,8 @@ import netaddr
from devops.driver.libvirt import libvirt_xml_builder as builder
from devops import error
from devops.helpers import cloud_image_settings
from devops.helpers import decorators
from devops.helpers import helpers
from devops.helpers.retry import retry
from devops.helpers import scancodes
from devops.helpers import subprocess_runner
from devops import logger
@ -471,7 +471,7 @@ class LibvirtL2NetworkDevice(network.L2NetworkDevice):
"""
return self._libvirt_network.isActive()
@retry(libvirt.libvirtError, delay=3)
@decorators.retry(libvirt.libvirtError, delay=3)
def define(self):
# define filter first
if self.driver.enable_nwfilters:
@ -541,7 +541,7 @@ class LibvirtL2NetworkDevice(network.L2NetworkDevice):
def start(self):
self.create()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def create(self, *args, **kwargs):
if not self.is_active():
self._libvirt_network.create()
@ -580,11 +580,11 @@ class LibvirtL2NetworkDevice(network.L2NetworkDevice):
except error.DevopsCalledProcessError:
pass
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def destroy(self):
self._libvirt_network.destroy()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def remove(self, *args, **kwargs):
if self.uuid:
if self.exists():
@ -620,7 +620,7 @@ class LibvirtL2NetworkDevice(network.L2NetworkDevice):
else:
raise
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def iface_define(self, name, ip=None, prefix=None, vlanid=None):
"""Define bridge interface
@ -634,7 +634,7 @@ class LibvirtL2NetworkDevice(network.L2NetworkDevice):
builder.LibvirtXMLBuilder.build_iface_xml(
name, ip, prefix, vlanid))
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def iface_undefine(self, iface_name):
"""Start interface
@ -721,7 +721,7 @@ class LibvirtVolume(volume.Volume):
logger.error("Volume not found by UUID: {}".format(self.uuid))
return None
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def define(self):
# Generate libvirt volume name
if self.node:
@ -796,7 +796,7 @@ class LibvirtVolume(volume.Volume):
if self.source_image is not None:
self.upload(self.source_image, capacity)
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def remove(self, *args, **kwargs):
if self.uuid:
if self.exists():
@ -819,7 +819,7 @@ class LibvirtVolume(volume.Volume):
warnings.warn(msg, DeprecationWarning)
logger.debug(msg)
@retry(libvirt.libvirtError, count=2)
@decorators.retry(libvirt.libvirtError, count=2)
def upload(self, path, capacity=0):
def chunk_render(_, _size, _fd):
return _fd.read(_size)
@ -989,7 +989,7 @@ class LibvirtNode(node.Node):
continue
self._libvirt_node.sendKey(0, 0, list(key_code), len(key_code), 0)
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def define(self):
"""Define node
@ -1075,18 +1075,18 @@ class LibvirtNode(node.Node):
def start(self):
self.create()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def create(self, *args, **kwargs):
if not self.is_active():
self._libvirt_node.create()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def destroy(self, *args, **kwargs):
if self.is_active():
self._libvirt_node.destroy()
super(LibvirtNode, self).destroy()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def remove(self, *args, **kwargs):
if self.uuid:
if self.exists():
@ -1238,7 +1238,7 @@ class LibvirtNode(node.Node):
libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_REDEFINE |
libvirt.VIR_DOMAIN_SNAPSHOT_CREATE_CURRENT)
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def snapshot(self, name=None, force=False, description=None,
disk_only=False, external=False):
super(LibvirtNode, self).snapshot()
@ -1393,7 +1393,7 @@ class LibvirtNode(node.Node):
uuid=snap_disk_file).backing_store
disk.save()
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def _node_revert_snapshot_recreate_disks(self, name):
"""Recreate snapshot disks."""
snapshot = self._get_snapshot(name)
@ -1468,7 +1468,7 @@ class LibvirtNode(node.Node):
# Create new snapshot
self.snapshot(name=revert_name, external=True)
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def revert(self, name=None):
"""Method to revert node in state from snapshot
@ -1525,7 +1525,7 @@ class LibvirtNode(node.Node):
snapshots = self._libvirt_node.listAllSnapshots(0)
return [Snapshot(snap) for snap in snapshots]
@retry(libvirt.libvirtError)
@decorators.retry(libvirt.libvirtError)
def erase_snapshot(self, name):
if self.has_snapshot(name):

View File

@ -17,7 +17,7 @@ import hashlib
import six
from devops.helpers.xmlgenerator import XMLGenerator
from devops.helpers import xmlgenerator
class LibvirtXMLBuilder(object):
@ -49,7 +49,7 @@ class LibvirtXMLBuilder(object):
if addresses is None:
addresses = []
network_xml = XMLGenerator('network')
network_xml = xmlgenerator.XMLGenerator('network')
network_xml.name(cls._crop_name(network_name))
if forward == 'bridge':
@ -98,7 +98,7 @@ class LibvirtXMLBuilder(object):
:type volume: Volume
:rtype : String
"""
volume_xml = XMLGenerator('volume')
volume_xml = xmlgenerator.XMLGenerator('volume')
volume_xml.name(cls._crop_name(name))
volume_xml.capacity(str(capacity))
with volume_xml.target:
@ -120,7 +120,7 @@ class LibvirtXMLBuilder(object):
:type name: String
:type description: String
"""
xml_builder = XMLGenerator('domainsnapshot')
xml_builder = xmlgenerator.XMLGenerator('domainsnapshot')
if name is not None:
xml_builder.name(name)
if description is not None:
@ -204,7 +204,7 @@ class LibvirtXMLBuilder(object):
:type rule: dict
:rtype : String
"""
filter_xml = XMLGenerator('filter', name=name)
filter_xml = xmlgenerator.XMLGenerator('filter', name=name)
if uuid:
filter_xml.uuid(uuid)
if rule:
@ -222,7 +222,7 @@ class LibvirtXMLBuilder(object):
:type rule: dict
:rtype : String
"""
filter_xml = XMLGenerator('filter', name=name)
filter_xml = xmlgenerator.XMLGenerator('filter', name=name)
filter_xml.filterref(filter=filterref)
if uuid:
filter_xml.uuid(uuid)
@ -243,13 +243,15 @@ class LibvirtXMLBuilder(object):
:type emulator: String
:rtype : String
"""
node_xml = XMLGenerator("domain", type=hypervisor)
node_xml = xmlgenerator.XMLGenerator("domain", type=hypervisor)
node_xml.name(cls._crop_name(name))
if acpi:
with node_xml.features:
# pylint: disable=pointless-statement
# noinspection PyStatementEffect
node_xml.acpi
# pylint: enable=pointless-statement
cpu_args = {}
if use_host_cpu:
@ -270,8 +272,10 @@ class LibvirtXMLBuilder(object):
if use_hugepages:
with node_xml.memoryBacking:
# pylint: disable=pointless-statement
# noinspection PyStatementEffect
node_xml.hugepages
# pylint: enable=pointless-statement
node_xml.clock(offset='utc')
with node_xml.clock.timer(name='rtc',
@ -341,9 +345,10 @@ class LibvirtXMLBuilder(object):
iface_type = 'ethernet'
iface_name = "{0}".format(name)
interface_xml = XMLGenerator('interface',
type=iface_type,
name=iface_name)
interface_xml = xmlgenerator.XMLGenerator(
'interface',
type=iface_type,
name=iface_name)
interface_xml.start(mode="onboot")
if vlanid:

View File

@ -19,7 +19,7 @@ from devops import logger
def generate_cloud_image_settings(cloud_image_settings_path, meta_data_path,
user_data_path, admin_network,
user_data_path, admin_network,
interface_name, admin_ip, admin_netmask,
gateway,
hostname,

View File

@ -15,7 +15,12 @@
from __future__ import unicode_literals
import functools
import inspect
import threading
import time
from devops import error
from devops import logger
def threaded(name=None, started=False, daemon=False):
@ -56,3 +61,59 @@ def threaded(name=None, started=False, daemon=False):
return real_decorator(func)
return real_decorator
def retry(exception, count=10, delay=1):
"""Retry decorator
Retries to run decorated method with the same parameters in case of
thrown :exception:
:type exception: class
:param exception: exception class
:type count: int
:param count: retry count
:type delay: int
:param delay: delay between retries in seconds
:rtype: function
"""
def decorator(func):
if inspect.ismethod(func):
full_name = '{}:{}.{}'.format(
inspect.getmodule(func.im_class).__name__,
func.im_class.__name__,
func.__name__)
elif inspect.isfunction(func):
full_name = '{}.{}'.format(
inspect.getmodule(func).__name__,
func.__name__)
else:
raise error.DevopsException(
'Wrong func parameter type {!r}'.format(func))
@functools.wraps(func)
def wrapper(*args, **kwargs):
i = 0
while True:
try:
return func(*args, **kwargs)
except exception as e:
i += 1
if i >= count:
raise
logger.debug(
'Exception {!r} while running {!r}. '
'Waiting {} seconds.'.format(e, func.__name__, delay),
exc_info=True) # logs traceback
time.sleep(delay)
arg_str = ', '.join((
', '.join(map(repr, args)),
', '.join('{}={!r}'.format(k, v) for k, v in kwargs),
))
logger.debug('Retrying {}({})'.format(full_name, arg_str))
return wrapper
return decorator

View File

@ -181,8 +181,8 @@ def get_private_keys(env):
logger.warning(msg)
warnings.warn(msg, DeprecationWarning)
from devops.client import DevopsClient
denv = DevopsClient().get_env(env.name)
from devops import client
denv = client.DevopsClient().get_env(env.name)
return denv.get_private_keys()
@ -196,8 +196,8 @@ def get_admin_remote(
logger.warning(msg)
warnings.warn(msg, DeprecationWarning)
from devops.client import DevopsClient
denv = DevopsClient().get_env(env.name)
from devops import client
denv = client.DevopsClient().get_env(env.name)
return denv.get_admin_remote(login=login, password=password)
@ -225,8 +225,8 @@ def get_admin_ip(env):
logger.warning(msg)
warnings.warn(msg, DeprecationWarning)
from devops.client import DevopsClient
denv = DevopsClient().get_env(env.name)
from devops import client
denv = client.DevopsClient().get_env(env.name)
return denv.get_admin_ip()

View File

@ -20,12 +20,12 @@ import paramiko
import six
from devops import error
from devops.helpers import decorators
from devops.helpers import helpers
from devops.helpers import retry
from devops import logger
@retry.retry(paramiko.SSHException, count=3, delay=60)
@decorators.retry(paramiko.SSHException, count=3, delay=60)
def sync_time(env, node_names, skip_sync=False):
"""Synchronize time on nodes
@ -39,8 +39,8 @@ def sync_time(env, node_names, skip_sync=False):
'sync_time is deprecated. Use DevopsClient.sync_time instead',
DeprecationWarning)
from devops.client import DevopsClient
denv = DevopsClient().get_env(env.name)
from devops import client
denv = client.DevopsClient().get_env(env.name)
return denv.sync_time(node_names=node_names, skip_sync=skip_sync)

View File

@ -12,65 +12,14 @@
# License for the specific language governing permissions and limitations
# under the License.
import functools
import inspect
import time
import warnings
from devops import error
from devops.helpers.decorators import retry
from devops import logger
def retry(exception, count=10, delay=1):
"""Retry decorator
msg = 'devops.helpers.retry.retry was moved to devops.helpers.decorators.retry'
logger.critical(msg)
warnings.warn(msg, DeprecationWarning)
Retries to run decorated method with the same parameters in case of
thrown :exception:
:type exception: class
:param exception: exception class
:type count: int
:param count: retry count
:type delay: int
:param delay: delay between retries in seconds
:rtype: function
"""
def decorator(func):
if inspect.ismethod(func):
full_name = '{}:{}.{}'.format(
inspect.getmodule(func.im_class).__name__,
func.im_class.__name__,
func.__name__)
elif inspect.isfunction(func):
full_name = '{}.{}'.format(
inspect.getmodule(func).__name__,
func.__name__)
else:
raise error.DevopsException(
'Wrong func parameter type {!r}'.format(func))
@functools.wraps(func)
def wrapper(*args, **kwargs):
i = 0
while True:
try:
return func(*args, **kwargs)
except exception as e:
i += 1
if i >= count:
raise
logger.debug(
'Exception {!r} while running {!r}. '
'Waiting {} seconds.'.format(e, func.__name__, delay),
exc_info=True) # logs traceback
time.sleep(delay)
arg_str = ', '.join((
', '.join(map(repr, args)),
', '.join('{}={!r}'.format(k, v) for k, v in kwargs),
))
logger.debug('Retrying {}({})'.format(full_name, arg_str))
return wrapper
return decorator
__all__ = ['retry']

View File

@ -30,7 +30,6 @@ from devops import error
from devops.helpers import decorators
from devops.helpers import exec_result
from devops.helpers import proc_enums
from devops.helpers import retry
from devops import logger
@ -157,7 +156,15 @@ class SSHAuth(object):
def __eq__(self, other):
return hash(self) == hash(other)
def __deepcopy__(self):
def __deepcopy__(self, memo):
return self.__class__(
username=self.username,
password=self.__password,
key=self.__key,
keys=self.__keys.copy()
)
def copy(self):
return self.__class__(
username=self.username,
password=self.__password,
@ -165,9 +172,6 @@ class SSHAuth(object):
keys=self.__keys
)
def copy(self):
return self.__deepcopy__()
def __repr__(self):
_key = (
None if self.__key is None else
@ -485,7 +489,7 @@ class SSHClient(six.with_metaclass(_MemorizedSSH, object)):
"""
return self.__ssh
@retry.retry(paramiko.SSHException, count=3, delay=3)
@decorators.retry(paramiko.SSHException, count=3, delay=3)
def __connect(self):
"""Main method for connection open"""
with self.lock:

View File

@ -423,7 +423,9 @@ def _calculate_numa(numa_nodes, vcpu, memory, name):
name))
for x in range(numa_nodes):
# List of cpu IDs for the numa node
# pylint: disable=range-builtin-not-iterating
cpus = range(x * cpus_per_numa, (x + 1) * cpus_per_numa)
# pylint: enable=range-builtin-not-iterating
cell = {
'cpus': ','.join(map(str, cpus)),
'memory': memory_per_numa,

View File

@ -25,6 +25,7 @@ try:
except AppRegistryNotReady:
django.setup()
# pylint: disable=wrong-import-position
from devops.models.driver import Driver
from devops.models.environment import Environment
from devops.models.group import Group
@ -36,6 +37,7 @@ from devops.models.network import L2NetworkDevice
from devops.models.node import Node
from devops.models.volume import Volume
from devops.models.volume import DiskDevice
# pylint: enable=wrong-import-position
__all__ = ['Driver', 'Environment', 'Group', 'Address', 'Interface',
'AddressPool', 'NetworkPool', 'L2NetworkDevice', 'Node',

View File

@ -105,9 +105,11 @@ class ParamedModelType(ModelBase):
obj = super(ParamedModelType, cls).__call__(*args, **kwargs)
# noinspection PyProtectedMember
if obj._class:
# we store actual class name in _class attribute
# so use it to load required class
# noinspection PyProtectedMember
Cls = loader.load_class(obj._class)
# replace base class
obj.__class__ = Cls
@ -273,6 +275,7 @@ class ParamedModelQuerySet(query.QuerySet):
def __get_all_field_names(self):
field_names = set()
# noinspection PyProtectedMember
_meta = self.model._meta
fields = _meta.get_fields()
for field in fields:
@ -282,6 +285,7 @@ class ParamedModelQuerySet(query.QuerySet):
field.related_model is None:
continue
# Relations to child proxy models should not be included.
# noinspection PyProtectedMember
if field.model != _meta.model and\
field.model._meta.concrete_model == _meta.concrete_model:
continue
@ -302,7 +306,7 @@ class ParamedModelQuerySet(query.QuerySet):
# Fix deprecated code usage from django
field_names = self.__get_all_field_names()
for param in kwargs.keys():
for param in kwargs:
first_subparam = param.split('__')[0]
if first_subparam not in field_names:
kwargs_for_params[param] = kwargs[param]

View File

@ -270,14 +270,14 @@ class Environment(base.BaseModel):
'describe_environment is deprecated in favor of '
'DevopsClient.create_env_from_config', DeprecationWarning)
from devops.client import DevopsClient
client = DevopsClient()
from devops import client
dclient = client.DevopsClient()
template = settings.DEVOPS_SETTINGS_TEMPLATE
if template:
return client.create_env_from_config(template)
return dclient.create_env_from_config(template)
else:
return client.create_env()
return dclient.create_env()
@classmethod
def create_environment(cls, full_config):
@ -358,8 +358,8 @@ class Environment(base.BaseModel):
logger.warning(msg)
warnings.warn(msg, DeprecationWarning)
from devops.client import DevopsClient
env = DevopsClient().get_env(self.name)
from devops import client
env = client.DevopsClient().get_env(self.name)
return env.get_admin_remote(login=login, password=password)
# LEGACY, for fuel-qa compatibility
@ -372,8 +372,8 @@ class Environment(base.BaseModel):
logger.warning(msg)
warnings.warn(msg, DeprecationWarning)
from devops.client import DevopsClient
env = DevopsClient().get_env(self.name)
from devops import client
env = client.DevopsClient().get_env(self.name)
return ssh_client.SSHClient(
ip,
auth=ssh_client.SSHAuth(

View File

@ -77,6 +77,7 @@ class ExtendableNodeType(base.ParamedModelType):
METHOD_NAMES = ('define', 'start', 'destroy', 'remove')
# pylint: disable=bad-mcs-classmethod-argument
# noinspection PyMethodParameters
def __new__(cls, name, bases, attrs):
super_new = super(ExtendableNodeType, cls).__new__
@ -101,6 +102,8 @@ class ExtendableNodeType(base.ParamedModelType):
return super_new(cls, name, bases, attrs)
# pylint: enable=bad-mcs-classmethod-argument
@staticmethod
def _install_ext_hook(node_method):
"""Installs pre/post hooks on Node method"""

View File

@ -13,7 +13,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.helpers.helpers import wait_tcp
from devops.helpers import helpers
from devops import logger
from devops import settings
@ -28,9 +28,10 @@ class NodeExtension(object):
self.node.start()
ip = self.node.get_ip_address_by_network_name(
settings.SSH_CREDENTIALS['admin_network'])
wait_tcp(host=ip, port=self.node.ssh_port,
timeout=self.node.bootstrap_timeout,
timeout_msg='Failed to bootstrap centos master')
helpers.wait_tcp(
host=ip, port=self.node.ssh_port,
timeout=self.node.bootstrap_timeout,
timeout_msg='Failed to bootstrap centos master')
logger.info('Centos cloud image bootstrap complete')
def deploy_wait(self):

View File

@ -14,9 +14,8 @@
from django.conf import settings
from devops.error import DevopsError
from devops.helpers.helpers import wait_ssh_cmd
from devops.helpers.helpers import wait_tcp
from devops import error
from devops.helpers import helpers
class NodeExtension(object):
@ -27,7 +26,7 @@ class NodeExtension(object):
def _start_setup(self):
if self.node.kernel_cmd is None:
raise DevopsError('kernel_cmd is None')
raise error.DevopsError('kernel_cmd is None')
self.node.start()
self.send_kernel_keys(self.node.kernel_cmd)
@ -57,8 +56,9 @@ class NodeExtension(object):
self._start_setup()
ip = self.node.get_ip_address_by_network_name(
settings.SSH_CREDENTIALS['admin_network'])
wait_tcp(host=ip, port=self.node.ssh_port,
timeout=self.node.bootstrap_timeout)
helpers.wait_tcp(
host=ip, port=self.node.ssh_port,
timeout=self.node.bootstrap_timeout)
def deploy_wait(self):
ip = self.node.get_ip_address_by_network_name(
@ -66,12 +66,13 @@ class NodeExtension(object):
if self.node.deploy_check_cmd is None:
self.node.deploy_check_cmd = self.get_deploy_check_cmd()
self.node.save()
wait_ssh_cmd(host=ip,
port=self.node.ssh_port,
check_cmd=self.node.deploy_check_cmd,
username=settings.SSH_CREDENTIALS['login'],
password=settings.SSH_CREDENTIALS['password'],
timeout=self.node.deploy_timeout)
helpers.wait_ssh_cmd(
host=ip,
port=self.node.ssh_port,
check_cmd=self.node.deploy_check_cmd,
username=settings.SSH_CREDENTIALS['login'],
password=settings.SSH_CREDENTIALS['password'],
timeout=self.node.deploy_timeout)
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',
wait_for_external_config='yes'):

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 4.1"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 5.0"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 5.1"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 6.0"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 6.1"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 7.0"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel 8.0"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -12,11 +12,10 @@
# License for the specific language governing permissions and limitations
# under the License.
from devops.models.node_ext.fuel_master import \
NodeExtension as NodeExtensionBase
from devops.models.node_ext import fuel_master
class NodeExtension(NodeExtensionBase):
class NodeExtension(fuel_master.NodeExtension):
"""Extension for Fuel Mitaka"""
def get_kernel_cmd(self, boot_from='cdrom', iface='enp0s3',

View File

@ -46,7 +46,8 @@ class Shell(object):
command_method = getattr(self, command_name)
command_method()
def print_table(self, headers, columns):
@staticmethod
def print_table(headers, columns):
if not columns:
return
print(tabulate.tabulate(columns, headers=headers,
@ -161,7 +162,8 @@ class Shell(object):
print('Time synchronization is starting')
self.do_time_sync()
def do_version(self):
@staticmethod
def do_version():
print(devops.__version__)
def do_create(self):

View File

@ -12,7 +12,9 @@
# License for the specific language governing permissions and limitations
# under the License.
# pylint: disable=wildcard-import, unused-wildcard-import
from devops.settings import * # noqa
# pylint: enable=wildcard-import, unused-wildcard-import
# make tests faster
DATABASES['default'] = {'ENGINE': 'django.db.backends.sqlite3'}

View File

@ -123,8 +123,10 @@ class TestLibvirtNodeSnapshot(TestLibvirtNodeSnapshotBase):
assert snapshot.memory_file is None
assert snapshot.name == 'test1'
with self.assertRaises(libvirt.libvirtError):
# pylint: disable=pointless-statement
# noinspection PyStatementEffect
snapshot.parent
# pylint: enable=pointless-statement
assert snapshot.state == 'shutoff'
rxml = r"""<domainsnapshot>

View File

@ -27,7 +27,9 @@ class ThreadedTest(unittest.TestCase):
@decorators.threaded
def func_test():
pass
# pylint: disable=assignment-from-no-return
test_thread = func_test()
# pylint: enable=assignment-from-no-return
self.assertEqual(test_thread.name, 'Threaded func_test')
self.assertFalse(test_thread.daemon)
self.assertFalse(test_thread.isAlive())
@ -37,7 +39,9 @@ class ThreadedTest(unittest.TestCase):
def func_test():
pass
# pylint: disable=assignment-from-no-return
test_thread = func_test()
# pylint: enable=assignment-from-no-return
self.assertEqual(test_thread.name, 'Threaded func_test')
self.assertFalse(test_thread.daemon)
self.assertFalse(test_thread.isAlive())
@ -47,7 +51,9 @@ class ThreadedTest(unittest.TestCase):
def func_test():
pass
# pylint: disable=assignment-from-no-return
test_thread = func_test()
# pylint: enable=assignment-from-no-return
self.assertEqual(test_thread.name, 'test name')
self.assertFalse(test_thread.daemon)
self.assertFalse(test_thread.isAlive())
@ -57,7 +63,9 @@ class ThreadedTest(unittest.TestCase):
def func_test():
pass
# pylint: disable=assignment-from-no-return
test_thread = func_test()
# pylint: enable=assignment-from-no-return
self.assertEqual(test_thread.name, 'Threaded func_test')
self.assertTrue(test_thread.daemon)
self.assertFalse(test_thread.isAlive())
@ -75,7 +83,9 @@ class ThreadedTest(unittest.TestCase):
def test_args(self):
event = threading.Event()
data = []
# pylint: disable=global-variable-not-assigned
global data
# pylint: enable=global-variable-not-assigned
@decorators.threaded(started=True)
def func_test(add, evnt):
@ -89,7 +99,9 @@ class ThreadedTest(unittest.TestCase):
def test_kwargs(self):
event = threading.Event()
data = []
# pylint: disable=global-variable-not-assigned
global data
# pylint: enable=global-variable-not-assigned
@decorators.threaded(started=True)
def func_test(add, evnt):

View File

@ -78,12 +78,16 @@ class TestExecResult(unittest.TestCase):
)
with self.assertRaises(IndexError):
# pylint: disable=pointless-statement
# noinspection PyStatementEffect
result['nonexistent']
# pylint: enable=pointless-statement
with self.assertRaises(error.DevopsError):
# pylint: disable=pointless-statement
# noinspection PyStatementEffect
result['stdout_json']
# pylint: enable=pointless-statement
logger.assert_has_calls((
mock.call.exception(
"'{cmd}' stdout is not valid json:\n"

View File

@ -12,12 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import mock
import unittest
import mock
from devops import error
from devops.helpers import retry
from devops.helpers import decorators
class TestRetry(unittest.TestCase):
@ -37,7 +37,7 @@ class TestRetry(unittest.TestCase):
def __init__(self, method):
self.m = method
@retry.retry(TypeError, count=count, delay=delay)
@decorators.retry(TypeError, count=count, delay=delay)
def method(self):
return self.m()
@ -93,6 +93,6 @@ class TestRetry(unittest.TestCase):
))
def test_wrong_arg(self):
retry_dec = retry.retry(AttributeError)
retry_dec = decorators.retry(AttributeError)
with self.assertRaises(error.DevopsException):
retry_dec('wrong')

View File

@ -1334,7 +1334,7 @@ class TestExecute(unittest.TestCase):
execute_async,
client, policy, logger):
(
chan, _stdin, exp_result, stderr, stdout
chan, _stdin, _, stderr, stdout
) = self.get_patched_execute_async_retval()
is_set = mock.Mock(return_value=False)
chan.status_event.attach_mock(is_set, 'is_set')
@ -1357,7 +1357,7 @@ class TestExecute(unittest.TestCase):
'devops.helpers.ssh_client.SSHClient.execute_async')
def test_execute_together(self, execute_async, client, policy, logger):
(
chan, _stdin, exp_result, stderr, stdout
chan, _stdin, _, stderr, stdout
) = self.get_patched_execute_async_retval()
execute_async.return_value = chan, _stdin, stderr, stdout
@ -1716,11 +1716,6 @@ class TestSftp(unittest.TestCase):
lstat.assert_called_once_with(dst)
def test_stat(self, client, policy, logger):
class Attrs(object):
def __init__(self, mode):
self.st_mode = mode
self.st_size = 0
ssh, _sftp = self.prepare_sftp_file_tests(client)
stat = mock.Mock()
_sftp.attach_mock(stat, 'stat')

View File

@ -16,7 +16,7 @@ import collections
import mock
from devops.models import Environment
from devops import models
from devops.tests.driver.libvirt.base import LibvirtTestCase
from django.conf import settings
@ -45,7 +45,7 @@ class TestCentosMasterExt(LibvirtTestCase):
# Environment with an 'admin' network
self.env = Environment.create('test')
self.env = models.Environment.create('test')
self.group = self.env.add_group(
group_name='test_group',
driver_name='devops.driver.libvirt',
@ -79,7 +79,7 @@ class TestCentosMasterExt(LibvirtTestCase):
networks=['fuelweb_admin'])
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.centos_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
@mock.patch(
'devops.helpers.subprocess_runner.Subprocess', autospec=True)

View File

@ -64,9 +64,9 @@ class TestFuelMasterNewtonExt(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = self.node.ext

View File

@ -64,9 +64,9 @@ class TestFuelMaster50Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -64,9 +64,9 @@ class TestFuelMaster51Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -65,9 +65,9 @@ class TestFuelMaster60Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -66,9 +66,9 @@ class TestFuelMaster61Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -67,9 +67,9 @@ class TestFuelMaster70Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -63,9 +63,9 @@ class TestFuelMaster80Ext(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = NodeExtension(self.node)

View File

@ -64,9 +64,9 @@ class TestFuelMasterMitakaExt(DriverlessTestCase):
self.send_keys_mock = self.patch('devops.models.Node.send_keys',
create=True)
self.wait_tcp_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_tcp')
'devops.helpers.helpers.wait_tcp')
self.wait_ssh_cmd_mock = self.patch(
'devops.models.node_ext.fuel_master.wait_ssh_cmd')
'devops.helpers.helpers.wait_ssh_cmd')
self.node_ext = self.node.ext

View File

@ -30,7 +30,6 @@ sphinx_apidoc_main([
'../../devops',
# exclude dirs
'../../devops/settings.py',
'../../devops/test_settings.py',
'../../devops/migrations/',
'../../devops/tests/',
'../../devops/templates/',

View File

@ -12,13 +12,12 @@
# License for the specific language governing permissions and limitations
# under the License.
from sys import version_info
import sys
from setuptools import find_packages
from setuptools import setup
import setuptools
setup(
setuptools.setup(
name='fuel-devops',
version='3.0.2',
description='Library for creating and manipulating virtual environments',
@ -28,7 +27,7 @@ setup(
keywords='devops virtual environment',
zip_safe=False,
include_package_data=True,
packages=find_packages(),
packages=setuptools.find_packages(),
package_data={'devops': ['templates/*.yaml', 'templates/*.yml']},
scripts=[
'bin/dos.py',
@ -51,7 +50,7 @@ setup(
'tabulate',
'six>=1.9.0',
'python-dateutil>=2.4.2',
'enum34' if version_info.major == 2 else ''
'enum34' if sys.version_info.major == 2 else ''
],
tests_require=[
'pytest>=2.7.1',