Skip to content

Commit d906507

Browse files
committed
Refactor security group rule create to use SDK
Refactored the 'os security group rule create' command to use the SDK when neutron is enabled, but continue to use the nova client when nova network is enabled. Added a release note for the change in security group rules output due to Network v2. Change-Id: I8c6c99d5272ff5d410a449f73d198d834c5cd96e Partial-Bug: #1519512 Implements: blueprint neutron-client
1 parent 4b4349e commit d906507

9 files changed

Lines changed: 434 additions & 345 deletions

File tree

doc/source/command-objects/security-group-rule.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ Create a new security group rule
3232

3333
.. option:: --dst-port <port-range>
3434

35-
Destination port, may be a range: 137:139 (default: 0; only required for proto tcp and udp)
35+
Destination port, may be a single port or port range: 137:139
36+
(only required for IP protocols tcp and udp)
3637

3738
.. describe:: <group>
3839

openstackclient/compute/v2/security_group.py

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,12 @@
1616

1717
"""Compute v2 Security Group action implementations"""
1818

19-
import six
20-
2119
try:
2220
from novaclient.v2 import security_group_rules
2321
except ImportError:
2422
from novaclient.v1_1 import security_group_rules
2523

2624
from openstackclient.common import command
27-
from openstackclient.common import parseractions
2825
from openstackclient.common import utils
2926

3027

@@ -56,68 +53,6 @@ def _xform_security_group_rule(sgroup):
5653
return info
5754

5855

59-
class CreateSecurityGroupRule(command.ShowOne):
60-
"""Create a new security group rule"""
61-
62-
def get_parser(self, prog_name):
63-
parser = super(CreateSecurityGroupRule, self).get_parser(prog_name)
64-
parser.add_argument(
65-
'group',
66-
metavar='<group>',
67-
help='Create rule in this security group (name or ID)',
68-
)
69-
parser.add_argument(
70-
"--proto",
71-
metavar="<proto>",
72-
default="tcp",
73-
help="IP protocol (icmp, tcp, udp; default: tcp)",
74-
)
75-
source_group = parser.add_mutually_exclusive_group()
76-
source_group.add_argument(
77-
"--src-ip",
78-
metavar="<ip-address>",
79-
default="0.0.0.0/0",
80-
help="Source IP address block (may use CIDR notation; default: "
81-
"0.0.0.0/0)",
82-
)
83-
source_group.add_argument(
84-
"--src-group",
85-
metavar="<group>",
86-
help="Source security group (ID only)",
87-
)
88-
parser.add_argument(
89-
"--dst-port",
90-
metavar="<port-range>",
91-
default=(0, 0),
92-
action=parseractions.RangeAction,
93-
help="Destination port, may be a range: 137:139 (default: 0; "
94-
"only required for proto tcp and udp)",
95-
)
96-
return parser
97-
98-
def take_action(self, parsed_args):
99-
compute_client = self.app.client_manager.compute
100-
group = utils.find_resource(
101-
compute_client.security_groups,
102-
parsed_args.group,
103-
)
104-
if parsed_args.proto.lower() == 'icmp':
105-
from_port, to_port = -1, -1
106-
else:
107-
from_port, to_port = parsed_args.dst_port
108-
data = compute_client.security_group_rules.create(
109-
group.id,
110-
parsed_args.proto,
111-
from_port,
112-
to_port,
113-
parsed_args.src_ip,
114-
parsed_args.src_group,
115-
)
116-
117-
info = _xform_security_group_rule(data._info)
118-
return zip(*sorted(six.iteritems(info)))
119-
120-
12156
class ListSecurityGroupRule(command.Lister):
12257
"""List security group rules"""
12358

openstackclient/network/v2/security_group_rule.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import six
1717

1818
from openstackclient.common import exceptions
19+
from openstackclient.common import parseractions
1920
from openstackclient.common import utils
2021
from openstackclient.network import common
2122
from openstackclient.network import utils as network_utils
@@ -34,6 +35,105 @@ def _get_columns(item):
3435
return tuple(sorted(columns))
3536

3637

38+
def _convert_to_lowercase(string):
39+
return string.lower()
40+
41+
42+
class CreateSecurityGroupRule(common.NetworkAndComputeShowOne):
43+
"""Create a new security group rule"""
44+
45+
def update_parser_common(self, parser):
46+
parser.add_argument(
47+
'group',
48+
metavar='<group>',
49+
help='Create rule in this security group (name or ID)',
50+
)
51+
# TODO(rtheis): Add support for additional protocols for network.
52+
# Until then, continue enforcing the compute choices.
53+
parser.add_argument(
54+
"--proto",
55+
metavar="<proto>",
56+
default="tcp",
57+
choices=['icmp', 'tcp', 'udp'],
58+
type=_convert_to_lowercase,
59+
help="IP protocol (icmp, tcp, udp; default: tcp)",
60+
)
61+
source_group = parser.add_mutually_exclusive_group()
62+
source_group.add_argument(
63+
"--src-ip",
64+
metavar="<ip-address>",
65+
default="0.0.0.0/0",
66+
help="Source IP address block (may use CIDR notation; default: "
67+
"0.0.0.0/0)",
68+
)
69+
source_group.add_argument(
70+
"--src-group",
71+
metavar="<group>",
72+
help="Source security group (ID only)",
73+
)
74+
parser.add_argument(
75+
"--dst-port",
76+
metavar="<port-range>",
77+
default=(0, 0),
78+
action=parseractions.RangeAction,
79+
help="Destination port, may be a single port or port range: "
80+
"137:139 (only required for IP protocols tcp and udp)",
81+
)
82+
return parser
83+
84+
def take_action_network(self, client, parsed_args):
85+
# Get the security group ID to hold the rule.
86+
security_group_id = client.find_security_group(
87+
parsed_args.group,
88+
ignore_missing=False
89+
).id
90+
91+
# Build the create attributes.
92+
attrs = {}
93+
# TODO(rtheis): Add --direction option. Until then, continue
94+
# with the default of 'ingress'.
95+
attrs['direction'] = 'ingress'
96+
# TODO(rtheis): Add --ethertype option. Until then, continue
97+
# with the default of 'IPv4'
98+
attrs['ethertype'] = 'IPv4'
99+
# TODO(rtheis): Add port range support (type and code) for icmp
100+
# protocol. Until then, continue ignoring the port range.
101+
if parsed_args.proto != 'icmp':
102+
attrs['port_range_min'] = parsed_args.dst_port[0]
103+
attrs['port_range_max'] = parsed_args.dst_port[1]
104+
attrs['protocol'] = parsed_args.proto
105+
if parsed_args.src_group is not None:
106+
attrs['remote_group_id'] = parsed_args.src_group
107+
else:
108+
attrs['remote_ip_prefix'] = parsed_args.src_ip
109+
attrs['security_group_id'] = security_group_id
110+
111+
# Create and show the security group rule.
112+
obj = client.create_security_group_rule(**attrs)
113+
columns = _get_columns(obj)
114+
data = utils.get_item_properties(obj, columns)
115+
return (columns, data)
116+
117+
def take_action_compute(self, client, parsed_args):
118+
group = utils.find_resource(
119+
client.security_groups,
120+
parsed_args.group,
121+
)
122+
if parsed_args.proto == 'icmp':
123+
from_port, to_port = -1, -1
124+
else:
125+
from_port, to_port = parsed_args.dst_port
126+
obj = client.security_group_rules.create(
127+
group.id,
128+
parsed_args.proto,
129+
from_port,
130+
to_port,
131+
parsed_args.src_ip,
132+
parsed_args.src_group,
133+
)
134+
return _format_security_group_rule_show(obj._info)
135+
136+
37137
class DeleteSecurityGroupRule(common.NetworkAndComputeCommand):
38138
"""Delete a security group rule"""
39139

openstackclient/tests/compute/v2/fakes.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,13 +393,13 @@ def create_one_security_group_rule(attrs=None, methods=None):
393393

394394
# Set default attributes.
395395
security_group_rule_attrs = {
396-
'from_port': -1,
396+
'from_port': 0,
397397
'group': {},
398398
'id': 'security-group-rule-id-' + uuid.uuid4().hex,
399-
'ip_protocol': 'icmp',
399+
'ip_protocol': 'tcp',
400400
'ip_range': {'cidr': '0.0.0.0/0'},
401401
'parent_group_id': 'security-group-id-' + uuid.uuid4().hex,
402-
'to_port': -1,
402+
'to_port': 0,
403403
}
404404

405405
# Overwrite default attributes.

0 commit comments

Comments
 (0)