ostf-117-141 Network Client for Nova

* network_client.py: new NovaNetworkClient added
  * test.py, manager.py, clients/py were updated
    to silently apply appropriate network client
  * base.py, test_sanity_* were updated to use
    new network client and to use new
    fuel_health structure of modules
This commit is contained in:
Sergey Lyopka 2013-07-01 17:21:59 +03:00
parent c550ae958b
commit 9136a05077
8 changed files with 96 additions and 33 deletions

View File

@ -39,7 +39,8 @@ from fuel_health.services.compute.json.tenant_usages_client import \
TenantUsagesClientJSON TenantUsagesClientJSON
from fuel_health.services.identity.json.identity_client import IdentityClientJSON from fuel_health.services.identity.json.identity_client import IdentityClientJSON
from fuel_health.services.identity.json.identity_client import TokenClientJSON from fuel_health.services.identity.json.identity_client import TokenClientJSON
from fuel_health.services.network.json.network_client import NetworkClient from fuel_health.services.network.json.network_client import NovaNetworkClient
from fuel_health.services.network.json.network_client import QuantumNetworkClient
from fuel_health.services.volume.json.admin.volume_types_client import \ from fuel_health.services.volume.json.admin.volume_types_client import \
VolumeTypesClientJSON VolumeTypesClientJSON
@ -51,7 +52,7 @@ LOG = logging.getLogger(__name__)
IMAGES_CLIENTS = { IMAGES_CLIENTS = {
"json": ImagesClientJSON, "json": ImagesClientJSON,
} }
KEYPAIRS_CLIENTS = { KEYPAIRS_CLIENTS = {
"json": KeyPairsClientJSON, "json": KeyPairsClientJSON,
@ -206,6 +207,10 @@ class Manager(object):
except KeyError: except KeyError:
msg = "Unsupported interface type `%s'" % interface msg = "Unsupported interface type `%s'" % interface
raise exceptions.InvalidConfiguration(msg) raise exceptions.InvalidConfiguration(msg)
NetworkClient = QuantumNetworkClient
if not self.config.network.quantum_available:
NetworkClient = NovaNetworkClient
self.network_client = NetworkClient(*client_args) self.network_client = NetworkClient(*client_args)
self.hosts_client = HostsClientJSON(*client_args) self.hosts_client = HostsClientJSON(*client_args)

View File

@ -32,7 +32,6 @@ from fuel_health.services.network.json import network_client
from fuel_health.services.volume.json import snapshots_client from fuel_health.services.volume.json import snapshots_client
from fuel_health.services.volume.json import volumes_client from fuel_health.services.volume.json import volumes_client
NetworkClient = network_client.NetworkClient
ImagesClient = images_client.ImagesClientJSON ImagesClient = images_client.ImagesClientJSON
FlavorsClient = flavors_client.FlavorsClientJSON FlavorsClient = flavors_client.FlavorsClientJSON
ServersClient = servers_client.ServersClientJSON ServersClient = servers_client.ServersClientJSON
@ -44,6 +43,9 @@ VolumesClient = volumes_client.VolumesClientJSON
SnapshotsClient = snapshots_client.SnapshotsClientJSON SnapshotsClient = snapshots_client.SnapshotsClientJSON
QuotasClient = quotas_client.QuotasClientJSON QuotasClient = quotas_client.QuotasClientJSON
HypervisorClient = hypervisor_client.HypervisorClientJSON HypervisorClient = hypervisor_client.HypervisorClientJSON
NetworkClient = network_client.QuantumNetworkClient
if not fuel_health.config.FuelConfig().network.quantum_available:
NetworkClient = network_client.NovaNetworkClient
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)

View File

@ -2,7 +2,62 @@ import json
from fuel_health.common.rest_client import RestClient from fuel_health.common.rest_client import RestClient
class NetworkClient(RestClient): class NovaNetworkClient(RestClient):
"""
REST client for Compute allows manipulate network data.
Uses v2 of the Compute API.
"""
def __init__(self, config, username, password, auth_url, tenant_name=None):
super(NovaNetworkClient, self).__init__(config, username, password,
auth_url, tenant_name)
self.service = self.config.compute.catalog_type
def list_networks(self):
resp, body = self.get("os-networks")
body = json.loads(body)
return resp, body
def create_network(self, label):
body = {
'network': {
'label': label,
}
}
body = json.dumps(body)
resp, body = self.post("os-networks/add", body, self.headers)
body = json.loads(body)
return resp, body
def show_network(self, uuid):
resp, body = self.get("/os-networks/%s" % uuid)
body = json.loads(body)
return resp, body
def delete_network(self, uuid):
resp, body = self.delete("/os-networks/%s" % uuid, self.headers)
return resp, body
def list_ports(self):
ports = {u'ports': []}
resp, body = self.get("os-networks")
networks = json.loads(body)[u'networks']
ports[u'ports'] = [{net['id']: net['vpn_public_port']}
for net in networks]
return resp, ports
def show_port(self, port_id):
ports = {u'ports': []}
resp, body = self.get("os-networks")
networks = json.loads(body)[u'networks']
ports[u'ports'] = [{net['id']: net['vpn_public_port']}
for net in networks
if net['vpn_public_port'] == port_id]
return resp, ports
class QuantumNetworkClient(RestClient):
""" """
REST client for Quantum. Uses v2 of the Quantum API, since the REST client for Quantum. Uses v2 of the Quantum API, since the
@ -18,7 +73,7 @@ class NetworkClient(RestClient):
""" """
def __init__(self, config, username, password, auth_url, tenant_name=None): def __init__(self, config, username, password, auth_url, tenant_name=None):
super(NetworkClient, self).__init__(config, username, password, super(QuantumNetworkClient, self).__init__(config, username, password,
auth_url, tenant_name) auth_url, tenant_name)
self.service = self.config.network.catalog_type self.service = self.config.network.catalog_type
self.version = '2.0' self.version = '2.0'

View File

@ -42,10 +42,10 @@ def _raise_TimeOut(sig, stack):
raise TimeOutError() raise TimeOutError()
class timeout(object): class ExecutionTimeout(object):
""" """
Timeout context that will stop code running within context Timeout context that will stop code running within context
if timeout is reached if timeout (sec) is reached
>>with timeout(2): >>with timeout(2):
... requests.get("http://msdn.com") ... requests.get("http://msdn.com")

View File

@ -304,8 +304,6 @@ class BaseNetworkTest(BaseIdentityAdminTest):
def setUpClass(cls): def setUpClass(cls):
os = clients.AdminManager() os = clients.AdminManager()
cls.network_cfg = os.config.network cls.network_cfg = os.config.network
if not cls.network_cfg.quantum_available:
raise cls.skipException("Quantum support is required")
cls.client = os.network_client cls.client = os.network_client
cls.networks = [] cls.networks = []
cls.subnets = [] cls.subnets = []

View File

@ -105,7 +105,7 @@ class SanityComputeTest(base.BaseComputeTest):
3. Check response contains absolute limits in "limits" section. 3. Check response contains absolute limits in "limits" section.
""" """
resp, body = self.limits_client.get_absolute_limits() resp, body = self.limits_client.get_absolute_limits()
self.verify_response_status(resp.status, 'Compute') self.verify_response_status(resp.status, 'Cinder')
self.verify_response_body(body["limits"], u'absolute', self.verify_response_body(body["limits"], u'absolute',
'Limits are unavailable. ' 'Limits are unavailable. '
'Looks like something broken in Compute.') 'Looks like something broken in Cinder.')

View File

@ -1,5 +1,7 @@
from fuel_health.common.ssh import Client as SSHClient from fuel_health.common.ssh import Client as SSHClient
from fuel_health.exceptions import SSHExecCommandFailed
from fuel_health.test import attr from fuel_health.test import attr
from fuel_health.test import ExecutionTimeout
from fuel_health.tests.sanity import base from fuel_health.tests.sanity import base
@ -53,8 +55,9 @@ class SanityInfrastructureTest(base.BaseComputeAdminTest):
4. Check number of normally executed services (with :-) state 4. Check number of normally executed services (with :-) state
is equal to the number of expected services is equal to the number of expected services
""" """
output = SSHClient(self.host, self.usr, self.pwd).exec_command( with ExecutionTimeout(5):
"nova-manage service list") output = SSHClient(self.host, self.usr, self.pwd).exec_command(
"nova-manage service list")
self.assertFalse(u'XXX' in output) self.assertFalse(u'XXX' in output)
self.assertEqual(len(self.list_of_expected_services), self.assertEqual(len(self.list_of_expected_services),
output.count(u':-)'), output.count(u':-)'),
@ -82,11 +85,12 @@ class SanityInfrastructureTest(base.BaseComputeAdminTest):
was successfully resolved. was successfully resolved.
""" """
output = '' output = ''
try: expected_output = "in-addr.arpa domain name pointer " + self.hostname
output = SSHClient(self.host, self.usr, self.pwd).exec_command( with ExecutionTimeout(10):
"host " + self.host) try:
finally: output = SSHClient(self.host, self.usr, self.pwd).exec_command(
expected_output = 'in-addr.arpa domain name pointer ' + \ "host " + self.host)
self.hostname except SSHExecCommandFailed:
self.assertTrue(expected_output in output, output = "'host' command failed."
'DNS name cannot be resolved') self.assertTrue(expected_output in output,
'DNS name cannot be resolved')

View File

@ -5,41 +5,40 @@ from fuel_health.tests.sanity import base
class NetworksTest(base.BaseNetworkTest): class NetworksTest(base.BaseNetworkTest):
""" """
TestClass contains tests check base networking functionality TestClass contains tests check base networking functionality
Special requirements: Quantum section should be on in the config
""" """
@attr(type=['sanity', 'fuel']) @attr(type=['sanity', 'fuel'])
def test_list_networks(self): def test_list_networks(self):
""" """
Test checks list of networks is available. Test checks list of networks is available.
Target component: Quantum Target component: Neutron or Nova
Special requirements: Quantum section should be on in the config
Scenario: Scenario:
1. Request list of networks. 1. Request list of networks.
2. Check response status is equal to 200. 2. Check response status is positive.
3. Check response contains "networks" section. 3. Check response contains "networks" section.
""" """
resp, body = self.client.list_networks() resp, body = self.client.list_networks()
self.verify_response_status(resp.status, u'Quantum') self.verify_response_status(resp.status, u'Network (Neutron or Nova)')
self.verify_response_body(body, u'networks', self.verify_response_body(body, u'networks',
'Network list is unavailable. ' "Network list is unavailable. "
'Looks like something broken in Quantum.') "Looks like something broken in Network "
"(Neutron or Nova).")
@attr(type=['sanity', 'fuel']) @attr(type=['sanity', 'fuel'])
def test_list_ports(self): def test_list_ports(self):
""" """
Test checks list of ports is available. Test checks list of ports is available.
Target component: Quantum Target component: Neutron or Nova
Special requirements: Quantum section should be on in the config
Scenario: Scenario:
1. Request list of ports. 1. Request list of ports.
2. Check response status is equal to 200. 2. Check response status is positive.
3. Check response contains "ports" section. 3. Check response contains "ports" section.
""" """
resp, body = self.client.list_ports() resp, body = self.client.list_ports()
self.verify_response_status(resp.status, u'Quantum') self.verify_response_status(resp.status, u'Network (Neutron or Nova)')
self.verify_response_body(body, u'ports', self.verify_response_body(body, u'ports',
'Ports list is unavailable. ' 'Ports list is unavailable. '
'Looks like something broken in Quantum.') 'Looks like something broken in Network '
'(Neutron or Nova).')