Network CRUD
bp/neutron https://wiki.openstack.org/wiki/OpenStackClient/Commands#Network_2 Change-Id: I89ee083154afa544b03587e84becace36d9d522a
This commit is contained in:
@@ -84,6 +84,16 @@ def format_dict(data):
|
|||||||
return output[:-2]
|
return output[:-2]
|
||||||
|
|
||||||
|
|
||||||
|
def format_list(data):
|
||||||
|
"""Return a formatted strings
|
||||||
|
|
||||||
|
:param data: a list of strings
|
||||||
|
:rtype: a string formatted to a,b,c
|
||||||
|
"""
|
||||||
|
|
||||||
|
return ', '.join(data)
|
||||||
|
|
||||||
|
|
||||||
def get_item_properties(item, fields, mixed_case_fields=[], formatters={}):
|
def get_item_properties(item, fields, mixed_case_fields=[], formatters={}):
|
||||||
"""Return a tuple containing the item properties.
|
"""Return a tuple containing the item properties.
|
||||||
|
|
||||||
|
|||||||
0
openstackclient/network/__init__.py
Normal file
0
openstackclient/network/__init__.py
Normal file
61
openstackclient/network/client.py
Normal file
61
openstackclient/network/client.py
Normal 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from openstackclient.common import utils
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
DEFAULT_NETWORK_API_VERSION = '2.0'
|
||||||
|
API_VERSION_OPTION = 'os_network_api_version'
|
||||||
|
API_NAME = "network"
|
||||||
|
API_VERSIONS = {
|
||||||
|
"2.0": "neutronclient.v2_0.client.Client",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def make_client(instance):
|
||||||
|
"""Returns an network service client."""
|
||||||
|
network_client = utils.get_client_class(
|
||||||
|
API_NAME,
|
||||||
|
instance._api_version[API_NAME],
|
||||||
|
API_VERSIONS)
|
||||||
|
if not instance._url:
|
||||||
|
instance._url = instance.get_endpoint_for_service_type("network")
|
||||||
|
return network_client(
|
||||||
|
username=instance._username,
|
||||||
|
tenant_name=instance._project_name,
|
||||||
|
password=instance._password,
|
||||||
|
region_name=instance._region_name,
|
||||||
|
auth_url=instance._auth_url,
|
||||||
|
endpoint_url=instance._url,
|
||||||
|
token=instance._token,
|
||||||
|
insecure=instance._insecure,
|
||||||
|
ca_cert=instance._cacert,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def build_option_parser(parser):
|
||||||
|
"""Hook to add global options"""
|
||||||
|
parser.add_argument(
|
||||||
|
'--os-network-api-version',
|
||||||
|
metavar='<network-api-version>',
|
||||||
|
default=utils.env(
|
||||||
|
'OS_NETWORK_API_VERSION',
|
||||||
|
default=DEFAULT_NETWORK_API_VERSION),
|
||||||
|
help='Network API version, default=' +
|
||||||
|
DEFAULT_NETWORK_API_VERSION +
|
||||||
|
' (Env: OS_NETWORK_API_VERSION)')
|
||||||
|
return parser
|
||||||
43
openstackclient/network/common.py
Normal file
43
openstackclient/network/common.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# 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 openstackclient.common import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def find(client, resource, resources, name_or_id):
|
||||||
|
"""Find a network resource
|
||||||
|
|
||||||
|
:param client: network client
|
||||||
|
:param resource: name of the resource
|
||||||
|
:param resources: plural name of resource
|
||||||
|
:param name_or_id: name or id of resource user is looking for
|
||||||
|
|
||||||
|
For example:
|
||||||
|
n = find(netclient, 'network', 'networks', 'matrix')
|
||||||
|
"""
|
||||||
|
list_method = getattr(client, "list_%s" % resources)
|
||||||
|
# Search for by name
|
||||||
|
data = list_method(name=name_or_id, fields='id')
|
||||||
|
info = data[resources]
|
||||||
|
if len(info) == 1:
|
||||||
|
return info[0]['id']
|
||||||
|
if len(info) > 1:
|
||||||
|
msg = "More than one %s exists with the name '%s'."
|
||||||
|
raise exceptions.CommandError(msg % (resource, name_or_id))
|
||||||
|
# Search for by id
|
||||||
|
data = list_method(id=name_or_id, fields='id')
|
||||||
|
info = data[resources]
|
||||||
|
if len(info) == 1:
|
||||||
|
return info[0]['id']
|
||||||
|
msg = "No %s with a name or ID of '%s' exists." % (resource, name_or_id)
|
||||||
|
raise exceptions.CommandError(msg)
|
||||||
0
openstackclient/network/v2_0/__init__.py
Normal file
0
openstackclient/network/v2_0/__init__.py
Normal file
236
openstackclient/network/v2_0/network.py
Normal file
236
openstackclient/network/v2_0/network.py
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
"""Network action implementations"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import six
|
||||||
|
|
||||||
|
from cliff import command
|
||||||
|
from cliff import lister
|
||||||
|
from cliff import show
|
||||||
|
|
||||||
|
from openstackclient.common import exceptions
|
||||||
|
from openstackclient.common import utils
|
||||||
|
from openstackclient.network import common
|
||||||
|
|
||||||
|
|
||||||
|
def filters(data):
|
||||||
|
if 'subnets' in data:
|
||||||
|
data['subnets'] = utils.format_list(data['subnets'])
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class CreateNetwork(show.ShowOne):
|
||||||
|
"""Create a network"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.CreateNetwork')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(CreateNetwork, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'name', metavar='<network_name>',
|
||||||
|
help='Name of network to create')
|
||||||
|
admin_group = parser.add_mutually_exclusive_group()
|
||||||
|
admin_group.add_argument(
|
||||||
|
'--admin-state-up',
|
||||||
|
dest='admin_state', action='store_true',
|
||||||
|
default=True, help='Set Admin State Up')
|
||||||
|
admin_group.add_argument(
|
||||||
|
'--admin-state-down',
|
||||||
|
dest='admin_state', action='store_false',
|
||||||
|
help='Set Admin State Down')
|
||||||
|
share_group = parser.add_mutually_exclusive_group()
|
||||||
|
share_group.add_argument(
|
||||||
|
'--share',
|
||||||
|
dest='shared', action='store_true',
|
||||||
|
default=None,
|
||||||
|
help='Share the network across tenants')
|
||||||
|
share_group.add_argument(
|
||||||
|
'--no-share',
|
||||||
|
dest='shared', action='store_false',
|
||||||
|
help='Do not share the network across tenants')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
client = self.app.client_manager.network
|
||||||
|
body = self.get_body(parsed_args)
|
||||||
|
create_method = getattr(client, "create_network")
|
||||||
|
data = create_method(body)['network']
|
||||||
|
if data:
|
||||||
|
data = filters(data)
|
||||||
|
else:
|
||||||
|
data = {'': ''}
|
||||||
|
return zip(*sorted(six.iteritems(data)))
|
||||||
|
|
||||||
|
def get_body(self, parsed_args):
|
||||||
|
body = {'name': str(parsed_args.name),
|
||||||
|
'admin_state_up': parsed_args.admin_state}
|
||||||
|
if parsed_args.shared is not None:
|
||||||
|
body['shared'] = parsed_args.shared
|
||||||
|
return {'network': body}
|
||||||
|
|
||||||
|
|
||||||
|
class DeleteNetwork(command.Command):
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.DeleteNetwork')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(DeleteNetwork, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
metavar="<network>",
|
||||||
|
help=("Name or identifier of network to delete")
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
client = self.app.client_manager.network
|
||||||
|
_id = common.find(client, 'network', 'networks',
|
||||||
|
parsed_args.identifier)
|
||||||
|
delete_method = getattr(client, "delete_network")
|
||||||
|
delete_method(_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class ListNetwork(lister.Lister):
|
||||||
|
"""List networks"""
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.ListNetwork')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ListNetwork, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'--external',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='List external networks',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--dhcp',
|
||||||
|
help='ID of the DHCP agent')
|
||||||
|
parser.add_argument(
|
||||||
|
'--long',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='Long listing',
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
client = self.app.client_manager.network
|
||||||
|
if parsed_args.dhcp:
|
||||||
|
list_method = getattr(client, 'list_networks_on_dhcp_agent')
|
||||||
|
resources = 'networks_on_dhcp_agent'
|
||||||
|
report_filter = {'dhcp_agent': parsed_args.dhcp}
|
||||||
|
data = list_method(**report_filter)[resources]
|
||||||
|
else:
|
||||||
|
list_method = getattr(client, "list_networks")
|
||||||
|
report_filter = {}
|
||||||
|
if parsed_args.external:
|
||||||
|
report_filter = {'router:external': True}
|
||||||
|
data = list_method(**report_filter)['networks']
|
||||||
|
columns = len(data) > 0 and sorted(data[0].keys()) or []
|
||||||
|
if parsed_args.columns:
|
||||||
|
list_columns = parsed_args.columns
|
||||||
|
else:
|
||||||
|
list_columns = ['id', 'name', 'subnets']
|
||||||
|
if not parsed_args.long and not parsed_args.dhcp:
|
||||||
|
columns = [x for x in list_columns if x in columns]
|
||||||
|
formatters = {'subnets': utils.format_list}
|
||||||
|
return (columns,
|
||||||
|
(utils.get_dict_properties(s, columns, formatters=formatters)
|
||||||
|
for s in data))
|
||||||
|
|
||||||
|
|
||||||
|
class SetNetwork(command.Command):
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.SetNetwork')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(SetNetwork, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
metavar="<network>",
|
||||||
|
help=("Name or identifier of network to set")
|
||||||
|
)
|
||||||
|
admin_group = parser.add_mutually_exclusive_group()
|
||||||
|
admin_group.add_argument(
|
||||||
|
'--admin-state-up',
|
||||||
|
dest='admin_state', action='store_true',
|
||||||
|
default=None,
|
||||||
|
help='Set Admin State Up')
|
||||||
|
admin_group.add_argument(
|
||||||
|
'--admin-state-down',
|
||||||
|
dest='admin_state', action='store_false',
|
||||||
|
help='Set Admin State Down')
|
||||||
|
parser.add_argument(
|
||||||
|
'--name',
|
||||||
|
metavar='<network_name>',
|
||||||
|
help='New name for the network')
|
||||||
|
share_group = parser.add_mutually_exclusive_group()
|
||||||
|
share_group.add_argument(
|
||||||
|
'--share',
|
||||||
|
dest='shared', action='store_true',
|
||||||
|
default=None,
|
||||||
|
help='Share the network across tenants')
|
||||||
|
share_group.add_argument(
|
||||||
|
'--no-share',
|
||||||
|
dest='shared', action='store_false',
|
||||||
|
help='Do not share the network across tenants')
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
client = self.app.client_manager.network
|
||||||
|
_id = common.find(client, 'network', 'networks',
|
||||||
|
parsed_args.identifier)
|
||||||
|
body = {}
|
||||||
|
if parsed_args.name is not None:
|
||||||
|
body['name'] = str(parsed_args.name)
|
||||||
|
if parsed_args.admin_state is not None:
|
||||||
|
body['admin_state_up'] = parsed_args.admin_state
|
||||||
|
if parsed_args.shared is not None:
|
||||||
|
body['shared'] = parsed_args.shared
|
||||||
|
if body == {}:
|
||||||
|
raise exceptions.CommandError("Nothing specified to be set")
|
||||||
|
update_method = getattr(client, "update_network")
|
||||||
|
update_method(_id, {'network': body})
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
class ShowNetwork(show.ShowOne):
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__ + '.ShowNetwork')
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(ShowNetwork, self).get_parser(prog_name)
|
||||||
|
parser.add_argument(
|
||||||
|
'identifier',
|
||||||
|
metavar="<network>",
|
||||||
|
help=("Name or identifier of network to show")
|
||||||
|
)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.log.debug('take_action(%s)' % parsed_args)
|
||||||
|
client = self.app.client_manager.network
|
||||||
|
_id = common.find(client, 'network', 'networks',
|
||||||
|
parsed_args.identifier)
|
||||||
|
show_method = getattr(client, "show_network")
|
||||||
|
data = show_method(_id)['network']
|
||||||
|
data = filters(data)
|
||||||
|
return zip(*sorted(six.iteritems(data)))
|
||||||
@@ -52,6 +52,7 @@ class FakeClientManager(object):
|
|||||||
self.image = None
|
self.image = None
|
||||||
self.object = None
|
self.object = None
|
||||||
self.volume = None
|
self.volume = None
|
||||||
|
self.network = None
|
||||||
self.auth_ref = None
|
self.auth_ref = None
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
0
openstackclient/tests/network/__init__.py
Normal file
0
openstackclient/tests/network/__init__.py
Normal file
52
openstackclient/tests/network/common.py
Normal file
52
openstackclient/tests/network/common.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 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 argparse
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from openstackclient.tests import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestNetworkBase(utils.TestCommand):
|
||||||
|
def setUp(self):
|
||||||
|
super(TestNetworkBase, self).setUp()
|
||||||
|
self.app = mock.Mock(name='app')
|
||||||
|
self.app.client_manager = mock.Mock(name='client_manager')
|
||||||
|
self.namespace = argparse.Namespace()
|
||||||
|
|
||||||
|
given_show_options = [
|
||||||
|
'-f',
|
||||||
|
'shell',
|
||||||
|
'-c',
|
||||||
|
'id',
|
||||||
|
'--prefix',
|
||||||
|
'TST',
|
||||||
|
]
|
||||||
|
then_show_options = [
|
||||||
|
('formatter', 'shell'),
|
||||||
|
('columns', ['id']),
|
||||||
|
('prefix', 'TST'),
|
||||||
|
]
|
||||||
|
given_list_options = [
|
||||||
|
'-f',
|
||||||
|
'csv',
|
||||||
|
'-c',
|
||||||
|
'id',
|
||||||
|
'--quote',
|
||||||
|
'all',
|
||||||
|
]
|
||||||
|
then_list_options = [
|
||||||
|
('formatter', 'csv'),
|
||||||
|
('columns', ['id']),
|
||||||
|
('quote_mode', 'all'),
|
||||||
|
]
|
||||||
0
openstackclient/tests/network/v2_0/__init__.py
Normal file
0
openstackclient/tests/network/v2_0/__init__.py
Normal file
319
openstackclient/tests/network/v2_0/test_network.py
Normal file
319
openstackclient/tests/network/v2_0/test_network.py
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
# 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 copy
|
||||||
|
import mock
|
||||||
|
|
||||||
|
from openstackclient.common import exceptions
|
||||||
|
from openstackclient.network.v2_0 import network
|
||||||
|
from openstackclient.tests.network import common
|
||||||
|
|
||||||
|
RESOURCE = 'network'
|
||||||
|
RESOURCES = 'networks'
|
||||||
|
FAKE_ID = 'iditty'
|
||||||
|
FAKE_NAME = 'noo'
|
||||||
|
RECORD = {
|
||||||
|
'id': FAKE_ID,
|
||||||
|
'name': FAKE_NAME,
|
||||||
|
'router:external': True,
|
||||||
|
'subnets': ['a', 'b'],
|
||||||
|
}
|
||||||
|
COLUMNS = ['id', 'name', 'subnets']
|
||||||
|
RESPONSE = {RESOURCE: RECORD}
|
||||||
|
FILTERED = [('id', 'name', 'router:external', 'subnets'),
|
||||||
|
(FAKE_ID, FAKE_NAME, True, 'a, b')]
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateNetwork(common.TestNetworkBase):
|
||||||
|
def test_create_no_options(self):
|
||||||
|
arglist = [
|
||||||
|
FAKE_NAME,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('name', FAKE_NAME),
|
||||||
|
('admin_state', True),
|
||||||
|
('shared', None),
|
||||||
|
]
|
||||||
|
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
|
||||||
|
self.app.client_manager.network.create_network = mocker
|
||||||
|
cmd = network.CreateNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with({
|
||||||
|
RESOURCE: {
|
||||||
|
'admin_state_up': True,
|
||||||
|
'name': FAKE_NAME,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertEqual(FILTERED, result)
|
||||||
|
|
||||||
|
def test_create_all_options(self):
|
||||||
|
arglist = [
|
||||||
|
"--admin-state-down",
|
||||||
|
"--share",
|
||||||
|
FAKE_NAME,
|
||||||
|
] + self.given_show_options
|
||||||
|
verifylist = [
|
||||||
|
('admin_state', False),
|
||||||
|
('shared', True),
|
||||||
|
('name', FAKE_NAME),
|
||||||
|
] + self.then_show_options
|
||||||
|
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
|
||||||
|
self.app.client_manager.network.create_network = mocker
|
||||||
|
cmd = network.CreateNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with({
|
||||||
|
RESOURCE: {
|
||||||
|
'admin_state_up': False,
|
||||||
|
'name': FAKE_NAME,
|
||||||
|
'shared': True,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertEqual(FILTERED, result)
|
||||||
|
|
||||||
|
def test_create_other_options(self):
|
||||||
|
arglist = [
|
||||||
|
"--admin-state-up",
|
||||||
|
"--no-share",
|
||||||
|
FAKE_NAME,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('admin_state', True),
|
||||||
|
('shared', False),
|
||||||
|
('name', FAKE_NAME),
|
||||||
|
]
|
||||||
|
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
|
||||||
|
self.app.client_manager.network.create_network = mocker
|
||||||
|
cmd = network.CreateNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with({
|
||||||
|
RESOURCE: {
|
||||||
|
'admin_state_up': True,
|
||||||
|
'name': FAKE_NAME,
|
||||||
|
'shared': False,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
self.assertEqual(FILTERED, result)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeleteNetwork(common.TestNetworkBase):
|
||||||
|
def test_delete(self):
|
||||||
|
arglist = [
|
||||||
|
FAKE_NAME,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('identifier', FAKE_NAME),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=None)
|
||||||
|
self.app.client_manager.network.delete_network = mocker
|
||||||
|
cmd = network.DeleteNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with(FAKE_ID)
|
||||||
|
self.assertEqual(None, result)
|
||||||
|
|
||||||
|
|
||||||
|
class TestListNetwork(common.TestNetworkBase):
|
||||||
|
def test_list_no_options(self):
|
||||||
|
arglist = []
|
||||||
|
verifylist = [
|
||||||
|
('long', False),
|
||||||
|
('dhcp', None),
|
||||||
|
('external', False),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
cmd = network.ListNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
lister.assert_called_with()
|
||||||
|
self.assertEqual(COLUMNS, result[0])
|
||||||
|
self.assertEqual((FAKE_ID, FAKE_NAME, 'a, b'), next(result[1]))
|
||||||
|
self.assertRaises(StopIteration, next, result[1])
|
||||||
|
|
||||||
|
def test_list_long(self):
|
||||||
|
arglist = ['--long']
|
||||||
|
verifylist = [
|
||||||
|
('long', True),
|
||||||
|
('dhcp', None),
|
||||||
|
('external', False),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
cmd = network.ListNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
lister.assert_called_with()
|
||||||
|
headings = ['id', 'name', 'router:external', 'subnets']
|
||||||
|
self.assertEqual(headings, result[0])
|
||||||
|
data = (FAKE_ID, FAKE_NAME, True, 'a, b')
|
||||||
|
self.assertEqual(data, next(result[1]))
|
||||||
|
self.assertRaises(StopIteration, next, result[1])
|
||||||
|
|
||||||
|
def test_list_dhcp(self):
|
||||||
|
arglist = [
|
||||||
|
'--dhcp',
|
||||||
|
'dhcpid',
|
||||||
|
] + self.given_list_options
|
||||||
|
verifylist = [
|
||||||
|
('dhcp', 'dhcpid'),
|
||||||
|
] + self.then_list_options
|
||||||
|
fake_dhcp_data = [{'id': '1'}, {'id': '2'}]
|
||||||
|
fake_dhcp_response = {'networks_on_dhcp_agent': fake_dhcp_data}
|
||||||
|
lister = mock.Mock(return_value=fake_dhcp_response)
|
||||||
|
netty = self.app.client_manager.network
|
||||||
|
netty.list_networks_on_dhcp_agent = lister
|
||||||
|
cmd = network.ListNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
lister.assert_called_with(dhcp_agent='dhcpid')
|
||||||
|
self.assertEqual(['id'], result[0])
|
||||||
|
self.assertEqual(('1',), next(result[1]))
|
||||||
|
self.assertEqual(('2',), next(result[1]))
|
||||||
|
self.assertRaises(StopIteration, next, result[1])
|
||||||
|
|
||||||
|
def test_list_external(self):
|
||||||
|
arglist = ['--external', '-c', 'id']
|
||||||
|
verifylist = [('external', True)]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
cmd = network.ListNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
lister.assert_called_with(**{'router:external': True})
|
||||||
|
self.assertEqual(['id'], result[0])
|
||||||
|
self.assertEqual((FAKE_ID,), next(result[1]))
|
||||||
|
self.assertRaises(StopIteration, next, result[1])
|
||||||
|
|
||||||
|
|
||||||
|
class TestSetNetwork(common.TestNetworkBase):
|
||||||
|
def test_set_this(self):
|
||||||
|
arglist = [
|
||||||
|
FAKE_NAME,
|
||||||
|
'--admin-state-up',
|
||||||
|
'--name', 'noob',
|
||||||
|
'--share',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('identifier', FAKE_NAME),
|
||||||
|
('admin_state', True),
|
||||||
|
('name', 'noob'),
|
||||||
|
('shared', True),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=None)
|
||||||
|
self.app.client_manager.network.update_network = mocker
|
||||||
|
cmd = network.SetNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
exp = {'admin_state_up': True, 'name': 'noob', 'shared': True}
|
||||||
|
exp_record = {RESOURCE: exp}
|
||||||
|
mocker.assert_called_with(FAKE_ID, exp_record)
|
||||||
|
self.assertEqual(None, result)
|
||||||
|
|
||||||
|
def test_set_that(self):
|
||||||
|
arglist = [
|
||||||
|
FAKE_NAME,
|
||||||
|
'--admin-state-down',
|
||||||
|
'--no-share',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('identifier', FAKE_NAME),
|
||||||
|
('admin_state', False),
|
||||||
|
('shared', False),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=None)
|
||||||
|
self.app.client_manager.network.update_network = mocker
|
||||||
|
cmd = network.SetNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
exp = {'admin_state_up': False, 'shared': False}
|
||||||
|
exp_record = {RESOURCE: exp}
|
||||||
|
mocker.assert_called_with(FAKE_ID, exp_record)
|
||||||
|
self.assertEqual(None, result)
|
||||||
|
|
||||||
|
def test_set_nothing(self):
|
||||||
|
arglist = [FAKE_NAME, ]
|
||||||
|
verifylist = [('identifier', FAKE_NAME), ]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=None)
|
||||||
|
self.app.client_manager.network.update_network = mocker
|
||||||
|
cmd = network.SetNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
self.assertRaises(exceptions.CommandError, cmd.take_action,
|
||||||
|
parsed_args)
|
||||||
|
|
||||||
|
|
||||||
|
class TestShowNetwork(common.TestNetworkBase):
|
||||||
|
def test_show_no_options(self):
|
||||||
|
arglist = [
|
||||||
|
FAKE_NAME,
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('identifier', FAKE_NAME),
|
||||||
|
]
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
|
||||||
|
self.app.client_manager.network.show_network = mocker
|
||||||
|
cmd = network.ShowNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with(FAKE_ID)
|
||||||
|
self.assertEqual(FILTERED, result)
|
||||||
|
|
||||||
|
def test_show_all_options(self):
|
||||||
|
arglist = [FAKE_NAME] + self.given_show_options
|
||||||
|
verifylist = [('identifier', FAKE_NAME)] + self.then_show_options
|
||||||
|
lister = mock.Mock(return_value={RESOURCES: [RECORD]})
|
||||||
|
self.app.client_manager.network.list_networks = lister
|
||||||
|
mocker = mock.Mock(return_value=copy.deepcopy(RESPONSE))
|
||||||
|
self.app.client_manager.network.show_network = mocker
|
||||||
|
cmd = network.ShowNetwork(self.app, self.namespace)
|
||||||
|
|
||||||
|
parsed_args = self.check_parser(cmd, arglist, verifylist)
|
||||||
|
result = cmd.take_action(parsed_args)
|
||||||
|
|
||||||
|
mocker.assert_called_with(FAKE_ID)
|
||||||
|
self.assertEqual(FILTERED, result)
|
||||||
@@ -39,11 +39,13 @@ DEFAULT_COMPUTE_API_VERSION = "2"
|
|||||||
DEFAULT_IDENTITY_API_VERSION = "2.0"
|
DEFAULT_IDENTITY_API_VERSION = "2.0"
|
||||||
DEFAULT_IMAGE_API_VERSION = "v2"
|
DEFAULT_IMAGE_API_VERSION = "v2"
|
||||||
DEFAULT_VOLUME_API_VERSION = "1"
|
DEFAULT_VOLUME_API_VERSION = "1"
|
||||||
|
DEFAULT_NETWORK_API_VERSION = "2.0"
|
||||||
|
|
||||||
LIB_COMPUTE_API_VERSION = "2"
|
LIB_COMPUTE_API_VERSION = "2"
|
||||||
LIB_IDENTITY_API_VERSION = "2.0"
|
LIB_IDENTITY_API_VERSION = "2.0"
|
||||||
LIB_IMAGE_API_VERSION = "1"
|
LIB_IMAGE_API_VERSION = "1"
|
||||||
LIB_VOLUME_API_VERSION = "1"
|
LIB_VOLUME_API_VERSION = "1"
|
||||||
|
LIB_NETWORK_API_VERSION = "2.0"
|
||||||
|
|
||||||
|
|
||||||
def make_shell():
|
def make_shell():
|
||||||
@@ -128,6 +130,8 @@ class TestShell(utils.TestCase):
|
|||||||
default_args["image_api_version"])
|
default_args["image_api_version"])
|
||||||
self.assertEqual(_shell.options.os_volume_api_version,
|
self.assertEqual(_shell.options.os_volume_api_version,
|
||||||
default_args["volume_api_version"])
|
default_args["volume_api_version"])
|
||||||
|
self.assertEqual(_shell.options.os_network_api_version,
|
||||||
|
default_args["network_api_version"])
|
||||||
|
|
||||||
|
|
||||||
class TestShellHelp(TestShell):
|
class TestShellHelp(TestShell):
|
||||||
@@ -455,6 +459,7 @@ class TestShellCli(TestShell):
|
|||||||
"OS_IDENTITY_API_VERSION": DEFAULT_IDENTITY_API_VERSION,
|
"OS_IDENTITY_API_VERSION": DEFAULT_IDENTITY_API_VERSION,
|
||||||
"OS_IMAGE_API_VERSION": DEFAULT_IMAGE_API_VERSION,
|
"OS_IMAGE_API_VERSION": DEFAULT_IMAGE_API_VERSION,
|
||||||
"OS_VOLUME_API_VERSION": DEFAULT_VOLUME_API_VERSION,
|
"OS_VOLUME_API_VERSION": DEFAULT_VOLUME_API_VERSION,
|
||||||
|
"OS_NETWORK_API_VERSION": DEFAULT_NETWORK_API_VERSION,
|
||||||
}
|
}
|
||||||
self.orig_env, os.environ = os.environ, env.copy()
|
self.orig_env, os.environ = os.environ, env.copy()
|
||||||
|
|
||||||
@@ -475,7 +480,8 @@ class TestShellCli(TestShell):
|
|||||||
"compute_api_version": DEFAULT_COMPUTE_API_VERSION,
|
"compute_api_version": DEFAULT_COMPUTE_API_VERSION,
|
||||||
"identity_api_version": DEFAULT_IDENTITY_API_VERSION,
|
"identity_api_version": DEFAULT_IDENTITY_API_VERSION,
|
||||||
"image_api_version": DEFAULT_IMAGE_API_VERSION,
|
"image_api_version": DEFAULT_IMAGE_API_VERSION,
|
||||||
"volume_api_version": DEFAULT_VOLUME_API_VERSION
|
"volume_api_version": DEFAULT_VOLUME_API_VERSION,
|
||||||
|
"network_api_version": DEFAULT_NETWORK_API_VERSION,
|
||||||
}
|
}
|
||||||
self._assert_cli(flag, kwargs)
|
self._assert_cli(flag, kwargs)
|
||||||
|
|
||||||
@@ -486,6 +492,7 @@ class TestShellCli(TestShell):
|
|||||||
"compute_api_version": LIB_COMPUTE_API_VERSION,
|
"compute_api_version": LIB_COMPUTE_API_VERSION,
|
||||||
"identity_api_version": LIB_IDENTITY_API_VERSION,
|
"identity_api_version": LIB_IDENTITY_API_VERSION,
|
||||||
"image_api_version": LIB_IMAGE_API_VERSION,
|
"image_api_version": LIB_IMAGE_API_VERSION,
|
||||||
"volume_api_version": LIB_VOLUME_API_VERSION
|
"volume_api_version": LIB_VOLUME_API_VERSION,
|
||||||
|
"network_api_version": LIB_NETWORK_API_VERSION
|
||||||
}
|
}
|
||||||
self._assert_cli(flag, kwargs)
|
self._assert_cli(flag, kwargs)
|
||||||
|
|||||||
@@ -6,5 +6,6 @@ python-glanceclient>=0.9.0
|
|||||||
python-keystoneclient>=0.9.0
|
python-keystoneclient>=0.9.0
|
||||||
python-novaclient>=2.17.0
|
python-novaclient>=2.17.0
|
||||||
python-cinderclient>=1.0.6
|
python-cinderclient>=1.0.6
|
||||||
|
python-neutronclient>=2.3.4,<3
|
||||||
requests>=1.1
|
requests>=1.1
|
||||||
six>=1.7.0
|
six>=1.7.0
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ openstack.cli.extension =
|
|||||||
image = openstackclient.image.client
|
image = openstackclient.image.client
|
||||||
object_store = openstackclient.object.client
|
object_store = openstackclient.object.client
|
||||||
volume = openstackclient.volume.client
|
volume = openstackclient.volume.client
|
||||||
|
network = openstackclient.network.client
|
||||||
|
|
||||||
openstack.common =
|
openstack.common =
|
||||||
limits_show = openstackclient.common.limits:ShowLimits
|
limits_show = openstackclient.common.limits:ShowLimits
|
||||||
@@ -289,6 +290,13 @@ openstack.volume.v1 =
|
|||||||
volume_type_set = openstackclient.volume.v1.type:SetVolumeType
|
volume_type_set = openstackclient.volume.v1.type:SetVolumeType
|
||||||
volume_type_unset = openstackclient.volume.v1.type:UnsetVolumeType
|
volume_type_unset = openstackclient.volume.v1.type:UnsetVolumeType
|
||||||
|
|
||||||
|
openstack.network.v2_0 =
|
||||||
|
network_create = openstackclient.network.v2_0.network:CreateNetwork
|
||||||
|
network_delete = openstackclient.network.v2_0.network:DeleteNetwork
|
||||||
|
network_list = openstackclient.network.v2_0.network:ListNetwork
|
||||||
|
network_set = openstackclient.network.v2_0.network:SetNetwork
|
||||||
|
network_show = openstackclient.network.v2_0.network:ShowNetwork
|
||||||
|
|
||||||
[build_sphinx]
|
[build_sphinx]
|
||||||
source-dir = doc/source
|
source-dir = doc/source
|
||||||
build-dir = doc/build
|
build-dir = doc/build
|
||||||
|
|||||||
Reference in New Issue
Block a user