Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

network: re-enable test_ipv6_support module #40

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 0 additions & 92 deletions network-suite-master/fixtures/fqdn.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import pytest

from ovirtlib import sshlib
from ovirtlib import syncutil

OVN_CONF = '/etc/ovirt-provider-ovn/conf.d/10-setup-ovirt-provider-ovn.conf'

Expand Down Expand Up @@ -35,94 +34,3 @@ def _fetch_fqdn(answer_file):
for line in f:
if line.startswith(FQDN_ENTRY):
return line.strip().split(':', 1)[1]


@pytest.fixture(scope='session')
def host0_eth2_ipv6(host0_facts):
"""
nics created by lago are managed by nmcli and have autoconf ipv6 but have
not been assigned an address. this function requests a dynamic assignment
of an ipv6 to 'eth2' and retrieves it.
:return: the ipv6 address as string
:raise: timeout exception if global ipv6 address not found on NIC
"""
host_0 = sshlib.Node(host0_facts.default_ip(), host0_facts.ssh_password)
return _enable_dynamic_ipv6(host_0, 'eth2')


@pytest.fixture(scope='session')
def host0_eth1_ipv6(host0_facts):
"""
nics created by lago are managed by nmcli and have autoconf ipv6 but have
not been assigned an address. this function requests a dynamic assignment
of an ipv6 to 'eth1' and retrieves it.
:return: the ipv6 address as string
:raise: timeout exception if global ipv6 address not found on NIC
"""
host_0 = sshlib.Node(host0_facts.default_ip(), host0_facts.ssh_password)
return _enable_dynamic_ipv6(host_0, 'eth1')


@pytest.fixture(scope='session')
def engine_storage_ipv6(engine_facts):
"""
lago creates a network with an ipv6 subnet and connects it to NIC
'eth1' of the engine. It names the network 'storage' but does not assign an
ipv6 address to the NIC.
this function requests a dynamic assignment of an ipv6 to 'eth1' of the
engine machine and retrieves it.
:return: the ipv6 address as string
:raise: timeout exception if global ipv6 address not found on NIC
"""
engine = sshlib.Node(engine_facts.default_ip(), engine_facts.ssh_password)
ENGINE_STORAGE_NIC = 'eth1'
return _enable_dynamic_ipv6(engine, ENGINE_STORAGE_NIC)


def _enable_dynamic_ipv6(ssh_node, nic_name):
"""
this function connects to the specified lago VM using its ssh API to:
* request the host OS to dynamically assign an ipv6 address to the
specified NIC
* wait for the address to be assigned (it might take up to a few seconds)
* retrieve the address
:return: the ipv6 address as string
:raise: timeout exception if global ipv6 address not found on NIC
"""
_assign_ipv6(ssh_node, nic_name)
return syncutil.sync(
exec_func=_get_ipv6,
exec_func_args=(ssh_node, nic_name),
success_criteria=lambda ipv6: ipv6 != '',
timeout=10,
)


def _assign_ipv6(ssh_node, nic_name):
"""
lago creates ipv6 subnets and sets ipv6 autoconf on its VMs' NICs but does
not assign ipv6 addresses to the NICs.
this function connects to a lago VM using its ssh API and requests an ipv6
address be assigned to the NIC using nmcli.
:param ssh_node: an sshlib.Node that exposes an ssh API into itself
:param nic_name: the name of the NIC to assign an ipv6 address to
:raise: exception if an error occurred during the assignment
"""
res = ssh_node.exec_command(' '.join(['nmcli', 'con', 'modify', nic_name, 'ipv6.method', 'auto']))

if res.code:
raise Exception('nmcli con modify failed: exit code %s, error "%s"' % (res.code, res.err))
res = ssh_node.exec_command(' '.join(['nmcli', 'con', 'up', nic_name]))
if res.code:
raise Exception('nmcli con up failed: exit code %s, error "%s"' % (res.code, res.err))


def _get_ipv6(ssh_node, nic_name):
"""
:param ssh_node: an sshlib.Node that exposes an ssh API into itself
:param nic_name: the name of the NIC from which to get the ipv6 address
:return: the ipv6 address of the lago vm on eth1 as string or empty string
"""
INET6 = 'inet6 '
res = ssh_node.exec_command(['ip -o -6 a show', nic_name, 'scope global'])
return res.out[res.out.find(INET6) + len(INET6) : res.out.find('/')]
9 changes: 2 additions & 7 deletions network-suite-master/fixtures/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,11 @@ def default_storage_domain(system, engine_facts, host_0_up, default_data_center)
try:
storage_domain.import_by_name(DEFAULT_DOMAIN_NAME)
except EntityNotFoundError:
nfs_storage_data = storagelib.NfsStorageData(engine_facts.default_ip(urlize=True), DEFAULT_DOMAIN_PATH)
storage_domain.create(
name=DEFAULT_DOMAIN_NAME,
domain_type=storagelib.StorageDomainType.DATA,
host=host_0_up,
host_storage_data=storagelib.HostStorageData(
storage_type=storagelib.StorageType.NFS,
address=engine_facts.default_ip(urlize=True),
path=DEFAULT_DOMAIN_PATH,
nfs_version=storagelib.NfsVersion.V4_2,
),
host_storage_data=nfs_storage_data,
)
storage_domain.wait_for_unattached_status()
default_data_center.attach_storage_domain(storage_domain)
Expand Down
125 changes: 84 additions & 41 deletions network-suite-master/ovirtlib/storagelib.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
#
import abc
import contextlib

from ovirtsdk4 import types
Expand Down Expand Up @@ -55,25 +56,26 @@ class NfsVersion(object):
V4_2 = types.NfsVersion.V4_2


class HostStorageData(object):
def __init__(self, storage_type, address, path, nfs_version=None, logical_units=()):
class HostStorageData(metaclass=abc.ABCMeta):
def __init__(self, storage_type, domain_type, address=None, path=None):
"""
:param storage_type: string indicates the storage type.
:param address: string indicates the NFS storage address.
:param path: string indicates the NFS storage path.
:param nfs_version: string indicates the NFS storage version.
:param logical_units: tuple of LogicalUnits.
Represent logical units (luns) in case of an iSCSI storage domain.
:param storage_type: storagelib.StorageType
:param domain_type: storagelib.StorageDomainType
:param address: string indicates the storage address.
:param path: string indicates the storage path.
"""
self._type = storage_type
self._storage_type = storage_type
self._domain_type = domain_type
self._address = address
self._path = path
self._nfs_version = nfs_version
self._logical_units = logical_units

@property
def type(self):
return self._type
def storage_type(self):
return self._storage_type

@property
def domain_type(self):
return self._domain_type

@property
def address(self):
Expand All @@ -83,14 +85,62 @@ def address(self):
def path(self):
return self._path

@abc.abstractmethod
def as_sdk_type(self):
"""
:return: representation of this object as the equivalent ovirtsdk4.types object.
ovirtlib is a wrapper and encapsulator of ovirtsdk4.types and ovirtsdk4.services,
so this method should not be used outside ovirtlib
"""


class NfsStorageData(HostStorageData):
def __init__(self, address, path, domain_type=StorageDomainType.DATA, version=NfsVersion.V4_2):
super(NfsStorageData, self).__init__(StorageType.NFS, domain_type, address, path)
self._version = version

@property
def nfs_version(self):
return self._nfs_version
def version(self):
return self._version

def as_sdk_type(self):
return types.HostStorage(
type=self.storage_type,
address=self.address,
path=self.path,
nfs_version=self.version,
)

def __repr__(self):
return (
f'<{self.__class__.__name__}| '
f'address:{self.address}, '
f'path:{self.path}, '
f'version:{self.version}>'
f'domain_type:{self.domain_type}, '
)


class IscsiStorageData(HostStorageData):
def __init__(self, domain_type=StorageDomainType.DATA, logical_units=()):
super(IscsiStorageData, self).__init__(StorageType.ISCSI, domain_type)
self._logical_units = logical_units

@property
def logical_units(self):
return self._logical_units

def as_sdk_type(self):
return types.HostStorage(
type=self.storage_type,
address=self.address,
path=self.path,
logical_units=[lun.as_sdk_type() for lun in self.logical_units],
)

def __repr__(self):
return f'<{self.__class__.__name__}| logical_units:{self.logical_units}, domain_type:{self.domain_type}>'


class StorageDomainStatus(object):

Expand All @@ -111,24 +161,17 @@ def status(self):
def wait_for_unattached_status(self):
self._wait_for_status(StorageDomainStatus.UNATTACHED)

def create(self, name, host, domain_type, host_storage_data):
def create(self, name, host, host_storage_data):
"""
:param name: string
:param host: hostlib.Host
:param domain_type: StorageDomainType
:param host_storage_data: HostStorageData
"""
sdk_type = types.StorageDomain(
name=name,
host=host.get_sdk_type(),
type=domain_type,
storage=types.HostStorage(
type=host_storage_data.type,
address=host_storage_data.address,
path=host_storage_data.path,
nfs_version=host_storage_data.nfs_version,
logical_units=self._get_sdk_type_logical_units(host_storage_data.logical_units),
),
type=host_storage_data.domain_type,
storage=host_storage_data.as_sdk_type(),
)
self._create_sdk_entity(sdk_type)

Expand Down Expand Up @@ -180,20 +223,9 @@ def create_disk(self, name):
disk.wait_for_up_status()
return disk

def _get_sdk_type_logical_units(self, logical_units):
return [
types.LogicalUnit(
id=lundata.id,
address=lundata.address,
port=lundata.port,
target=lundata.target,
)
for lundata in logical_units
]

def __repr__(self):
return self._execute_without_raising(
lambda: (f'<{self.__class__.__name__}| ' f'name:{self.name}, ' f'status:{self.status}, ' f'id:{self.id}>')
lambda: f'<{self.__class__.__name__}| name:{self.name}, status:{self.status}, id:{self.id}>'
)


Expand Down Expand Up @@ -233,8 +265,8 @@ def wait_for_up_status(self):


class LogicalUnit(object):
def __init__(self, id, address, port, target):
self._id = id
def __init__(self, lun_id, address, port, target):
self._id = lun_id
self._address = address
self._port = port
self._target = target
Expand All @@ -255,13 +287,24 @@ def port(self):
def target(self):
return self._target

def as_sdk_type(self):
return types.LogicalUnit(id=self.id, address=self.address, port=self.port, target=self.target)

def __repr__(self):
return (
f'<{self.__class__.__name__}| '
f'address:{self.address}, '
f'port:{self.port}, '
f'target:{self.target}, '
f'lun_id:{self.id}>'
)


@contextlib.contextmanager
def storage_domain(system, name, domain_type, host, host_storage_data):
def storage_domain(system, name, host, host_storage_data):
sd = StorageDomain(system)
sd.create(
name=name,
domain_type=domain_type,
host=host,
host_storage_data=host_storage_data,
)
Expand Down
5 changes: 2 additions & 3 deletions network-suite-master/test-scenarios/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,6 @@
from fixtures.engine import api
from fixtures.engine import test_invocation_logger

from fixtures.fqdn import engine_storage_ipv6
from fixtures.fqdn import host0_eth1_ipv6
from fixtures.fqdn import host0_eth2_ipv6
from fixtures.fqdn import ovirt_provider_ovn_with_ip_fqdn

from fixtures.storage import default_storage_domain
Expand Down Expand Up @@ -87,6 +84,7 @@
from ost_utils.pytest.fixtures.engine import engine_ip
from ost_utils.pytest.fixtures.engine import engine_ip_url
from ost_utils.pytest.fixtures.engine import engine_ips_for_network
from ost_utils.pytest.fixtures.engine import engine_storage_ips
from ost_utils.pytest.fixtures.engine import engine_username
from ost_utils.pytest.fixtures.env import ost_images_distro
from ost_utils.pytest.fixtures.env import root_dir
Expand All @@ -95,6 +93,7 @@
from ost_utils.pytest.fixtures.env import working_dir
from ost_utils.pytest.fixtures.network import management_network_name
from ost_utils.pytest.fixtures.network import management_subnet
from ost_utils.pytest.fixtures.network import storage_network_name
from ost_utils.pytest.fixtures.network import storage_subnet
from ost_utils.pytest.fixtures.sdk import get_user_service_for_user
from ost_utils.pytest.fixtures.sdk import system_service
Expand Down
Loading