Implement network agents

This commit adds api support for network agents.

Change-Id: I9755637f76787d5fac8ff295ae273b308fcb98d0
Implements: blueprint implement-network-agents
This commit is contained in:
Michael Gugino 2016-05-12 16:08:35 -04:00
parent 13e94f55e9
commit 83aef9c8a0
9 changed files with 287 additions and 1 deletions

View File

@ -76,6 +76,19 @@ provide external network access for servers on project networks.
Full example: `network resource list`_
List Network Agents
------------
A **network agent** is a plugin that handles various tasks used to
implement virtual networks. These agents include neutron-dhcp-agent,
neutron-l3-agent, neutron-metering-agent, and neutron-lbaas-agent,
among others.
.. literalinclude:: ../examples/network/list.py
:pyobject: list_network_agents
Full example: `network resource list`_
Create Network
--------------
@ -100,4 +113,4 @@ Full example: `network resource delete`_
.. _network resource create: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/network/create.py
.. _network resource delete: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/network/delete.py
.. _network resource list: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/network/list.py
.. _network resource list: http://git.openstack.org/cgit/openstack/python-openstacksdk/tree/examples/network/list.py

View File

@ -5,6 +5,7 @@ Network Resources
:maxdepth: 1
v2/address_scope
v2/agent
v2/availability_zone
v2/extension
v2/floating_ip

View File

@ -0,0 +1,12 @@
openstack.network.v2.network
============================
.. automodule:: openstack.network.v2.agent
The Agent Class
-----------------
The ``Agent`` class inherits from :class:`~openstack.resource.Resource`.
.. autoclass:: openstack.network.v2.agent.Agent
:members:

View File

@ -50,3 +50,10 @@ def list_routers(conn):
for router in conn.network.routers():
print(router)
def list_network_agents(conn):
print("List Network Agents:")
for agent in conn.network.agents():
print(agent)

View File

@ -11,6 +11,7 @@
# under the License.
from openstack.network.v2 import address_scope as _address_scope
from openstack.network.v2 import agent as _agent
from openstack.network.v2 import availability_zone
from openstack.network.v2 import extension
from openstack.network.v2 import floating_ip as _floating_ip
@ -122,6 +123,59 @@ class Proxy(proxy.BaseProxy):
address_scope,
**attrs)
def agents(self, **query):
"""Return a generator of network agents
:param kwargs \*\*query: Optional query parameters to be sent to limit
the resources being returned.
:returns: A generator of agents
:rtype: :class:`~openstack.network.v2.agent.Agent`
"""
return self._list(_agent.Agent, paginated=False, **query)
def delete_agent(self, agent, ignore_missing=True):
"""Delete a network agent
:param agent: The value can be the ID of a agent or a
:class:`~openstack.network.v2.agent.Agent` instance.
:param bool ignore_missing: When set to ``False``
:class:`~openstack.exceptions.ResourceNotFound` will be
raised when the agent does not exist.
When set to ``True``, no exception will be set when
attempting to delete a nonexistent agent.
:returns: ``None``
"""
self._delete(_agent.Agent, agent,
ignore_missing=ignore_missing)
def get_agent(self, agent, ignore_missing=True):
"""Get a single network agent
:param agent: The value can be the ID of a agent or a
:class:`~openstack.network.v2.agent.Agent` instance.
:returns: One :class:`~openstack.network.v2.agent.Agent`
:rtype: :class:`~openstack.network.v2.agent.Agent`
:raises: :class:`~openstack.exceptions.ResourceNotFound`
when no resource can be found.
"""
return self._get(_agent.Agent, agent)
def update_agent(self, agent, **attrs):
"""Update a network agent
:param agent: The value can be the ID of a agent or a
:class:`~openstack.network.v2.agent.Agent` instance.
:attrs kwargs: The attributes to update on the agent represented
by ``value``.
:returns: One :class:`~openstack.network.v2.agent.Agent`
:rtype: :class:`~openstack.network.v2.agent.Agent`
"""
return self._update(_agent.Agent, agent, **attrs)
def availability_zones(self):
"""Return a generator of availability zones

View File

@ -0,0 +1,61 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from openstack import format
from openstack.network import network_service
from openstack import resource
class Agent(resource.Resource):
resource_key = 'agent'
resources_key = 'agents'
base_path = '/agents'
service = network_service.NetworkService()
# capabilities
allow_create = False
allow_retrieve = True
allow_update = True
allow_delete = True
allow_list = True
# Properties
#: The type of network agent.
agent_type = resource.prop('agent_type')
#: Availability zone for the network agent.
availability_zone = resource.prop('availability_zone')
#: The name of the network agent's application binary.
binary = resource.prop('binary')
#: Network agent configuration data specific to the agent_type.
configuration = resource.prop('configurations')
#: Timestamp when the network agent was created.
#: *Type: datetime object parsed from ISO 8601 formatted string*
created_at = resource.prop('created_at', type=format.ISO8601)
#: The network agent description.
description = resource.prop('description')
#: Timestamp when the network agent's heartbeat was last seen.
#: *Type: datetime object parsed from ISO 8601 formatted string*
last_heartbeat_at = resource.prop('heartbeat_timestamp',
type=format.ISO8601)
#: The host the agent is running on.
host = resource.prop('host')
#: The administrative state of the network agent, which is up
#: ``True`` or down ``False``. *Type: bool*
is_admin_state_up = resource.prop('admin_state_up', type=bool)
#: Whether or not the network agent is alive.
#: *Type: bool*
is_alive = resource.prop('alive', type=bool)
#: Timestamp when the network agent was last started.
#: *Type: datetime object parsed from ISO 8601 formatted string*
started_at = resource.prop('started_at', type=format.ISO8601)
#: The messaging queue topic the network agent subscribes to.
topic = resource.prop('topic')

View File

@ -0,0 +1,51 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import uuid
from openstack.network.v2 import agent
from openstack.tests.functional import base
class TestAgent(base.BaseFunctionalTest):
AGENT = None
DESC = 'test descrition'
def validate_uuid(self, s):
try:
uuid.UUID(s)
except Exception:
return False
return True
@classmethod
def setUpClass(cls):
super(TestAgent, cls).setUpClass()
agent_list = list(cls.conn.network.agents())
cls.AGENT = agent_list[0]
assert isinstance(cls.AGENT, agent.Agent)
def test_list(self):
agent_list = list(self.conn.network.agents())
self.AGENT = agent_list[0]
assert isinstance(self.AGENT, agent.Agent)
self.assertTrue(self.validate_uuid(self.AGENT.id))
def test_get(self):
sot = self.conn.network.get_agent(self.AGENT.id)
self.assertEqual(self.AGENT.id, sot.id)
def test_update(self):
sot = self.conn.network.update_agent(self.AGENT.id,
description=self.DESC)
self.assertEqual(self.DESC, sot.description)

View File

@ -0,0 +1,73 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import datetime
import testtools
from openstack.network.v2 import agent
IDENTIFIER = 'IDENTIFIER'
EXAMPLE = {
'admin_state_up': True,
'agent_type': 'Test Agent',
'alive': True,
'availability_zone': 'az1',
'binary': 'test-binary',
'configurations': {'attr1': 'value1', 'attr2': 'value2'},
'created_at': '2016-03-09T12:14:57.233772',
'description': 'test description',
'heartbeat_timestamp': '2016-08-09T12:14:57.233772',
'host': 'test-host',
'id': IDENTIFIER,
'started_at': '2016-07-09T12:14:57.233772',
'topic': 'test-topic'
}
class TestAgent(testtools.TestCase):
def test_basic(self):
sot = agent.Agent()
self.assertEqual('agent', sot.resource_key)
self.assertEqual('agents', sot.resources_key)
self.assertEqual('/agents', sot.base_path)
self.assertEqual('network', sot.service.service_type)
self.assertFalse(sot.allow_create)
self.assertTrue(sot.allow_retrieve)
self.assertTrue(sot.allow_update)
self.assertTrue(sot.allow_delete)
self.assertTrue(sot.allow_list)
def test_make_it(self):
sot = agent.Agent(EXAMPLE)
self.assertTrue(sot.is_admin_state_up)
self.assertEqual(EXAMPLE['agent_type'], sot.agent_type)
self.assertTrue(sot.is_alive)
self.assertEqual(EXAMPLE['availability_zone'],
sot.availability_zone)
self.assertEqual(EXAMPLE['binary'], sot.binary)
self.assertEqual(EXAMPLE['configurations'], sot.configuration)
dt = datetime.datetime(2016, 3, 9, 12, 14, 57, 233772).replace(
tzinfo=None)
self.assertEqual(dt, sot.created_at.replace(tzinfo=None))
self.assertEqual(EXAMPLE['description'], sot.description)
dt = datetime.datetime(2016, 8, 9, 12, 14, 57, 233772).replace(
tzinfo=None)
self.assertEqual(dt,
sot.last_heartbeat_at.replace(tzinfo=None))
self.assertEqual(EXAMPLE['host'], sot.host)
self.assertEqual(EXAMPLE['id'], sot.id)
dt = datetime.datetime(2016, 7, 9, 12, 14, 57, 233772).replace(
tzinfo=None)
self.assertEqual(dt, sot.started_at.replace(tzinfo=None))
self.assertEqual(EXAMPLE['topic'], sot.topic)

View File

@ -14,6 +14,7 @@ import mock
from openstack.network.v2 import _proxy
from openstack.network.v2 import address_scope
from openstack.network.v2 import agent
from openstack.network.v2 import availability_zone
from openstack.network.v2 import extension
from openstack.network.v2 import floating_ip
@ -73,6 +74,19 @@ class TestNetworkProxy(test_proxy_base.TestProxyBase):
self.verify_update(self.proxy.update_address_scope,
address_scope.AddressScope)
def test_agent_delete(self):
self.verify_delete(self.proxy.delete_agent, agent.Agent, True)
def test_agent_get(self):
self.verify_get(self.proxy.get_agent, agent.Agent)
def test_agents(self):
self.verify_list(self.proxy.agents, agent.Agent,
paginated=False)
def test_agent_update(self):
self.verify_update(self.proxy.update_agent, agent.Agent)
def test_availability_zones(self):
self.verify_list_no_kwargs(self.proxy.availability_zones,
availability_zone.AvailabilityZone,