The change implements LBaaS CLI commands.

Implements: blueprint lbaas-cli

New commands:
 * Vip: lb-vip-create, lb-vip-list, lb-vip-show, lb-vip-update,
   lb-vip-delete
 * Pool: lb-pool-create, lb-pool-list, lb-pool-show, lb-pool-update,
   lb-pool-delete, lb-pool-stats
 * Member: lb-member-create, lb-member-list, lb-member-show,
   lb-member-update, lb-member-delete
 * Health Monitor: lb-healthmonitor-create, lb-healthmonitor-list,
   lb-healthmonitor-show, lb-healthmonitor-update, lb-healthmonitor-delete,
   lb-healthmonitor-associate, lb-healthmonitor-disassociate

Change-Id: Idaa569024c24955886a836e3dfedd009fed87007
This commit is contained in:
Ilya Shakhat
2012-12-19 17:40:00 +04:00
parent 9f1858d0f1
commit 2bca8ee440
15 changed files with 1409 additions and 5 deletions

View File

@@ -141,7 +141,10 @@ def parse_args_to_dict(values_specs):
current_arg = _options[_item]
_item = _temp
elif _item.startswith('type='):
if current_arg is not None:
if current_arg is None:
raise exceptions.CommandError(
"invalid values_specs %s" % ' '.join(values_specs))
if 'type' not in current_arg:
_type_str = _item.split('=', 2)[1]
current_arg.update({'type': eval(_type_str)})
if _type_str == 'bool':
@@ -149,9 +152,6 @@ def parse_args_to_dict(values_specs):
elif _type_str == 'dict':
current_arg.update({'type': utils.str2dict})
continue
else:
raise exceptions.CommandError(
"invalid values_specs %s" % ' '.join(values_specs))
elif _item == 'list=true':
_list_flag = True
continue
@@ -212,6 +212,12 @@ def _merge_args(qCmd, parsed_args, _extra_values, value_specs):
_extra_values.pop(key)
def update_dict(obj, dict, attributes):
for attribute in attributes:
if hasattr(obj, attribute) and getattr(obj, attribute):
dict[attribute] = getattr(obj, attribute)
class QuantumCommand(command.OpenStackCommand):
api = 'network'
log = logging.getLogger(__name__ + '.QuantumCommand')

View File

@@ -0,0 +1,16 @@
# Copyright 2013 OpenStack LLC.
# All Rights Reserved
#
# 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.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4

View File

@@ -0,0 +1,172 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import logging
from quantumclient.quantum import v2_0 as quantumv20
class ListHealthMonitor(quantumv20.ListCommand):
"""List healthmonitors that belong to a given tenant."""
resource = 'health_monitor'
log = logging.getLogger(__name__ + '.ListHealthMonitor')
list_columns = ['id', 'type', 'admin_state_up', 'status']
_formatters = {}
class ShowHealthMonitor(quantumv20.ShowCommand):
"""Show information of a given healthmonitor."""
resource = 'health_monitor'
log = logging.getLogger(__name__ + '.ShowHealthMonitor')
class CreateHealthMonitor(quantumv20.CreateCommand):
"""Create a healthmonitor"""
resource = 'health_monitor'
log = logging.getLogger(__name__ + '.CreateHealthMonitor')
def add_known_arguments(self, parser):
parser.add_argument(
'--admin-state-down',
default=True, action='store_false',
help='set admin state up to false')
parser.add_argument(
'--delay',
required=True,
help='the minimum time in seconds between regular connections '
'of the member.')
parser.add_argument(
'--expected-codes',
help='the list of HTTP status codes expected in '
'response from the member to declare it healthy. This '
'attribute can contain one value, '
'or a list of values separated by comma, '
'or a range of values (e.g. "200-299"). If this attribute '
'is not specified, it defaults to "200". ')
parser.add_argument(
'--http-method',
help='the HTTP method used for requests by the monitor of type '
'HTTP.')
parser.add_argument(
'--max-retries',
required=True,
help='number of permissible connection failures before changing '
'the member status to INACTIVE.')
parser.add_argument(
'--timeout',
required=True,
help='maximum number of seconds for a monitor to wait for a '
'connection to be established before it times out. The '
'value must be less than the delay value.')
parser.add_argument(
'--type',
required=True,
help='one of predefined health monitor types, e.g. RoundRobin')
parser.add_argument(
'--url-path',
help='the HTTP path used in the HTTP request used by the monitor'
' to test a member health. This must be a string '
'beginning with a / (forward slash)')
def args2body(self, parsed_args):
body = {
self.resource: {
'admin_state_up': parsed_args.admin_state_down,
'delay': parsed_args.delay,
'max_retries': parsed_args.max_retries,
'timeout': parsed_args.timeout,
'type': parsed_args.type,
},
}
quantumv20.update_dict(parsed_args, body[self.resource],
['expected_codes', 'http_method', 'url_path',
'tenant_id'])
return body
class UpdateHealthMonitor(quantumv20.UpdateCommand):
"""Update a given healthmonitor."""
resource = 'health_monitor'
log = logging.getLogger(__name__ + '.UpdateHealthMonitor')
class DeleteHealthMonitor(quantumv20.DeleteCommand):
"""Delete a given healthmonitor."""
resource = 'health_monitor'
log = logging.getLogger(__name__ + '.DeleteHealthMonitor')
class AssociateHealthMonitor(quantumv20.QuantumCommand):
"""Create a mapping between a health monitor and a pool."""
log = logging.getLogger(__name__ + '.AssociateHealthMonitor')
resource = 'health_monitor'
def get_parser(self, prog_name):
parser = super(AssociateHealthMonitor, self).get_parser(prog_name)
parser.add_argument(
'health_monitor_id',
help='Health monitor to associate')
parser.add_argument(
'pool_id',
help='ID of the pool to be associated with the health monitor')
return parser
def run(self, parsed_args):
quantum_client = self.get_client()
quantum_client.format = parsed_args.request_format
body = {'health_monitor': {'id': parsed_args.health_monitor_id}}
pool_id = quantumv20.find_resourceid_by_name_or_id(
quantum_client, 'pool', parsed_args.pool_id)
quantum_client.associate_health_monitor(pool_id, body)
print >>self.app.stdout, (_('Associated health monitor '
'%s') % parsed_args.health_monitor_id)
class DisassociateHealthMonitor(quantumv20.QuantumCommand):
"""Remove a mapping from a health monitor to a pool."""
log = logging.getLogger(__name__ + '.DisassociateHealthMonitor')
resource = 'health_monitor'
def get_parser(self, prog_name):
parser = super(DisassociateHealthMonitor, self).get_parser(prog_name)
parser.add_argument(
'health_monitor_id',
help='Health monitor to associate')
parser.add_argument(
'pool_id',
help='ID of the pool to be associated with the health monitor')
return parser
def run(self, parsed_args):
quantum_client = self.get_client()
quantum_client.format = parsed_args.request_format
pool_id = quantumv20.find_resourceid_by_name_or_id(
quantum_client, 'pool', parsed_args.pool_id)
quantum_client.disassociate_health_monitor(pool_id,
parsed_args
.health_monitor_id)
print >>self.app.stdout, (_('Disassociated health monitor '
'%s') % parsed_args.health_monitor_id)

View File

@@ -0,0 +1,93 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import logging
from quantumclient.quantum import v2_0 as quantumv20
class ListMember(quantumv20.ListCommand):
"""List members that belong to a given tenant."""
resource = 'member'
log = logging.getLogger(__name__ + '.ListMember')
list_columns = ['id', 'address', 'port', 'admin_state_up', 'status']
_formatters = {}
class ShowMember(quantumv20.ShowCommand):
"""Show information of a given member."""
resource = 'member'
log = logging.getLogger(__name__ + '.ShowMember')
class CreateMember(quantumv20.CreateCommand):
"""Create a member"""
resource = 'member'
log = logging.getLogger(__name__ + '.CreateMember')
def add_known_arguments(self, parser):
parser.add_argument(
'pool_id', metavar='pool',
help='Pool id or name this vip belongs to')
parser.add_argument(
'--address',
required=True,
help='IP address of the pool member on the pool network. ')
parser.add_argument(
'--admin-state-down',
default=True, action='store_false',
help='set admin state up to false')
parser.add_argument(
'--port',
required=True,
help='port on which the pool member listens for requests or '
'connections. ')
parser.add_argument(
'--weight',
help='weight of pool member in the pool')
def args2body(self, parsed_args):
_pool_id = quantumv20.find_resourceid_by_name_or_id(
self.get_client(), 'pool', parsed_args.pool_id)
body = {
self.resource: {
'pool_id': _pool_id,
'admin_state_up': parsed_args.admin_state_down,
},
}
quantumv20.update_dict(parsed_args, body[self.resource],
['address', 'port', 'weight', 'tenant_id'])
return body
class UpdateMember(quantumv20.UpdateCommand):
"""Update a given member."""
resource = 'member'
log = logging.getLogger(__name__ + '.UpdateMember')
class DeleteMember(quantumv20.DeleteCommand):
"""Delete a given member."""
resource = 'member'
log = logging.getLogger(__name__ + '.DeleteMember')

View File

@@ -0,0 +1,120 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import logging
from quantumclient.quantum import v2_0 as quantumv20
class ListPool(quantumv20.ListCommand):
"""List pools that belong to a given tenant."""
resource = 'pool'
log = logging.getLogger(__name__ + '.ListPool')
list_columns = ['id', 'name', 'lb_method', 'protocol',
'admin_state_up', 'status']
_formatters = {}
class ShowPool(quantumv20.ShowCommand):
"""Show information of a given pool."""
resource = 'pool'
log = logging.getLogger(__name__ + '.ShowPool')
class CreatePool(quantumv20.CreateCommand):
"""Create a pool"""
resource = 'pool'
log = logging.getLogger(__name__ + '.CreatePool')
def add_known_arguments(self, parser):
parser.add_argument(
'--admin-state-down',
default=True, action='store_false',
help='set admin state up to false')
parser.add_argument(
'--description',
help='description of the pool')
parser.add_argument(
'--lb-method',
required=True,
help='the algorithm used to distribute load between the members '
'of the pool')
parser.add_argument(
'--name',
required=True,
help='the name of the pool')
parser.add_argument(
'--protocol',
required=True,
help='protocol for balancing')
parser.add_argument(
'--subnet-id',
required=True,
help='the subnet on which the members of the pool will be located')
def args2body(self, parsed_args):
body = {
self.resource: {
'admin_state_up': parsed_args.admin_state_down,
},
}
quantumv20.update_dict(parsed_args, body[self.resource],
['description', 'lb_method', 'name',
'subnet_id', 'protocol', 'tenant_id'])
return body
class UpdatePool(quantumv20.UpdateCommand):
"""Update a given pool."""
resource = 'pool'
log = logging.getLogger(__name__ + '.UpdatePool')
class DeletePool(quantumv20.DeleteCommand):
"""Delete a given pool."""
resource = 'pool'
log = logging.getLogger(__name__ + '.DeletePool')
class RetrievePoolStats(quantumv20.ShowCommand):
"""Retrieve stats for a given pool."""
resource = 'pool'
log = logging.getLogger(__name__ + '.RetrievePoolStats')
def get_data(self, parsed_args):
self.log.debug('run(%s)' % parsed_args)
quantum_client = self.get_client()
quantum_client.format = parsed_args.request_format
params = {}
if parsed_args.fields:
params = {'fields': parsed_args.fields}
data = quantum_client.retrieve_pool_stats(parsed_args.id, **params)
self.format_output_data(data)
stats = data['stats']
if 'stats' in data:
return zip(*sorted(stats.iteritems()))
else:
return None

View File

@@ -0,0 +1,111 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import logging
from quantumclient.quantum import v2_0 as quantumv20
class ListVip(quantumv20.ListCommand):
"""List vips that belong to a given tenant."""
resource = 'vip'
log = logging.getLogger(__name__ + '.ListVip')
list_columns = ['id', 'name', 'algorithm', 'protocol',
'admin_state_up', 'status']
_formatters = {}
class ShowVip(quantumv20.ShowCommand):
"""Show information of a given vip."""
resource = 'vip'
log = logging.getLogger(__name__ + '.ShowVip')
class CreateVip(quantumv20.CreateCommand):
"""Create a vip"""
resource = 'vip'
log = logging.getLogger(__name__ + '.CreateVip')
def add_known_arguments(self, parser):
parser.add_argument(
'pool_id', metavar='pool',
help='Pool id or name this vip belongs to')
parser.add_argument(
'--address',
help='IP address of the vip')
parser.add_argument(
'--admin-state-down',
default=True, action='store_false',
help='set admin state up to false')
parser.add_argument(
'--connection-limit',
help='the maximum number of connections per second allowed for '
'the vip')
parser.add_argument(
'--description',
help='description of the vip')
parser.add_argument(
'--name',
required=True,
help='name of the vip')
parser.add_argument(
'--port',
required=True,
help='TCP port on which to listen for client traffic that is '
'associated with the vip address')
parser.add_argument(
'--protocol',
required=True,
help='protocol for balancing')
parser.add_argument(
'--subnet-id',
required=True,
help='the subnet on which to allocate the vip address')
def args2body(self, parsed_args):
_pool_id = quantumv20.find_resourceid_by_name_or_id(
self.get_client(), 'pool', parsed_args.pool_id)
body = {
self.resource: {
'pool_id': _pool_id,
'admin_state_up': parsed_args.admin_state_down,
},
}
quantumv20.update_dict(parsed_args, body[self.resource],
['address', 'connection_limit', 'description',
'name', 'port', 'protocol', 'subnet_id',
'tenant_id'])
return body
class UpdateVip(quantumv20.UpdateCommand):
"""Update a given vip."""
resource = 'vip'
log = logging.getLogger(__name__ + '.UpdateVip')
class DeleteVip(quantumv20.DeleteCommand):
"""Delete a given vip."""
resource = 'vip'
log = logging.getLogger(__name__ + '.DeleteVip')

View File

@@ -145,6 +145,53 @@ COMMAND_V2 = {
'quantumclient.quantum.v2_0.securitygroup.CreateSecurityGroupRule'),
'security-group-rule-delete': utils.import_class(
'quantumclient.quantum.v2_0.securitygroup.DeleteSecurityGroupRule'),
'lb-vip-list': utils.import_class(
'quantumclient.quantum.v2_0.lb.vip.ListVip'),
'lb-vip-show': utils.import_class(
'quantumclient.quantum.v2_0.lb.vip.ShowVip'),
'lb-vip-create': utils.import_class(
'quantumclient.quantum.v2_0.lb.vip.CreateVip'),
'lb-vip-update': utils.import_class(
'quantumclient.quantum.v2_0.lb.vip.UpdateVip'),
'lb-vip-delete': utils.import_class(
'quantumclient.quantum.v2_0.lb.vip.DeleteVip'),
'lb-pool-list': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.ListPool'),
'lb-pool-show': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.ShowPool'),
'lb-pool-create': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.CreatePool'),
'lb-pool-update': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.UpdatePool'),
'lb-pool-delete': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.DeletePool'),
'lb-pool-stats': utils.import_class(
'quantumclient.quantum.v2_0.lb.pool.RetrievePoolStats'),
'lb-member-list': utils.import_class(
'quantumclient.quantum.v2_0.lb.member.ListMember'),
'lb-member-show': utils.import_class(
'quantumclient.quantum.v2_0.lb.member.ShowMember'),
'lb-member-create': utils.import_class(
'quantumclient.quantum.v2_0.lb.member.CreateMember'),
'lb-member-update': utils.import_class(
'quantumclient.quantum.v2_0.lb.member.UpdateMember'),
'lb-member-delete': utils.import_class(
'quantumclient.quantum.v2_0.lb.member.DeleteMember'),
'lb-healthmonitor-list': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.ListHealthMonitor'),
'lb-healthmonitor-show': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.ShowHealthMonitor'),
'lb-healthmonitor-create': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.CreateHealthMonitor'),
'lb-healthmonitor-update': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.UpdateHealthMonitor'),
'lb-healthmonitor-delete': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.DeleteHealthMonitor'),
'lb-healthmonitor-associate': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor.AssociateHealthMonitor'),
'lb-healthmonitor-disassociate': utils.import_class(
'quantumclient.quantum.v2_0.lb.healthmonitor'
'.DisassociateHealthMonitor'),
}
COMMANDS = {'2.0': COMMAND_V2}

View File

@@ -0,0 +1,16 @@
# Copyright 2013 OpenStack LLC.
# All Rights Reserved
#
# 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.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4

View File

@@ -0,0 +1,189 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import sys
from mox import ContainsKeyValue
from quantumclient.quantum.v2_0.lb import healthmonitor
from quantumclient.tests.unit import test_cli20
class CLITestV20LbHealthmonitor(test_cli20.CLITestV20Base):
def test_create_healthmonitor_with_all_params(self):
"""lb-healthmonitor-create with mandatory params only"""
resource = 'health_monitor'
cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
delay = '60'
max_retries = '2'
timeout = '10'
type = 'tcp'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--admin-state-down',
'--delay', delay,
'--max-retries', max_retries,
'--timeout', timeout,
'--type', type,
'--tenant-id', tenant_id]
position_names = ['admin_state_up', 'delay', 'max_retries', 'timeout',
'type', 'tenant_id']
position_values = [True, delay, max_retries, timeout, type,
tenant_id]
self._test_create_resource(resource, cmd, '', my_id, args,
position_names, position_values)
def test_create_healthmonitor_with_all_params(self):
"""lb-healthmonitor-create with all params set"""
resource = 'health_monitor'
cmd = healthmonitor.CreateHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
admin_state_up = False
delay = '60'
expected_codes = '200-202,204'
http_method = 'HEAD'
max_retries = '2'
timeout = '10'
type = 'tcp'
tenant_id = 'my-tenant'
url_path = '/health'
my_id = 'my-id'
args = ['--admin-state-down',
'--delay', delay,
'--expected-codes', expected_codes,
'--http-method', http_method,
'--max-retries', max_retries,
'--timeout', timeout,
'--type', type,
'--tenant-id', tenant_id,
'--url-path', url_path]
position_names = ['admin_state_up', 'delay',
'expected_codes', 'http_method',
'max_retries', 'timeout',
'type', 'tenant_id', 'url_path']
position_values = [admin_state_up, delay,
expected_codes, http_method,
max_retries, timeout,
type, tenant_id, url_path]
self._test_create_resource(resource, cmd, '', my_id, args,
position_names, position_values)
def test_list_healthmonitors(self):
"""lb-healthmonitor-list"""
resources = "health_monitors"
cmd = healthmonitor.ListHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
self._test_list_resources(resources, cmd, True)
def test_show_healthmonitor_id(self):
"""lb-healthmonitor-show test_id"""
resource = 'health_monitor'
cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(resource, cmd, self.test_id, args, ['id'])
def test_show_healthmonitor_id_name(self):
"""lb-healthmonitor-show"""
resource = 'health_monitor'
cmd = healthmonitor.ShowHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(resource, cmd, self.test_id,
args, ['id', 'name'])
def test_update_health_monitor(self):
"""lb-healthmonitor-update myid --name myname --tags a b."""
resource = 'health_monitor'
cmd = healthmonitor.UpdateHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
self._test_update_resource(resource, cmd, 'myid',
['myid', '--timeout', '5'],
{'timeout': '5', })
def test_delete_healthmonitor(self):
"""lb-healthmonitor-delete my-id"""
resource = 'health_monitor'
cmd = healthmonitor.DeleteHealthMonitor(test_cli20.MyApp(sys.stdout),
None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(resource, cmd, my_id, args)
def test_associate_healthmonitor(self):
cmd = healthmonitor.AssociateHealthMonitor(
test_cli20.MyApp(sys.stdout),
None)
resource = 'health_monitor'
health_monitor_id = 'hm-id'
pool_id = 'p_id'
args = [health_monitor_id, pool_id]
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
body = {resource: {'id': health_monitor_id}}
result = {resource: {'id': health_monitor_id}, }
result_str = self.client.serialize(result)
path = getattr(self.client,
"associate_pool_health_monitors_path") % pool_id
return_tup = (test_cli20.MyResp(200), result_str)
self.client.httpclient.request(
test_cli20.end_url(path), 'POST',
body=test_cli20.MyComparator(body, self.client),
headers=ContainsKeyValue('X-Auth-Token',
test_cli20.TOKEN)).AndReturn(return_tup)
self.mox.ReplayAll()
cmd_parser = cmd.get_parser('test_' + resource)
parsed_args = cmd_parser.parse_args(args)
cmd.run(parsed_args)
self.mox.VerifyAll()
self.mox.UnsetStubs()
def test_disassociate_healthmonitor(self):
cmd = healthmonitor.DisassociateHealthMonitor(
test_cli20.MyApp(sys.stdout),
None)
resource = 'health_monitor'
health_monitor_id = 'hm-id'
pool_id = 'p_id'
args = [health_monitor_id, pool_id]
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
path = getattr(self.client,
"disassociate_pool_health_monitors_path") % \
{'pool': pool_id, 'health_monitor': health_monitor_id}
return_tup = (test_cli20.MyResp(204), None)
self.client.httpclient.request(
test_cli20.end_url(path), 'DELETE',
body=None,
headers=ContainsKeyValue('X-Auth-Token',
test_cli20.TOKEN)).AndReturn(return_tup)
self.mox.ReplayAll()
cmd_parser = cmd.get_parser('test_' + resource)
parsed_args = cmd_parser.parse_args(args)
cmd.run(parsed_args)
self.mox.VerifyAll()
self.mox.UnsetStubs()

View File

@@ -0,0 +1,104 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import sys
from quantumclient.quantum.v2_0.lb import member
from quantumclient.tests.unit import test_cli20
class CLITestV20LbMember(test_cli20.CLITestV20Base):
def test_create_member(self):
"""lb-member-create with mandatory params only"""
resource = 'member'
cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None)
address = '10.0.0.1'
port = '8080'
tenant_id = 'my-tenant'
my_id = 'my-id'
pool_id = 'pool-id'
args = ['--address', address, '--port', port,
'--tenant-id', tenant_id, pool_id]
position_names = ['address', 'port', 'tenant_id', 'pool_id',
'admin_state_up']
position_values = [address, port, tenant_id, pool_id,
True]
self._test_create_resource(resource, cmd, None, my_id, args,
position_names, position_values,
admin_state_up=None)
def test_create_member_all_params(self):
"""lb-member-create with all available params"""
resource = 'member'
cmd = member.CreateMember(test_cli20.MyApp(sys.stdout), None)
address = '10.0.0.1'
admin_state_up = False
port = '8080'
weight = '1'
tenant_id = 'my-tenant'
my_id = 'my-id'
pool_id = 'pool-id'
args = ['--address', address, '--admin-state-down',
'--port', port, '--weight', weight,
'--tenant-id', tenant_id, pool_id]
position_names = ['address', 'admin_state_up', 'port', 'weight',
'tenant_id', 'pool_id']
position_values = [address, admin_state_up, port, weight,
tenant_id, pool_id]
self._test_create_resource(resource, cmd, None, my_id, args,
position_names, position_values,
admin_state_up=None)
def test_list_members(self):
"""lb-member-list"""
resources = "members"
cmd = member.ListMember(test_cli20.MyApp(sys.stdout), None)
self._test_list_resources(resources, cmd, True)
def test_show_member_id(self):
"""lb-member-show test_id"""
resource = 'member'
cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(resource, cmd, self.test_id, args, ['id'])
def test_show_member_id_name(self):
"""lb-member-show"""
resource = 'member'
cmd = member.ShowMember(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(resource, cmd, self.test_id,
args, ['id', 'name'])
def test_update_member(self):
"""lb-member-update myid --name myname --tags a b."""
resource = 'member'
cmd = member.UpdateMember(test_cli20.MyApp(sys.stdout), None)
self._test_update_resource(resource, cmd, 'myid',
['myid', '--name', 'myname',
'--tags', 'a', 'b'],
{'name': 'myname', 'tags': ['a', 'b'], })
def test_delete_member(self):
"""lb-member-delete my-id"""
resource = 'member'
cmd = member.DeleteMember(test_cli20.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(resource, cmd, my_id, args)

View File

@@ -0,0 +1,145 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import sys
from mox import ContainsKeyValue
from quantumclient.quantum.v2_0.lb import pool
from quantumclient.tests.unit import test_cli20
class CLITestV20LbPool(test_cli20.CLITestV20Base):
def test_create_pool_with_mandatory_params(self):
"""lb-pool-create with mandatory params only"""
resource = 'pool'
cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None)
name = 'my-name'
lb_method = 'round-robin'
protocol = 'http'
subnet_id = 'subnet-id'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--lb-method', lb_method,
'--name', name,
'--protocol', protocol,
'--subnet-id', subnet_id,
'--tenant-id', tenant_id]
position_names = ['admin_state_up', 'lb_method', 'name',
'protocol', 'subnet_id', 'tenant_id']
position_values = [True, lb_method, name,
protocol, subnet_id, tenant_id]
self._test_create_resource(resource, cmd, name, my_id, args,
position_names, position_values)
def test_create_pool_with_all_params(self):
"""lb-pool-create with all params set"""
resource = 'pool'
cmd = pool.CreatePool(test_cli20.MyApp(sys.stdout), None)
name = 'my-name'
description = 'my-desc'
lb_method = 'round-robin'
protocol = 'http'
subnet_id = 'subnet-id'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--admin-state-down',
'--description', description,
'--lb-method', lb_method,
'--name', name,
'--protocol', protocol,
'--subnet-id', subnet_id,
'--tenant-id', tenant_id]
position_names = ['admin_state_up', 'description', 'lb_method', 'name',
'protocol', 'subnet_id', 'tenant_id']
position_values = [False, description, lb_method, name,
protocol, subnet_id, tenant_id]
self._test_create_resource(resource, cmd, name, my_id, args,
position_names, position_values)
def test_list_pools(self):
"""lb-pool-list"""
resources = "pools"
cmd = pool.ListPool(test_cli20.MyApp(sys.stdout), None)
self._test_list_resources(resources, cmd, True)
def test_show_pool_id(self):
"""lb-pool-show test_id"""
resource = 'pool'
cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(resource, cmd, self.test_id, args, ['id'])
def test_show_pool_id_name(self):
"""lb-pool-show"""
resource = 'pool'
cmd = pool.ShowPool(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(resource, cmd, self.test_id,
args, ['id', 'name'])
def test_update_pool(self):
"""lb-pool-update myid --name newname --tags a b."""
resource = 'pool'
cmd = pool.UpdatePool(test_cli20.MyApp(sys.stdout), None)
self._test_update_resource(resource, cmd, 'myid',
['myid', '--name', 'newname'],
{'name': 'newname', })
def test_delete_pool(self):
"""lb-pool-delete my-id"""
resource = 'pool'
cmd = pool.DeletePool(test_cli20.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(resource, cmd, my_id, args)
def test_retrieve_pool_stats(self):
"""lb-pool-stats test_id"""
resource = 'pool'
cmd = pool.RetrievePoolStats(test_cli20.MyApp(sys.stdout), None)
my_id = self.test_id
fields = ['bytes_in', 'bytes_out']
args = ['--fields', 'bytes_in', '--fields', 'bytes_out', my_id]
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
query = "&".join(["fields=%s" % field for field in fields])
expected_res = {'stats': {'bytes_in': '1234', 'bytes_out': '4321'}}
resstr = self.client.serialize(expected_res)
path = getattr(self.client, "pool_path_stats")
return_tup = (test_cli20.MyResp(200), resstr)
self.client.httpclient.request(
test_cli20.end_url(path % my_id, query), 'GET',
body=None,
headers=ContainsKeyValue('X-Auth-Token',
test_cli20.TOKEN)).AndReturn(return_tup)
self.mox.ReplayAll()
cmd_parser = cmd.get_parser("test_" + resource)
parsed_args = cmd_parser.parse_args(args)
cmd.run(parsed_args)
self.mox.VerifyAll()
self.mox.UnsetStubs()
_str = self.fake_stdout.make_string()
self.assertTrue('bytes_in' in _str)
self.assertTrue('bytes_out' in _str)

View File

@@ -0,0 +1,185 @@
# Copyright 2013 Mirantis Inc.
# All Rights Reserved
#
# 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.
#
# @author: Ilya Shakhat, Mirantis Inc.
#
# vim: tabstop=4 shiftwidth=4 softtabstop=4
import sys
from quantumclient.quantum.v2_0.lb import vip
from quantumclient.tests.unit import test_cli20
class CLITestV20LbVip(test_cli20.CLITestV20Base):
def test_create_vip_with_mandatory_params(self):
"""lb-vip-create with all mandatory params"""
resource = 'vip'
cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None)
pool_id = 'my-pool-id'
name = 'my-name'
subnet_id = 'subnet-id'
port = '1000'
protocol = 'tcp'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--name', name,
'--port', port,
'--protocol', protocol,
'--subnet-id', subnet_id,
'--tenant-id', tenant_id,
pool_id]
position_names = ['pool_id', 'name', 'port', 'protocol',
'subnet_id', 'tenant_id']
position_values = [pool_id, name, port, protocol,
subnet_id, tenant_id]
self._test_create_resource(resource, cmd, name, my_id, args,
position_names, position_values,
admin_state_up=True)
def test_create_vip_with_all_params(self):
"""lb-vip-create with all params"""
resource = 'vip'
cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None)
pool_id = 'my-pool-id'
name = 'my-name'
description = 'my-desc'
address = '10.0.0.2'
admin_state = False
connection_limit = '1000'
subnet_id = 'subnet-id'
port = '80'
protocol = 'tcp'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--name', name,
'--description', description,
'--address', address,
'--admin-state-down',
'--connection-limit', connection_limit,
'--port', port,
'--protocol', protocol,
'--subnet-id', subnet_id,
'--tenant-id', tenant_id,
pool_id]
position_names = ['pool_id', 'name', 'description', 'address',
'admin_state_up', 'connection_limit', 'port',
'protocol', 'subnet_id',
'tenant_id']
position_values = [pool_id, name, description, address,
admin_state, connection_limit, port,
protocol, subnet_id,
tenant_id]
self._test_create_resource(resource, cmd, name, my_id, args,
position_names, position_values)
def test_create_vip_with_session_persistence_params(self):
"""lb-vip-create with mandatory and session-persistence params"""
resource = 'vip'
cmd = vip.CreateVip(test_cli20.MyApp(sys.stdout), None)
pool_id = 'my-pool-id'
name = 'my-name'
subnet_id = 'subnet-id'
port = '1000'
protocol = 'tcp'
tenant_id = 'my-tenant'
my_id = 'my-id'
args = ['--name', name,
'--port', port,
'--protocol', protocol,
'--subnet-id', subnet_id,
'--tenant-id', tenant_id,
pool_id,
'--session-persistence', 'type=dict',
'type=cookie,cookie_name=pie',
'--optional-param', 'any']
position_names = ['pool_id', 'name', 'port', 'protocol',
'subnet_id', 'tenant_id', 'optional_param']
position_values = [pool_id, name, port, protocol,
subnet_id, tenant_id, 'any']
extra_body = {
'session_persistence': {
'type': 'cookie',
'cookie_name': 'pie',
},
}
self._test_create_resource(resource, cmd, name, my_id, args,
position_names, position_values,
admin_state_up=True, extra_body=extra_body)
def test_list_vips(self):
"""lb-vip-list"""
resources = "vips"
cmd = vip.ListVip(test_cli20.MyApp(sys.stdout), None)
self._test_list_resources(resources, cmd, True)
def test_show_vip_id(self):
"""lb-vip-show test_id"""
resource = 'vip'
cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', self.test_id]
self._test_show_resource(resource, cmd, self.test_id, args, ['id'])
def test_show_vip_id_name(self):
"""lb-vip-show"""
resource = 'vip'
cmd = vip.ShowVip(test_cli20.MyApp(sys.stdout), None)
args = ['--fields', 'id', '--fields', 'name', self.test_id]
self._test_show_resource(resource, cmd, self.test_id,
args, ['id', 'name'])
def test_update_vip(self):
"""lb-vip-update myid --name myname --tags a b."""
resource = 'vip'
cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None)
self._test_update_resource(resource, cmd, 'myid',
['myid', '--name', 'myname',
'--tags', 'a', 'b'],
{'name': 'myname', 'tags': ['a', 'b'], })
def test_update_vip_with_session_persistence(self):
resource = 'vip'
cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None)
body = {
'session_persistence': {
'type': 'source',
},
}
args = ['myid', '--session-persistence', 'type=dict',
'type=source']
self._test_update_resource(resource, cmd, 'myid', args, body)
def test_update_vip_with_session_persistence_and_name(self):
resource = 'vip'
cmd = vip.UpdateVip(test_cli20.MyApp(sys.stdout), None)
body = {
'name': 'newname',
'session_persistence': {
'type': 'cookie',
'cookie_name': 'pie',
},
}
args = ['myid', '--name', 'newname',
'--session-persistence', 'type=dict',
'type=cookie,cookie_name=pie']
self._test_update_resource(resource, cmd, 'myid', args, body)
def test_delete_vip(self):
"""lb-vip-delete my-id"""
resource = 'vip'
cmd = vip.DeleteVip(test_cli20.MyApp(sys.stdout), None)
my_id = 'my-id'
args = [my_id]
self._test_delete_resource(resource, cmd, my_id, args)

View File

@@ -53,6 +53,16 @@ class CLITestArgs(testtools.TestCase):
self.assertRaises(exceptions.CommandError,
quantumV20.parse_args_to_dict, _specs)
def test_badarg_duplicate(self):
_specs = ['--tag=t', '--arg1', 'value1', '--arg1', 'value1']
self.assertRaises(exceptions.CommandError,
quantumV20.parse_args_to_dict, _specs)
def test_badarg_early_type_specification(self):
_specs = ['type=dict', 'key=value']
self.assertRaises(exceptions.CommandError,
quantumV20.parse_args_to_dict, _specs)
def test_arg(self):
_specs = ['--tag=t', '--arg1', 'value1']
self.assertEqual('value1',
@@ -64,6 +74,12 @@ class CLITestArgs(testtools.TestCase):
self.assertEqual('value1', arg1['key1'])
self.assertEqual('value2', arg1['key2'])
def test_dict_arg_with_attribute_named_type(self):
_specs = ['--tag=t', '--arg1', 'type=dict', 'type=value1,key2=value2']
arg1 = quantumV20.parse_args_to_dict(_specs)['arg1']
self.assertEqual('value1', arg1['type'])
self.assertEqual('value2', arg1['key2'])
def test_list_of_dict_arg(self):
_specs = ['--tag=t', '--arg1', 'type=dict',
'list=true', 'key1=value1,key2=value2']

View File

@@ -135,7 +135,8 @@ class CLITestV20Base(testtools.TestCase):
def _test_create_resource(self, resource, cmd,
name, myid, args,
position_names, position_values, tenant_id=None,
tags=None, admin_state_up=True, shared=False):
tags=None, admin_state_up=True, shared=False,
extra_body=None):
self.mox.StubOutWithMock(cmd, "get_client")
self.mox.StubOutWithMock(self.client.httpclient, "request")
cmd.get_client().MultipleTimes().AndReturn(self.client)
@@ -151,6 +152,8 @@ class CLITestV20Base(testtools.TestCase):
body[resource].update({'tags': tags})
if shared:
body[resource].update({'shared': shared})
if extra_body:
body[resource].update(extra_body)
for i in xrange(len(position_names)):
body[resource].update({position_names[i]: position_values[i]})

View File

@@ -168,6 +168,18 @@ class Client(object):
security_group_path = "/security-groups/%s"
security_group_rules_path = "/security-group-rules"
security_group_rule_path = "/security-group-rules/%s"
vips_path = "/lb/vips"
vip_path = "/lb/vips/%s"
pools_path = "/lb/pools"
pool_path = "/lb/pools/%s"
pool_path_stats = "/lb/pools/%s/stats"
members_path = "/lb/members"
member_path = "/lb/members/%s"
health_monitors_path = "/lb/health_monitors"
health_monitor_path = "/lb/health_monitors/%s"
associate_pool_health_monitors_path = "/lb/pools/%s/health_monitors"
disassociate_pool_health_monitors_path = (
"/lb/pools/%(pool)s/health_monitors/%(health_monitor)s")
@APIParamsCall
def get_quotas_tenant(self, **_params):
@@ -475,6 +487,175 @@ class Client(object):
return self.get(self.security_group_rule_path % (security_group_rule),
params=_params)
@APIParamsCall
def list_vips(self, **_params):
"""
Fetches a list of all load balancer vips for a tenant
"""
# Pass filters in "params" argument to do_request
return self.get(self.vips_path, params=_params)
@APIParamsCall
def show_vip(self, vip, **_params):
"""
Fetches information of a certain load balancer vip
"""
return self.get(self.vip_path % (vip), params=_params)
@APIParamsCall
def create_vip(self, body=None):
"""
Creates a new load balancer vip
"""
return self.post(self.vips_path, body=body)
@APIParamsCall
def update_vip(self, vip, body=None):
"""
Updates a load balancer vip
"""
return self.put(self.vip_path % (vip), body=body)
@APIParamsCall
def delete_vip(self, vip):
"""
Deletes the specified load balancer vip
"""
return self.delete(self.vip_path % (vip))
@APIParamsCall
def list_pools(self, **_params):
"""
Fetches a list of all load balancer pools for a tenant
"""
# Pass filters in "params" argument to do_request
return self.get(self.pools_path, params=_params)
@APIParamsCall
def show_pool(self, pool, **_params):
"""
Fetches information of a certain load balancer pool
"""
return self.get(self.pool_path % (pool), params=_params)
@APIParamsCall
def create_pool(self, body=None):
"""
Creates a new load balancer pool
"""
return self.post(self.pools_path, body=body)
@APIParamsCall
def update_pool(self, pool, body=None):
"""
Updates a load balancer pool
"""
return self.put(self.pool_path % (pool), body=body)
@APIParamsCall
def delete_pool(self, pool):
"""
Deletes the specified load balancer pool
"""
return self.delete(self.pool_path % (pool))
@APIParamsCall
def retrieve_pool_stats(self, pool, **_params):
"""
Retrieves stats for a certain load balancer pool
"""
return self.get(self.pool_path_stats % (pool), params=_params)
@APIParamsCall
def list_members(self, **_params):
"""
Fetches a list of all load balancer members for a tenant
"""
# Pass filters in "params" argument to do_request
return self.get(self.members_path, params=_params)
@APIParamsCall
def show_member(self, member, **_params):
"""
Fetches information of a certain load balancer member
"""
return self.get(self.member_path % (member), params=_params)
@APIParamsCall
def create_member(self, body=None):
"""
Creates a new load balancer member
"""
return self.post(self.members_path, body=body)
@APIParamsCall
def update_member(self, member, body=None):
"""
Updates a load balancer member
"""
return self.put(self.member_path % (member), body=body)
@APIParamsCall
def delete_member(self, member):
"""
Deletes the specified load balancer member
"""
return self.delete(self.member_path % (member))
@APIParamsCall
def list_health_monitors(self, **_params):
"""
Fetches a list of all load balancer health monitors for a tenant
"""
# Pass filters in "params" argument to do_request
return self.get(self.health_monitors_path, params=_params)
@APIParamsCall
def show_health_monitor(self, health_monitor, **_params):
"""
Fetches information of a certain load balancer health monitor
"""
return self.get(self.health_monitor_path % (health_monitor),
params=_params)
@APIParamsCall
def create_health_monitor(self, body=None):
"""
Creates a new load balancer health monitor
"""
return self.post(self.health_monitors_path, body=body)
@APIParamsCall
def update_health_monitor(self, health_monitor, body=None):
"""
Updates a load balancer health monitor
"""
return self.put(self.health_monitor_path % (health_monitor), body=body)
@APIParamsCall
def delete_health_monitor(self, health_monitor):
"""
Deletes the specified load balancer health monitor
"""
return self.delete(self.health_monitor_path % (health_monitor))
@APIParamsCall
def associate_health_monitor(self, pool, body):
"""
Associate specified load balancer health monitor and pool
"""
return self.post(self.associate_pool_health_monitors_path % (pool),
body=body)
@APIParamsCall
def disassociate_health_monitor(self, pool, health_monitor):
"""
Disassociate specified load balancer health monitor and pool
"""
path = (self.disassociate_pool_health_monitors_path %
{'pool': pool, 'health_monitor': health_monitor})
return self.delete(path)
def __init__(self, **kwargs):
""" Initialize a new client for the Quantum v2.0 API. """
super(Client, self).__init__()