Add nova floating ip management in VM scenario
This patch allows VM runcommand scenario attach a floating ip to the instance to perform ssh connection. Blueprint: benchmark-scenarios-vm-floating-ip Change-Id: I2e77d6be34a64d5feb9d3ecc5e35c8a712b10bed
This commit is contained in:
parent
044abcbd8f
commit
3d8b423db3
@ -8,6 +8,9 @@
|
|||||||
"image": {
|
"image": {
|
||||||
"name": "cirros-0.3.1-x86_64-uec"
|
"name": "cirros-0.3.1-x86_64-uec"
|
||||||
},
|
},
|
||||||
|
"fixed_network": "private",
|
||||||
|
"floating_network": "public",
|
||||||
|
"use_floatingip": true,
|
||||||
"script": "doc/samples/support/instance_dd_test.sh",
|
"script": "doc/samples/support/instance_dd_test.sh",
|
||||||
"interpreter": "/bin/sh",
|
"interpreter": "/bin/sh",
|
||||||
"username": "cirros"
|
"username": "cirros"
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
name: "m1.nano"
|
name: "m1.nano"
|
||||||
image:
|
image:
|
||||||
name: "cirros-0.3.1-x86_64-uec"
|
name: "cirros-0.3.1-x86_64-uec"
|
||||||
|
fixed_network: "private"
|
||||||
|
floating_network: "public"
|
||||||
|
use_floatingip: true
|
||||||
script: "doc/samples/support/instance_dd_test.sh"
|
script: "doc/samples/support/instance_dd_test.sh"
|
||||||
interpreter: "/bin/sh"
|
interpreter: "/bin/sh"
|
||||||
username: "cirros"
|
username: "cirros"
|
||||||
|
@ -102,6 +102,24 @@
|
|||||||
type: "constant"
|
type: "constant"
|
||||||
times: 100
|
times: 100
|
||||||
concurrency: 10
|
concurrency: 10
|
||||||
|
|
||||||
|
VMTasks.boot_runcommand_delete:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
flavor:
|
||||||
|
name: "m1.tiny"
|
||||||
|
image:
|
||||||
|
name: "cirros-0.3.2-x86_64-uec"
|
||||||
|
fixed_network: "private"
|
||||||
|
floating_network: "public"
|
||||||
|
use_floatingip: true
|
||||||
|
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
|
interpreter: "/bin/sh"
|
||||||
|
username: "cirros"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 6
|
||||||
|
concurrency: 3
|
||||||
context:
|
context:
|
||||||
users:
|
users:
|
||||||
tenants: 1
|
tenants: 1
|
||||||
|
@ -321,3 +321,44 @@
|
|||||||
users:
|
users:
|
||||||
tenants: 3
|
tenants: 3
|
||||||
users_per_tenant: 5
|
users_per_tenant: 5
|
||||||
|
|
||||||
|
VMTasks.boot_runcommand_delete:
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
flavor:
|
||||||
|
name: "m1.tiny"
|
||||||
|
image:
|
||||||
|
name: "cirros-0.3.2-x86_64-uec"
|
||||||
|
fixed_network: "private"
|
||||||
|
floating_network: "public"
|
||||||
|
use_floatingip: true
|
||||||
|
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
|
interpreter: "/bin/sh"
|
||||||
|
username: "cirros"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 6
|
||||||
|
concurrency: 3
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
-
|
||||||
|
args:
|
||||||
|
flavor:
|
||||||
|
name: "m1.tiny"
|
||||||
|
image:
|
||||||
|
name: "cirros-0.3.2-x86_64-uec"
|
||||||
|
fixed_network: "private"
|
||||||
|
use_floatingip: false
|
||||||
|
script: "/home/jenkins/.rally/extra/instance_dd_test.sh"
|
||||||
|
interpreter: "/bin/sh"
|
||||||
|
username: "cirros"
|
||||||
|
runner:
|
||||||
|
type: "constant"
|
||||||
|
times: 6
|
||||||
|
concurrency: 3
|
||||||
|
context:
|
||||||
|
users:
|
||||||
|
tenants: 1
|
||||||
|
users_per_tenant: 1
|
||||||
|
@ -21,6 +21,7 @@ from rally.benchmark.scenarios import base
|
|||||||
from rally.benchmark.scenarios import utils as scenario_utils
|
from rally.benchmark.scenarios import utils as scenario_utils
|
||||||
from rally.benchmark import utils as bench_utils
|
from rally.benchmark import utils as bench_utils
|
||||||
|
|
||||||
|
|
||||||
nova_benchmark_opts = []
|
nova_benchmark_opts = []
|
||||||
option_names_and_defaults = [
|
option_names_and_defaults = [
|
||||||
# action, prepoll delay, timeout, poll interval
|
# action, prepoll delay, timeout, poll interval
|
||||||
@ -93,6 +94,7 @@ class NovaScenario(base.Scenario):
|
|||||||
|
|
||||||
server = self.clients("nova").servers.create(server_name, image_id,
|
server = self.clients("nova").servers.create(server_name, image_id,
|
||||||
flavor_id, **kwargs)
|
flavor_id, **kwargs)
|
||||||
|
|
||||||
time.sleep(CONF.benchmark.nova_server_boot_prepoll_delay)
|
time.sleep(CONF.benchmark.nova_server_boot_prepoll_delay)
|
||||||
server = bench_utils.wait_for(
|
server = bench_utils.wait_for(
|
||||||
server,
|
server,
|
||||||
@ -312,3 +314,86 @@ class NovaScenario(base.Scenario):
|
|||||||
check_interval=CONF.benchmark.nova_server_boot_poll_interval
|
check_interval=CONF.benchmark.nova_server_boot_poll_interval
|
||||||
) for server in servers]
|
) for server in servers]
|
||||||
return servers
|
return servers
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.list_floating_ip_pools')
|
||||||
|
def _list_floating_ip_pools(self):
|
||||||
|
"""Returns user floating ip pools list."""
|
||||||
|
return self.clients("nova").floating_ip_pools.list()
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.list_floating_ips')
|
||||||
|
def _list_floating_ips(self):
|
||||||
|
"""Returns user floating ips list."""
|
||||||
|
return self.clients("nova").floating_ips.list()
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.create_floating_ip')
|
||||||
|
def _create_floating_ip(self, pool):
|
||||||
|
"""Create (allocate) a floating ip from the given pool
|
||||||
|
|
||||||
|
:param pool: Name of the floating ip pool or external network
|
||||||
|
|
||||||
|
:returns: The created floating ip
|
||||||
|
"""
|
||||||
|
return self.clients("nova").floating_ips.create(pool)
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.delete_floating_ip')
|
||||||
|
def _delete_floating_ip(self, floating_ip):
|
||||||
|
"""Delete (deallocate) a floating ip for a tenant
|
||||||
|
|
||||||
|
:param floating_ip: The floating ip address to delete.
|
||||||
|
"""
|
||||||
|
self.clients("nova").floating_ips.delete(floating_ip)
|
||||||
|
bench_utils.wait_for_delete(
|
||||||
|
floating_ip,
|
||||||
|
update_resource=bench_utils.get_from_manager()
|
||||||
|
)
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.associate_floating_ip')
|
||||||
|
def _associate_floating_ip(self, server, address, fixed_address=None):
|
||||||
|
"""Add floating IP to an instance
|
||||||
|
|
||||||
|
:param server: The :class:`Server` to add an IP to.
|
||||||
|
:param address: The ip address or FloatingIP to add to the instance
|
||||||
|
:param fixed_address: The fixedIP address the FloatingIP is to be
|
||||||
|
associated with (optional)
|
||||||
|
"""
|
||||||
|
server.add_floating_ip(address, fixed_address=fixed_address)
|
||||||
|
bench_utils.wait_for(
|
||||||
|
server,
|
||||||
|
is_ready=self.check_ip_address(address),
|
||||||
|
update_resource=bench_utils.get_from_manager()
|
||||||
|
)
|
||||||
|
# Update server data
|
||||||
|
server.addresses = server.manager.get(server.id).addresses
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.dissociate_floating_ip')
|
||||||
|
def _dissociate_floating_ip(self, server, address):
|
||||||
|
"""Remove floating IP from an instance
|
||||||
|
|
||||||
|
:param server: The :class:`Server` to add an IP to.
|
||||||
|
:param address: The ip address or FloatingIP to remove
|
||||||
|
"""
|
||||||
|
server.remove_floating_ip(address)
|
||||||
|
bench_utils.wait_for(
|
||||||
|
server,
|
||||||
|
is_ready=self.check_ip_address(address, must_exist=False),
|
||||||
|
update_resource=bench_utils.get_from_manager()
|
||||||
|
)
|
||||||
|
# Update server data
|
||||||
|
server.addresses = server.manager.get(server.id).addresses
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_ip_address(address, must_exist=True):
|
||||||
|
ip_to_check = getattr(address, "ip", address)
|
||||||
|
|
||||||
|
def _check_addr(resource):
|
||||||
|
for network, addr_list in resource.addresses.items():
|
||||||
|
for addr in addr_list:
|
||||||
|
if ip_to_check == addr["addr"]:
|
||||||
|
return must_exist
|
||||||
|
return not must_exist
|
||||||
|
return _check_addr
|
||||||
|
|
||||||
|
@scenario_utils.atomic_action_timer('nova.list_networks')
|
||||||
|
def _list_networks(self):
|
||||||
|
"""Returns user networks list."""
|
||||||
|
return self.clients("nova").networks.list()
|
||||||
|
@ -14,8 +14,11 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
|
||||||
|
import subprocess
|
||||||
|
|
||||||
from rally.benchmark.scenarios import base
|
from rally.benchmark.scenarios import base
|
||||||
from rally.benchmark.scenarios import utils as scenario_utils
|
from rally.benchmark.scenarios import utils as scenario_utils
|
||||||
|
from rally.benchmark import utils as bench_utils
|
||||||
from rally import sshutils
|
from rally import sshutils
|
||||||
|
|
||||||
|
|
||||||
@ -29,12 +32,19 @@ class VMScenario(base.Scenario):
|
|||||||
"""
|
"""
|
||||||
return ssh.execute(interpreter, stdin=open(script, "rb"))
|
return ssh.execute(interpreter, stdin=open(script, "rb"))
|
||||||
|
|
||||||
@scenario_utils.atomic_action_timer('vm.wait_for_network')
|
@scenario_utils.atomic_action_timer('vm.wait_for_ssh')
|
||||||
def wait_for_network(self, ssh):
|
def wait_for_ssh(self, ssh):
|
||||||
ssh.wait()
|
ssh.wait()
|
||||||
|
|
||||||
def run_command(self, server, username, network, port, ip_version,
|
@scenario_utils.atomic_action_timer('vm.wait_for_ping')
|
||||||
interpreter, script):
|
def wait_for_ping(self, server_ip):
|
||||||
|
bench_utils.wait_for(
|
||||||
|
server_ip,
|
||||||
|
is_ready=self.ping_ip_address,
|
||||||
|
timeout=120
|
||||||
|
)
|
||||||
|
|
||||||
|
def run_command(self, server_ip, port, username, interpreter, script):
|
||||||
"""Run command via SSH on server.
|
"""Run command via SSH on server.
|
||||||
|
|
||||||
Create SSH connection for server, wait for server to become
|
Create SSH connection for server, wait for server to become
|
||||||
@ -42,21 +52,38 @@ class VMScenario(base.Scenario):
|
|||||||
and sshd being available). Then call __run_command to actually
|
and sshd being available). Then call __run_command to actually
|
||||||
execute the command.
|
execute the command.
|
||||||
"""
|
"""
|
||||||
|
self.wait_for_ping(server_ip)
|
||||||
if network not in server.addresses:
|
|
||||||
raise ValueError(
|
|
||||||
"Can't find cloud network %(network)s, so cannot boot "
|
|
||||||
"instance for Rally scenario boot-runcommand-delete. "
|
|
||||||
"Available networks: %(networks)s" % (
|
|
||||||
dict(network=network,
|
|
||||||
networks=server.addresses.keys()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
server_ip = [ip for ip in server.addresses[network] if
|
|
||||||
ip["version"] == ip_version][0]["addr"]
|
|
||||||
ssh = sshutils.SSH(username, server_ip, port=port,
|
ssh = sshutils.SSH(username, server_ip, port=port,
|
||||||
pkey=self.context()["user"]["keypair"]["private"])
|
pkey=self.context()["user"]["keypair"]["private"])
|
||||||
|
|
||||||
self.wait_for_network(ssh)
|
self.wait_for_ssh(ssh)
|
||||||
return self.run_action(ssh, interpreter, script)
|
return self.run_action(ssh, interpreter, script)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def check_network(server, network):
|
||||||
|
"""Check if a server is attached to the specified network.
|
||||||
|
|
||||||
|
:param server: The server object to consider
|
||||||
|
:param network: The name of the network to search for.
|
||||||
|
|
||||||
|
:raises: `ValueError` if server is not attached to network.
|
||||||
|
"""
|
||||||
|
if network not in server.addresses:
|
||||||
|
raise ValueError(
|
||||||
|
"Server %(server_name)s is not attached to"
|
||||||
|
" network %(network)s. "
|
||||||
|
"Attached networks are: %(networks)s" % {
|
||||||
|
"server_name": server.name,
|
||||||
|
"network": network,
|
||||||
|
"networks": server.addresses.keys()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def ping_ip_address(host, should_succeed=True):
|
||||||
|
cmd = ['ping', '-c1', '-w1', host]
|
||||||
|
proc = subprocess.Popen(cmd,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE)
|
||||||
|
proc.wait()
|
||||||
|
return (proc.returncode == 0) == should_succeed
|
||||||
|
@ -20,11 +20,7 @@ from rally.benchmark.scenarios.nova import utils as nova_utils
|
|||||||
from rally.benchmark.scenarios.vm import utils as vm_utils
|
from rally.benchmark.scenarios.vm import utils as vm_utils
|
||||||
from rally.benchmark import types as types
|
from rally.benchmark import types as types
|
||||||
from rally.benchmark import validation
|
from rally.benchmark import validation
|
||||||
from rally.openstack.common.gettextutils import _ # noqa
|
from rally import exceptions
|
||||||
from rally.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario):
|
class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario):
|
||||||
@ -38,44 +34,100 @@ class VMTasks(nova_utils.NovaScenario, vm_utils.VMScenario):
|
|||||||
@validation.add(validation.file_exists("script"))
|
@validation.add(validation.file_exists("script"))
|
||||||
@validation.add(validation.number("port", minval=1, maxval=65535,
|
@validation.add(validation.number("port", minval=1, maxval=65535,
|
||||||
nullable=True, integer_only=True))
|
nullable=True, integer_only=True))
|
||||||
|
@validation.add(validation.external_network_exists("floating_network",
|
||||||
|
"use_floatingip"))
|
||||||
@base.scenario(context={"cleanup": ["nova"],
|
@base.scenario(context={"cleanup": ["nova"],
|
||||||
"keypair": {}, "allow_ssh": {}})
|
"keypair": {}, "allow_ssh": {}})
|
||||||
def boot_runcommand_delete(self, image, flavor,
|
def boot_runcommand_delete(self, image, flavor,
|
||||||
script, interpreter, network='private',
|
script, interpreter, username,
|
||||||
username='ubuntu', ip_version=4,
|
fixed_network="private",
|
||||||
port=22, **kwargs):
|
floating_network="public",
|
||||||
|
ip_version=4, port=22,
|
||||||
|
use_floatingip=True, **kwargs):
|
||||||
"""Boot server, run a script that outputs JSON, delete server.
|
"""Boot server, run a script that outputs JSON, delete server.
|
||||||
|
|
||||||
Parameters:
|
:param script: script to run on the server, must output JSON mapping
|
||||||
script: script to run on the server, must output JSON mapping metric
|
metric names to values. See sample script below.
|
||||||
names to values. See sample script below.
|
:param interpreter: The shell interpreter to use when running script
|
||||||
network: Network to choose address to connect to instance from
|
:param username: User to SSH to instance as
|
||||||
username: User to SSH to instance as
|
:param fixed_network: Network where instance is part of
|
||||||
ip_version: Version of ip protocol to use for connection
|
:param floating_network: External network used to get floating ip from
|
||||||
|
:param ip_version: Version of ip protocol to use for connection
|
||||||
|
:param port: Port to use for SSH connection
|
||||||
|
:param use_floatingip: Whether to associate a floating ip for
|
||||||
|
connection
|
||||||
|
|
||||||
returns: Dictionary containing two keys, data and errors. Data is JSON
|
:returns: Dictionary containing two keys, data and errors. Data is JSON
|
||||||
data output by the script. Errors is raw data from the
|
data output by the script. Errors is raw data from the
|
||||||
script's standard error stream.
|
script's standard error stream.
|
||||||
|
|
||||||
|
|
||||||
Example Script in doc/samples/support/instance_dd_test.sh
|
Example Script in doc/samples/support/instance_dd_test.sh
|
||||||
"""
|
"""
|
||||||
server = self._boot_server(
|
server = None
|
||||||
self._generate_random_name("rally_novaserver_"),
|
floating_ip = None
|
||||||
image, flavor, key_name='rally_ssh_key', **kwargs)
|
|
||||||
|
|
||||||
code, out, err = self.run_command(server, username, network, port,
|
|
||||||
ip_version, interpreter, script)
|
|
||||||
if code:
|
|
||||||
LOG.error(_("Error running script on instance via SSH. "
|
|
||||||
"Error: %s") % err)
|
|
||||||
try:
|
try:
|
||||||
out = json.loads(out)
|
server = self._boot_server(
|
||||||
except ValueError:
|
self._generate_random_name("rally_novaserver_"),
|
||||||
LOG.warning(_("Script %s did not output valid JSON.") % script)
|
image, flavor, key_name='rally_ssh_key', **kwargs)
|
||||||
|
|
||||||
|
self.check_network(server, fixed_network)
|
||||||
|
|
||||||
|
fixed_ip = [ip for ip in server.addresses[fixed_network] if
|
||||||
|
ip["version"] == ip_version][0]["addr"]
|
||||||
|
|
||||||
|
if use_floatingip:
|
||||||
|
floating_ip = self._create_floating_ip(floating_network)
|
||||||
|
self._associate_floating_ip(server, floating_ip)
|
||||||
|
server_ip = floating_ip.ip
|
||||||
|
else:
|
||||||
|
server_ip = fixed_ip
|
||||||
|
|
||||||
|
code, out, err = self.run_command(server_ip, port,
|
||||||
|
username, interpreter, script)
|
||||||
|
|
||||||
|
if code:
|
||||||
|
raise exceptions.ScriptError(
|
||||||
|
"Error running script %(script)s."
|
||||||
|
"Error %(code)s: %(error)s" % {
|
||||||
|
"script": script,
|
||||||
|
"code": code,
|
||||||
|
"error": err
|
||||||
|
})
|
||||||
|
|
||||||
|
try:
|
||||||
|
out = json.loads(out)
|
||||||
|
except ValueError as e:
|
||||||
|
raise exceptions.ScriptError(
|
||||||
|
"Script %(script)s did not output valid JSON: %(error)s" %
|
||||||
|
{
|
||||||
|
"script": script,
|
||||||
|
"error": str(e)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Always try to free resources
|
||||||
|
finally:
|
||||||
|
if use_floatingip:
|
||||||
|
self._release_server_floating_ip(server, floating_ip)
|
||||||
|
if server:
|
||||||
|
self._delete_server(server)
|
||||||
|
|
||||||
self._delete_server(server)
|
|
||||||
LOG.debug("Output streams from in-instance script execution: "
|
|
||||||
"stdout: %(stdout)s, stderr: $(stderr)s" % dict(
|
|
||||||
stdout=out, stderr=err))
|
|
||||||
return {"data": out, "errors": err}
|
return {"data": out, "errors": err}
|
||||||
|
|
||||||
|
def _release_server_floating_ip(self, server, floating_ip):
|
||||||
|
"""Release a floating ip associated to a server.
|
||||||
|
|
||||||
|
This method check that the given floating ip is associated with the
|
||||||
|
specified server and tries to dissociate it.
|
||||||
|
Once dissociated, release the floating ip to reintegrate
|
||||||
|
it to the pool of available ips.
|
||||||
|
|
||||||
|
:param server: The server to dissociate the floating ip from
|
||||||
|
:param floating_ip: The floating ip to release
|
||||||
|
"""
|
||||||
|
if floating_ip and server:
|
||||||
|
if self.check_ip_address(floating_ip)(server):
|
||||||
|
self._dissociate_floating_ip(server, floating_ip)
|
||||||
|
if floating_ip:
|
||||||
|
self._delete_floating_ip(floating_ip)
|
||||||
|
@ -227,6 +227,46 @@ def image_valid_on_flavor(flavor_name, image_name):
|
|||||||
return image_valid_on_flavor_validator
|
return image_valid_on_flavor_validator
|
||||||
|
|
||||||
|
|
||||||
|
def network_exists(network_name):
|
||||||
|
def network_exists_validator(**kwargs):
|
||||||
|
network = kwargs.get(network_name, "private")
|
||||||
|
|
||||||
|
networks = [net.label for net in
|
||||||
|
kwargs["clients"].nova().networks.list()]
|
||||||
|
if network not in networks:
|
||||||
|
message = _("Network with name %(network)s not found. "
|
||||||
|
"Available networks: %(networks)s") % {
|
||||||
|
"network": network,
|
||||||
|
"networks": networks
|
||||||
|
}
|
||||||
|
return ValidationResult(False, message)
|
||||||
|
|
||||||
|
return ValidationResult()
|
||||||
|
return network_exists_validator
|
||||||
|
|
||||||
|
|
||||||
|
def external_network_exists(network_name, use_external_network):
|
||||||
|
def external_network_exists_validator(**kwargs):
|
||||||
|
if not kwargs.get(use_external_network, True):
|
||||||
|
return ValidationResult()
|
||||||
|
|
||||||
|
ext_network = kwargs.get(network_name, "public")
|
||||||
|
|
||||||
|
networks = [net.name for net in
|
||||||
|
kwargs["clients"].nova().floating_ip_pools.list()]
|
||||||
|
if ext_network not in networks:
|
||||||
|
message = _("External (floating) network with name %(network)s "
|
||||||
|
"not found. "
|
||||||
|
"Available networks: %(networks)s") % {
|
||||||
|
"network": ext_network,
|
||||||
|
"networks": networks
|
||||||
|
}
|
||||||
|
return ValidationResult(False, message)
|
||||||
|
|
||||||
|
return ValidationResult()
|
||||||
|
return external_network_exists_validator
|
||||||
|
|
||||||
|
|
||||||
def tempest_tests_exists():
|
def tempest_tests_exists():
|
||||||
"""Returns validator for tempest test."""
|
"""Returns validator for tempest test."""
|
||||||
def tempest_test_exists_validator(**kwargs):
|
def tempest_test_exists_validator(**kwargs):
|
||||||
|
@ -186,6 +186,10 @@ class SSHError(RallyException):
|
|||||||
msg_fmt = _("Remote command failed.")
|
msg_fmt = _("Remote command failed.")
|
||||||
|
|
||||||
|
|
||||||
|
class ScriptError(RallyException):
|
||||||
|
msg_fmt = _("Script execution failed.")
|
||||||
|
|
||||||
|
|
||||||
class TaskInvalidStatus(RallyException):
|
class TaskInvalidStatus(RallyException):
|
||||||
msg_fmt = _("Task `%(uuid)s` in `%(actual)s` status but `%(require)s` is "
|
msg_fmt = _("Task `%(uuid)s` in `%(actual)s` status but `%(require)s` is "
|
||||||
"required.")
|
"required.")
|
||||||
|
@ -123,7 +123,7 @@ class SSH(object):
|
|||||||
self._client.connect(self.host, username=self.user,
|
self._client.connect(self.host, username=self.user,
|
||||||
port=self.port, pkey=self.pkey,
|
port=self.port, pkey=self.pkey,
|
||||||
key_filename=self.key_filename,
|
key_filename=self.key_filename,
|
||||||
password=self.password)
|
password=self.password, timeout=1)
|
||||||
return self._client
|
return self._client
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
message = _("Exception %(exception_type)s was raised "
|
message = _("Exception %(exception_type)s was raised "
|
||||||
|
@ -35,6 +35,7 @@ class NovaScenarioTestCase(test.TestCase):
|
|||||||
super(NovaScenarioTestCase, self).setUp()
|
super(NovaScenarioTestCase, self).setUp()
|
||||||
self.server = mock.Mock()
|
self.server = mock.Mock()
|
||||||
self.server1 = mock.Mock()
|
self.server1 = mock.Mock()
|
||||||
|
self.floating_ip = mock.Mock()
|
||||||
self.image = mock.Mock()
|
self.image = mock.Mock()
|
||||||
self.res_is = mockpatch.Patch(BM_UTILS + ".resource_is")
|
self.res_is = mockpatch.Patch(BM_UTILS + ".resource_is")
|
||||||
self.get_fm = mockpatch.Patch(BM_UTILS + '.get_from_manager')
|
self.get_fm = mockpatch.Patch(BM_UTILS + '.get_from_manager')
|
||||||
@ -270,3 +271,98 @@ class NovaScenarioTestCase(test.TestCase):
|
|||||||
self.res_is.mock.assert_has_calls(mock.call('ACTIVE'))
|
self.res_is.mock.assert_has_calls(mock.call('ACTIVE'))
|
||||||
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
'nova.boot_servers')
|
'nova.boot_servers')
|
||||||
|
|
||||||
|
@mock.patch(NOVA_UTILS + '.NovaScenario.clients')
|
||||||
|
def test__list_floating_ip_pools(self, mock_clients):
|
||||||
|
pools_list = []
|
||||||
|
mock_clients("nova").floating_ip_pools.list.return_value = pools_list
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
return_pools_list = nova_scenario._list_floating_ip_pools()
|
||||||
|
self.assertEqual(pools_list, return_pools_list)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.list_floating_ip_pools')
|
||||||
|
|
||||||
|
@mock.patch(NOVA_UTILS + '.NovaScenario.clients')
|
||||||
|
def test__list_floating_ips(self, mock_clients):
|
||||||
|
floating_ips_list = []
|
||||||
|
mock_clients("nova").floating_ips.list.return_value = floating_ips_list
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
return_floating_ips_list = nova_scenario._list_floating_ips()
|
||||||
|
self.assertEqual(floating_ips_list, return_floating_ips_list)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.list_floating_ips')
|
||||||
|
|
||||||
|
@mock.patch(NOVA_UTILS + '.NovaScenario.clients')
|
||||||
|
def test__create_floating_ip(self, mock_clients):
|
||||||
|
mock_clients("nova").floating_ips.create.return_value = \
|
||||||
|
self.floating_ip
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
return_floating_ip = nova_scenario._create_floating_ip("public")
|
||||||
|
self.assertEqual(self.floating_ip, return_floating_ip)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.create_floating_ip')
|
||||||
|
|
||||||
|
@mock.patch(NOVA_UTILS + '.NovaScenario.clients')
|
||||||
|
def test__delete_floating_ip(self, mock_clients):
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
nova_scenario._delete_floating_ip(self.floating_ip)
|
||||||
|
mock_clients("nova").floating_ips.delete.assert_called_once_with(
|
||||||
|
self.floating_ip)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.delete_floating_ip')
|
||||||
|
|
||||||
|
def test__associate_floating_ip(self):
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
nova_scenario._associate_floating_ip(self.server, self.floating_ip)
|
||||||
|
self.server.add_floating_ip.assert_called_once_with(self.floating_ip,
|
||||||
|
fixed_address=None)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.associate_floating_ip')
|
||||||
|
|
||||||
|
def test__dissociate_floating_ip(self):
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
nova_scenario._dissociate_floating_ip(self.server, self.floating_ip)
|
||||||
|
self.server.remove_floating_ip.assert_called_once_with(
|
||||||
|
self.floating_ip)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.dissociate_floating_ip')
|
||||||
|
|
||||||
|
def test__check_ip_address(self):
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
fake_server = fakes.FakeServerManager().create("test_server",
|
||||||
|
"image_id_01",
|
||||||
|
"flavor_id_01")
|
||||||
|
fake_server.addresses = {
|
||||||
|
"private": [
|
||||||
|
{"version": 4, "addr": "1.2.3.4"},
|
||||||
|
]}
|
||||||
|
floating_ip = fakes.FakeFloatingIP()
|
||||||
|
floating_ip.ip = "10.20.30.40"
|
||||||
|
|
||||||
|
# Also test function check_ip_address accept a string as attr
|
||||||
|
self.assertFalse(
|
||||||
|
nova_scenario.check_ip_address(floating_ip.ip)(fake_server))
|
||||||
|
self.assertTrue(
|
||||||
|
nova_scenario.check_ip_address(floating_ip.ip, must_exist=False)
|
||||||
|
(fake_server))
|
||||||
|
|
||||||
|
fake_server.addresses["private"].append(
|
||||||
|
{"version": 4, "addr": floating_ip.ip}
|
||||||
|
)
|
||||||
|
# Also test function check_ip_address accept an object with attr ip
|
||||||
|
self.assertTrue(
|
||||||
|
nova_scenario.check_ip_address(floating_ip)
|
||||||
|
(fake_server))
|
||||||
|
self.assertFalse(
|
||||||
|
nova_scenario.check_ip_address(floating_ip, must_exist=False)
|
||||||
|
(fake_server))
|
||||||
|
|
||||||
|
@mock.patch(NOVA_UTILS + '.NovaScenario.clients')
|
||||||
|
def test__list_networks(self, mock_clients):
|
||||||
|
network_list = []
|
||||||
|
mock_clients("nova").networks.list.return_value = network_list
|
||||||
|
nova_scenario = utils.NovaScenario()
|
||||||
|
return_network_list = nova_scenario._list_networks()
|
||||||
|
self.assertEqual(network_list, return_network_list)
|
||||||
|
self._test_atomic_action_timer(nova_scenario.atomic_actions(),
|
||||||
|
'nova.list_networks')
|
||||||
|
@ -14,7 +14,9 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
from oslotest import mockpatch
|
||||||
from rally.benchmark.scenarios.vm import utils
|
from rally.benchmark.scenarios.vm import utils
|
||||||
from tests import fakes
|
from tests import fakes
|
||||||
from tests import test
|
from tests import test
|
||||||
@ -25,6 +27,12 @@ VMTASKS_UTILS = "rally.benchmark.scenarios.vm.utils"
|
|||||||
|
|
||||||
class VMScenarioTestCase(test.TestCase):
|
class VMScenarioTestCase(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(VMScenarioTestCase, self).setUp()
|
||||||
|
self.wait_for = mockpatch.Patch(VMTASKS_UTILS +
|
||||||
|
".bench_utils.wait_for")
|
||||||
|
self.useFixture(self.wait_for)
|
||||||
|
|
||||||
@mock.patch('__builtin__.open')
|
@mock.patch('__builtin__.open')
|
||||||
def test_run_action(self, mock_open):
|
def test_run_action(self, mock_open):
|
||||||
mock_ssh = mock.MagicMock()
|
mock_ssh = mock.MagicMock()
|
||||||
@ -35,32 +43,64 @@ class VMScenarioTestCase(test.TestCase):
|
|||||||
mock_ssh.execute.assert_called_once_with('interpreter',
|
mock_ssh.execute.assert_called_once_with('interpreter',
|
||||||
stdin=mock_file_handle)
|
stdin=mock_file_handle)
|
||||||
|
|
||||||
def test_wait_for_network(self):
|
def test_wait_for_ssh(self):
|
||||||
ssh = mock.MagicMock()
|
ssh = mock.MagicMock()
|
||||||
vm_scenario = utils.VMScenario()
|
vm_scenario = utils.VMScenario()
|
||||||
vm_scenario.wait_for_network(ssh)
|
vm_scenario.wait_for_ssh(ssh)
|
||||||
ssh.wait.assert_called_once_with()
|
ssh.wait.assert_called_once_with()
|
||||||
|
|
||||||
|
@mock.patch(VMTASKS_UTILS + ".VMScenario.ping_ip_address")
|
||||||
|
def test_wait_for_ping(self, mock_ping):
|
||||||
|
mock_ping.return_value = True
|
||||||
|
vm_scenario = utils.VMScenario()
|
||||||
|
vm_scenario.wait_for_ping("1.2.3.4")
|
||||||
|
self.wait_for.mock.assert_called_once_with("1.2.3.4",
|
||||||
|
is_ready=mock_ping,
|
||||||
|
timeout=120)
|
||||||
|
|
||||||
@mock.patch(VMTASKS_UTILS + ".VMScenario.run_action")
|
@mock.patch(VMTASKS_UTILS + ".VMScenario.run_action")
|
||||||
|
@mock.patch(VMTASKS_UTILS + ".VMScenario.wait_for_ping")
|
||||||
@mock.patch("rally.sshutils.SSH")
|
@mock.patch("rally.sshutils.SSH")
|
||||||
def test_run_command(self, mock_ssh_class,
|
def test_run_command(self, mock_ssh_class, mock_wait_ping,
|
||||||
mock_run_action):
|
mock_run_action):
|
||||||
mock_ssh_instance = mock.MagicMock()
|
mock_ssh_instance = mock.MagicMock()
|
||||||
mock_ssh_class.return_value = mock_ssh_instance
|
mock_ssh_class.return_value = mock_ssh_instance
|
||||||
fake_server = fakes.FakeServer()
|
|
||||||
fake_server.addresses = dict(
|
|
||||||
private=[dict(
|
|
||||||
version=4,
|
|
||||||
addr="1.2.3.4"
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
vm_scenario = utils.VMScenario()
|
vm_scenario = utils.VMScenario()
|
||||||
vm_scenario._context = {"user": {"keypair": {"private": "ssh"}}}
|
vm_scenario._context = {"user": {"keypair": {"private": "ssh"}}}
|
||||||
vm_scenario.run_command(fake_server, "username", "private", 22, 4,
|
vm_scenario.run_command("1.2.3.4", 22, "username", "int", "script")
|
||||||
"int", "script")
|
|
||||||
|
|
||||||
mock_ssh_class.assert_called_once_with("username", "1.2.3.4",
|
mock_wait_ping.assert_called_once_with("1.2.3.4")
|
||||||
port=22, pkey="ssh")
|
mock_ssh_class.assert_called_once_with("username", "1.2.3.4", port=22,
|
||||||
|
pkey="ssh")
|
||||||
mock_ssh_instance.wait.assert_called_once_with()
|
mock_ssh_instance.wait.assert_called_once_with()
|
||||||
mock_run_action.assert_called_once_with(mock_ssh_instance,
|
mock_run_action.assert_called_once_with(mock_ssh_instance,
|
||||||
"int", "script")
|
"int", "script")
|
||||||
|
|
||||||
|
def test_check_network(self):
|
||||||
|
vm_scenario = utils.VMScenario()
|
||||||
|
fake_server = fakes.FakeServer()
|
||||||
|
fake_server.addresses = {}
|
||||||
|
self.assertRaises(ValueError,
|
||||||
|
vm_scenario.check_network, fake_server, "private")
|
||||||
|
fake_server.addresses["private_1"] = {
|
||||||
|
"version": 4,
|
||||||
|
"addr": "1.2.3.4"
|
||||||
|
}
|
||||||
|
vm_scenario.check_network(fake_server, "private_1")
|
||||||
|
|
||||||
|
@mock.patch("subprocess.Popen")
|
||||||
|
def test_ping_ip_address(self, mock_subprocess):
|
||||||
|
|
||||||
|
ping_process = mock.MagicMock()
|
||||||
|
ping_process.returncode = 0
|
||||||
|
mock_subprocess.return_value = ping_process
|
||||||
|
|
||||||
|
vm_scenario = utils.VMScenario()
|
||||||
|
host_ip = "1.2.3.4"
|
||||||
|
self.assertTrue(vm_scenario.ping_ip_address(host_ip))
|
||||||
|
|
||||||
|
mock_subprocess.assert_called_once_with(
|
||||||
|
['ping', '-c1', '-w1', host_ip],
|
||||||
|
stderr=subprocess.PIPE, stdout=subprocess.PIPE)
|
||||||
|
ping_process.wait.assert_called_once_with()
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
import mock
|
import mock
|
||||||
|
|
||||||
from rally.benchmark.scenarios.vm import vmtasks
|
from rally.benchmark.scenarios.vm import vmtasks
|
||||||
|
from tests import fakes
|
||||||
from tests import test
|
from tests import test
|
||||||
|
|
||||||
|
|
||||||
@ -25,27 +26,119 @@ class VMTasksTestCase(test.TestCase):
|
|||||||
def test_boot_runcommand_delete(self, mock_json_loads):
|
def test_boot_runcommand_delete(self, mock_json_loads):
|
||||||
# Setup mocks
|
# Setup mocks
|
||||||
scenario = vmtasks.VMTasks()
|
scenario = vmtasks.VMTasks()
|
||||||
scenario._boot_server = mock.MagicMock(return_value="fake_server")
|
fake_server = fakes.FakeServer()
|
||||||
|
fake_server.addresses = dict(
|
||||||
|
private=[dict(
|
||||||
|
version=4,
|
||||||
|
addr="1.2.3.4"
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
|
||||||
|
scenario._boot_server = mock.MagicMock(return_value=fake_server)
|
||||||
|
|
||||||
scenario._generate_random_name = mock.MagicMock(return_value="name")
|
scenario._generate_random_name = mock.MagicMock(return_value="name")
|
||||||
|
|
||||||
|
fake_floating_ip = fakes.FakeFloatingIP()
|
||||||
|
fake_floating_ip.ip = "4.3.2.1"
|
||||||
|
scenario._create_floating_ip = mock.MagicMock(
|
||||||
|
return_value=fake_floating_ip)
|
||||||
|
scenario._associate_floating_ip = mock.MagicMock()
|
||||||
|
#scenario._dissociate_floating_ip = mock.MagicMock()
|
||||||
|
#scenario._delete_floating_ip = mock.MagicMock()
|
||||||
|
scenario._release_server_floating_ip = mock.MagicMock()
|
||||||
|
#scenario.check_ip_address = mock.MagicMock(
|
||||||
|
# return_value=mock.MagicMock(return_value=True))
|
||||||
|
|
||||||
|
fake_floating_ip_pool = fakes.FakeFloatingIPPool()
|
||||||
|
fake_floating_ip_pool.name = "public"
|
||||||
|
scenario._list_floating_ip_pools = mock.MagicMock(
|
||||||
|
return_value=[fake_floating_ip_pool])
|
||||||
|
|
||||||
scenario.run_command = mock.MagicMock()
|
scenario.run_command = mock.MagicMock()
|
||||||
scenario.run_command.return_value = ('code', 'stdout', 'stderr')
|
scenario.run_command.return_value = (0, 'stdout', 'stderr')
|
||||||
scenario._delete_server = mock.MagicMock()
|
scenario._delete_server = mock.MagicMock()
|
||||||
|
|
||||||
# Run scenario
|
# Run scenario
|
||||||
scenario.boot_runcommand_delete(
|
scenario.boot_runcommand_delete(
|
||||||
"image_id", "flavour_id", "script_path", "interpreter",
|
"image_id", "flavour_id", "script_path", "interpreter",
|
||||||
network="network", username="username", ip_version="ip_version",
|
fixed_network='private', floating_network='public',
|
||||||
port="port", fakearg="f")
|
username="username", ip_version=4,
|
||||||
|
port=22, use_floatingip=True, fakearg="f")
|
||||||
|
|
||||||
# Assertions
|
# Assertions
|
||||||
scenario._boot_server.assert_called_once_with(
|
scenario._boot_server.assert_called_once_with(
|
||||||
'name', 'image_id', "flavour_id", key_name="rally_ssh_key",
|
'name', 'image_id', "flavour_id", key_name="rally_ssh_key",
|
||||||
fakearg="f")
|
fakearg="f")
|
||||||
|
|
||||||
|
scenario._create_floating_ip.assert_called_once_with(
|
||||||
|
fake_floating_ip_pool.name)
|
||||||
|
scenario._associate_floating_ip.assert_called_once_with(
|
||||||
|
fake_server, fake_floating_ip)
|
||||||
scenario.run_command.assert_called_once_with(
|
scenario.run_command.assert_called_once_with(
|
||||||
"fake_server", 'username', "network", "port", "ip_version",
|
fake_floating_ip.ip, 22, 'username',
|
||||||
"interpreter", "script_path")
|
"interpreter", "script_path")
|
||||||
|
|
||||||
mock_json_loads.assert_called_once_with('stdout')
|
mock_json_loads.assert_called_once_with('stdout')
|
||||||
|
|
||||||
scenario._delete_server.assert_called_once_with("fake_server")
|
#scenario._dissociate_floating_ip.assert_called_once_with(
|
||||||
|
# fake_server, fake_floating_ip)
|
||||||
|
#scenario._delete_floating_ip.assert_called_once_with(fake_floating_ip)
|
||||||
|
scenario._release_server_floating_ip.assert_called_once_with(
|
||||||
|
fake_server, fake_floating_ip)
|
||||||
|
scenario._delete_server.assert_called_once_with(fake_server)
|
||||||
|
|
||||||
|
@mock.patch("json.loads")
|
||||||
|
def test_boot_runcommand_delete_no_floating_ip(self, mock_json_loads):
|
||||||
|
# Setup mocks
|
||||||
|
scenario = vmtasks.VMTasks()
|
||||||
|
fake_server = fakes.FakeServer()
|
||||||
|
fake_server.addresses = dict(
|
||||||
|
private=[dict(
|
||||||
|
version=4,
|
||||||
|
addr="1.2.3.4"
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
|
||||||
|
scenario._boot_server = mock.MagicMock(return_value=fake_server)
|
||||||
|
|
||||||
|
scenario._generate_random_name = mock.MagicMock(return_value="name")
|
||||||
|
|
||||||
|
scenario.run_command = mock.MagicMock()
|
||||||
|
scenario.run_command.return_value = (0, 'stdout', 'stderr')
|
||||||
|
scenario._delete_server = mock.MagicMock()
|
||||||
|
|
||||||
|
# Run scenario
|
||||||
|
scenario.boot_runcommand_delete(
|
||||||
|
"image_id", "flavour_id", "script_path", "interpreter",
|
||||||
|
fixed_network='private', floating_network='public',
|
||||||
|
username="username", ip_version=4,
|
||||||
|
port=22, use_floatingip=False, fakearg="f")
|
||||||
|
|
||||||
|
# Assertions
|
||||||
|
scenario._boot_server.assert_called_once_with(
|
||||||
|
'name', 'image_id', "flavour_id", key_name="rally_ssh_key",
|
||||||
|
fakearg="f")
|
||||||
|
|
||||||
|
scenario.run_command.assert_called_once_with(
|
||||||
|
fake_server.addresses['private'][0]['addr'], 22, 'username',
|
||||||
|
"interpreter", "script_path")
|
||||||
|
|
||||||
|
mock_json_loads.assert_called_once_with('stdout')
|
||||||
|
|
||||||
|
scenario._delete_server.assert_called_once_with(fake_server)
|
||||||
|
|
||||||
|
def test__release_server_floating_ip(self):
|
||||||
|
scenario = vmtasks.VMTasks()
|
||||||
|
fake_server = fakes.FakeServer()
|
||||||
|
fake_floating_ip = fakes.FakeFloatingIP()
|
||||||
|
|
||||||
|
scenario._dissociate_floating_ip = mock.MagicMock()
|
||||||
|
scenario._delete_floating_ip = mock.MagicMock()
|
||||||
|
scenario.check_ip_address = mock.MagicMock(
|
||||||
|
return_value=mock.MagicMock(return_value=True))
|
||||||
|
|
||||||
|
scenario._release_server_floating_ip(fake_server, fake_floating_ip)
|
||||||
|
|
||||||
|
scenario._dissociate_floating_ip.assert_called_once_with(
|
||||||
|
fake_server, fake_floating_ip)
|
||||||
|
scenario._delete_floating_ip.assert_called_once_with(fake_floating_ip)
|
||||||
|
@ -260,6 +260,118 @@ class ValidationUtilsTestCase(test.TestCase):
|
|||||||
self.assertFalse(result.is_valid)
|
self.assertFalse(result.is_valid)
|
||||||
self.assertEqual(result.msg, "Image with id 'test_image_id' not found")
|
self.assertEqual(result.msg, "Image with id 'test_image_id' not found")
|
||||||
|
|
||||||
|
@mock.patch("rally.osclients.Clients")
|
||||||
|
def test_network_exists(self, mock_osclients):
|
||||||
|
fakenclient = fakes.FakeNovaClient()
|
||||||
|
fake_network = fakes.FakeNetwork()
|
||||||
|
fake_network.label = "private"
|
||||||
|
fake_network.id = "net_id_1234"
|
||||||
|
|
||||||
|
fakenclient.networks.list = mock.MagicMock(
|
||||||
|
return_value=[fake_network])
|
||||||
|
mock_osclients.nova.return_value = fakenclient
|
||||||
|
|
||||||
|
validator = validation.network_exists("fixed_network")
|
||||||
|
|
||||||
|
network_name = "private"
|
||||||
|
|
||||||
|
result = validator(clients=mock_osclients,
|
||||||
|
fixed_network=network_name)
|
||||||
|
|
||||||
|
fakenclient.networks.list.assert_called_once_with()
|
||||||
|
self.assertTrue(result.is_valid)
|
||||||
|
self.assertIsNone(result.msg)
|
||||||
|
|
||||||
|
@mock.patch("rally.osclients.Clients")
|
||||||
|
def test_network_exists_fail(self, mock_osclients):
|
||||||
|
fakenclient = fakes.FakeNovaClient()
|
||||||
|
fake_network = fakes.FakeNetwork()
|
||||||
|
fake_network.label = "private"
|
||||||
|
fake_network.id = "net_id_1234"
|
||||||
|
|
||||||
|
fakenclient.networks.list = mock.MagicMock(
|
||||||
|
return_value=[fake_network])
|
||||||
|
mock_osclients.nova.return_value = fakenclient
|
||||||
|
|
||||||
|
validator = validation.network_exists("fixed_network")
|
||||||
|
|
||||||
|
network_name = "foo"
|
||||||
|
|
||||||
|
result = validator(clients=mock_osclients,
|
||||||
|
fixed_network=network_name)
|
||||||
|
|
||||||
|
fakenclient.networks.list.assert_called_once_with()
|
||||||
|
self.assertFalse(result.is_valid)
|
||||||
|
self.assertEqual(result.msg,
|
||||||
|
"Network with name foo not found. "
|
||||||
|
"Available networks: ['private']")
|
||||||
|
|
||||||
|
@mock.patch("rally.osclients.Clients")
|
||||||
|
def test_external_network_exists(self, mock_osclients):
|
||||||
|
fakenclient = fakes.FakeNovaClient()
|
||||||
|
fake_pool = fakes.FakeFloatingIPPool()
|
||||||
|
fake_pool.name = "floating"
|
||||||
|
fakenclient.floating_ip_pools.list = mock.MagicMock(
|
||||||
|
return_value=[fake_pool])
|
||||||
|
mock_osclients.nova.return_value = fakenclient
|
||||||
|
|
||||||
|
validator = validation.external_network_exists("floating_network",
|
||||||
|
"use_floatingip")
|
||||||
|
|
||||||
|
network_name = "floating"
|
||||||
|
|
||||||
|
result = validator(clients=mock_osclients,
|
||||||
|
floating_network=network_name)
|
||||||
|
|
||||||
|
fakenclient.floating_ip_pools.list.assert_called_once_with()
|
||||||
|
self.assertTrue(result.is_valid)
|
||||||
|
self.assertIsNone(result.msg)
|
||||||
|
|
||||||
|
@mock.patch("rally.osclients.Clients")
|
||||||
|
def test_external_network_exists_ignored(self, mock_osclients):
|
||||||
|
fakenclient = fakes.FakeNovaClient()
|
||||||
|
fake_pool = fakes.FakeFloatingIPPool()
|
||||||
|
fake_pool.name = "floating"
|
||||||
|
fakenclient.floating_ip_pools.list = mock.MagicMock(
|
||||||
|
return_value=[fake_pool])
|
||||||
|
mock_osclients.nova.return_value = fakenclient
|
||||||
|
|
||||||
|
validator = validation.external_network_exists("floating_network",
|
||||||
|
"use_floatingip")
|
||||||
|
|
||||||
|
network_name = "not_used"
|
||||||
|
|
||||||
|
result = validator(clients=mock_osclients,
|
||||||
|
floating_network=network_name,
|
||||||
|
use_floatingip=False)
|
||||||
|
|
||||||
|
self.assertFalse(fakenclient.floating_ip_pools.list.called)
|
||||||
|
self.assertTrue(result.is_valid)
|
||||||
|
self.assertIsNone(result.msg)
|
||||||
|
|
||||||
|
@mock.patch("rally.osclients.Clients")
|
||||||
|
def test_external_network_exists_fail(self, mock_osclients):
|
||||||
|
fakenclient = fakes.FakeNovaClient()
|
||||||
|
fake_pool = fakes.FakeFloatingIPPool()
|
||||||
|
fake_pool.name = "floating"
|
||||||
|
fakenclient.floating_ip_pools.list = mock.MagicMock(
|
||||||
|
return_value=[fake_pool])
|
||||||
|
mock_osclients.nova.return_value = fakenclient
|
||||||
|
|
||||||
|
validator = validation.external_network_exists("floating_network",
|
||||||
|
"use_floatingip")
|
||||||
|
|
||||||
|
network_name = "foo"
|
||||||
|
|
||||||
|
result = validator(clients=mock_osclients,
|
||||||
|
floating_network=network_name)
|
||||||
|
|
||||||
|
fakenclient.floating_ip_pools.list.assert_called_once_with()
|
||||||
|
self.assertFalse(result.is_valid)
|
||||||
|
self.assertEqual(result.msg, "External (floating) network with name "
|
||||||
|
"foo not found. "
|
||||||
|
"Available networks: ['floating']")
|
||||||
|
|
||||||
@mock.patch("rally.osclients.Clients")
|
@mock.patch("rally.osclients.Clients")
|
||||||
def test_image_valid_on_flavor_flavor_not_exist(self, mock_osclients):
|
def test_image_valid_on_flavor_flavor_not_exist(self, mock_osclients):
|
||||||
fakegclient = fakes.FakeGlanceClient()
|
fakegclient = fakes.FakeGlanceClient()
|
||||||
|
@ -134,6 +134,10 @@ class FakeFloatingIP(FakeResource):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FakeFloatingIPPool(FakeResource):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FakeTenant(FakeResource):
|
class FakeTenant(FakeResource):
|
||||||
|
|
||||||
def __init__(self, manager, name):
|
def __init__(self, manager, name):
|
||||||
@ -337,6 +341,12 @@ class FakeFloatingIPsManager(FakeManager):
|
|||||||
return FakeFloatingIP(self)
|
return FakeFloatingIP(self)
|
||||||
|
|
||||||
|
|
||||||
|
class FakeFloatingIPPoolsManager(FakeManager):
|
||||||
|
|
||||||
|
def create(self):
|
||||||
|
return FakeFloatingIPPool(self)
|
||||||
|
|
||||||
|
|
||||||
class FakeTenantsManager(FakeManager):
|
class FakeTenantsManager(FakeManager):
|
||||||
|
|
||||||
def create(self, name):
|
def create(self, name):
|
||||||
@ -565,6 +575,7 @@ class FakeNovaClient(object):
|
|||||||
else:
|
else:
|
||||||
self.servers = FakeServerManager(self.images)
|
self.servers = FakeServerManager(self.images)
|
||||||
self.floating_ips = FakeFloatingIPsManager()
|
self.floating_ips = FakeFloatingIPsManager()
|
||||||
|
self.floating_ip_pools = FakeFloatingIPPoolsManager()
|
||||||
self.networks = FakeNetworkManager()
|
self.networks = FakeNetworkManager()
|
||||||
self.flavors = FakeFlavorManager()
|
self.flavors = FakeFlavorManager()
|
||||||
self.keypairs = FakeKeypairManager()
|
self.keypairs = FakeKeypairManager()
|
||||||
|
@ -104,7 +104,7 @@ class SSHTestCase(test.TestCase):
|
|||||||
mock.call.set_missing_host_key_policy('autoadd'),
|
mock.call.set_missing_host_key_policy('autoadd'),
|
||||||
mock.call.connect('example.net', username='admin',
|
mock.call.connect('example.net', username='admin',
|
||||||
port=22, pkey='key', key_filename=None,
|
port=22, pkey='key', key_filename=None,
|
||||||
password=None),
|
password=None, timeout=1),
|
||||||
]
|
]
|
||||||
self.assertEqual(client_calls, client.mock_calls)
|
self.assertEqual(client_calls, client.mock_calls)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user