diff options
| author | Dean Troyer <dtroyer@gmail.com> | 2013-07-12 15:49:03 -0500 |
|---|---|---|
| committer | Dean Troyer <dtroyer@gmail.com> | 2013-07-29 19:07:22 -0500 |
| commit | c94e262df8d2d37e6c2043a3c3d0bc1cb78348a5 (patch) | |
| tree | 4db83cbff672f27f8d5ff94f9d97b03a4ba4d412 /openstackclient/compute | |
| parent | 65d2a14e3e834ce0c57c879ec7d42715058254bf (diff) | |
| download | python-openstackclient-c94e262df8d2d37e6c2043a3c3d0bc1cb78348a5.tar.gz | |
Add security group commands
* Add security group: create, delete, list, set, show
* Add server: add secgroup, remove secgroup
* Add security group rule: create, delete, list
* Add Oslo's strutils and gettextutils
* Adds parseractions.RangeAction() to handle option arguments of either a single number
or a range of numbers: '--port 25' or '--port 1024:65535'
Blueprint: nova-client
Change-Id: Iad2de1b273ba29197709fc4c6a1036b4ae99725f
Diffstat (limited to 'openstackclient/compute')
| -rw-r--r-- | openstackclient/compute/v2/security_group.py | 394 | ||||
| -rw-r--r-- | openstackclient/compute/v2/server.py | 73 |
2 files changed, 467 insertions, 0 deletions
diff --git a/openstackclient/compute/v2/security_group.py b/openstackclient/compute/v2/security_group.py new file mode 100644 index 00000000..a1dc786d --- /dev/null +++ b/openstackclient/compute/v2/security_group.py @@ -0,0 +1,394 @@ +# Copyright 2012 OpenStack Foundation +# Copyright 2013 Nebula Inc +# +# 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. +# + +"""Compute v2 Security Group action implementations""" + +import logging +import six + +from cliff import command +from cliff import lister +from cliff import show + +from novaclient.v1_1 import security_group_rules +from openstackclient.common import parseractions +from openstackclient.common import utils + + +def _xform_security_group_rule(sgroup): + info = {} + info.update(sgroup) + info.update( + {'port_range': "%u:%u" % ( + info.pop('from_port'), + info.pop('to_port'), + )} + ) + info['ip_range'] = info['ip_range']['cidr'] + if info['ip_protocol'] == 'icmp': + info['port_range'] = '' + return info + + +class CreateSecurityGroup(show.ShowOne): + """Create a new security group""" + + log = logging.getLogger(__name__ + ".CreateSecurityGroup") + + def get_parser(self, prog_name): + parser = super(CreateSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + "name", + metavar="<name>", + help="New security group name", + ) + parser.add_argument( + "--description", + metavar="<description>", + help="Security group description", + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + + data = compute_client.security_groups.create( + parsed_args.name, + parsed_args.description, + ) + + info = {} + info.update(data._info) + return zip(*sorted(six.iteritems(info))) + + +class DeleteSecurityGroup(command.Command): + """Delete a security group""" + + log = logging.getLogger(__name__ + '.DeleteSecurityGroup') + + def get_parser(self, prog_name): + parser = super(DeleteSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Name or ID of security group to delete', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + data = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + compute_client.security_groups.delete(data.id) + return + + +class ListSecurityGroup(lister.Lister): + """List all security groups""" + + log = logging.getLogger(__name__ + ".ListSecurityGroup") + + def get_parser(self, prog_name): + parser = super(ListSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + '--all-projects', + action='store_true', + default=False, + help='Display information from all projects (admin only)', + ) + return parser + + def take_action(self, parsed_args): + + def _get_project(project_id): + try: + return getattr(project_hash[project_id], 'name', project_id) + except KeyError: + return project_id + + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + columns = ( + "ID", + "Name", + "Description", + ) + column_headers = columns + if parsed_args.all_projects: + # TODO(dtroyer): Translate Project_ID to Project (name) + columns = columns + ('Tenant ID',) + column_headers = column_headers + ('Project',) + search = {'all_tenants': parsed_args.all_projects} + data = compute_client.security_groups.list(search_opts=search) + + projects = self.app.client_manager.identity.projects.list() + project_hash = {} + for project in projects: + project_hash[project.id] = project + + return (column_headers, + (utils.get_item_properties( + s, columns, + formatters={'Tenant ID': _get_project}, + ) for s in data)) + + +class SetSecurityGroup(show.ShowOne): + """Set security group properties""" + + log = logging.getLogger(__name__ + '.SetSecurityGroup') + + def get_parser(self, prog_name): + parser = super(SetSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Name or ID of security group to change', + ) + parser.add_argument( + '--name', + metavar='<new-name>', + help='New security group name', + ) + parser.add_argument( + "--description", + metavar="<description>", + help="New security group name", + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + data = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + + if parsed_args.name: + data.name = parsed_args.name + if parsed_args.description: + data.description = parsed_args.description + + info = {} + info.update(compute_client.security_groups.update( + data, + data.name, + data.description, + )._info) + + if info: + return zip(*sorted(six.iteritems(info))) + else: + return ({}, {}) + + +class ShowSecurityGroup(show.ShowOne): + """Show a specific security group""" + + log = logging.getLogger(__name__ + '.ShowSecurityGroup') + + def get_parser(self, prog_name): + parser = super(ShowSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Name or ID of security group to change', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + info = {} + info.update(utils.find_resource( + compute_client.security_groups, + parsed_args.group, + )._info) + rules = [] + for r in info['rules']: + rules.append(utils.format_dict(_xform_security_group_rule(r))) + + # Format rules into a list of strings + info.update( + {'rules': rules} + ) + # Map 'tenant_id' column to 'project_id' + info.update( + {'project_id': info.pop('tenant_id')} + ) + + return zip(*sorted(six.iteritems(info))) + + +class CreateSecurityGroupRule(show.ShowOne): + """Create a new security group rule""" + + log = logging.getLogger(__name__ + ".CreateSecurityGroupRule") + + def get_parser(self, prog_name): + parser = super(CreateSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Create rule in this security group', + ) + parser.add_argument( + "--proto", + metavar="<proto>", + default="tcp", + help="IP protocol (icmp, tcp, udp; default: tcp)", + ) + parser.add_argument( + "--src-ip", + metavar="<ip-address>", + default="0.0.0.0/0", + help="Source IP (may use CIDR notation; default: 0.0.0.0/0)", + ) + parser.add_argument( + "--dst-port", + metavar="<port-range>", + action=parseractions.RangeAction, + help="Destination port, may be a range: 137:139 (default: 0; " + "only required for proto tcp and udp)", + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + from_port, to_port = parsed_args.dst_port + data = compute_client.security_group_rules.create( + group.id, + parsed_args.proto, + from_port, + to_port, + parsed_args.src_ip, + ) + + info = _xform_security_group_rule(data._info) + return zip(*sorted(six.iteritems(info))) + + +class DeleteSecurityGroupRule(command.Command): + """Delete a security group rule""" + + log = logging.getLogger(__name__ + '.DeleteSecurityGroupRule') + + def get_parser(self, prog_name): + parser = super(DeleteSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Create rule in this security group', + ) + parser.add_argument( + "--proto", + metavar="<proto>", + default="tcp", + help="IP protocol (icmp, tcp, udp; default: tcp)", + ) + parser.add_argument( + "--src-ip", + metavar="<ip-address>", + default="0.0.0.0/0", + help="Source IP (may use CIDR notation; default: 0.0.0.0/0)", + ) + parser.add_argument( + "--dst-port", + metavar="<port-range>", + action=parseractions.RangeAction, + help="Destination port, may be a range: 137:139 (default: 0; " + "only required for proto tcp and udp)", + ) + return parser + + def take_action(self, parsed_args): + self.log.debug('take_action(%s)' % parsed_args) + + compute_client = self.app.client_manager.compute + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + from_port, to_port = parsed_args.dst_port + # sigh...delete by ID? + compute_client.security_group_rules.delete( + group.id, + parsed_args.proto, + from_port, + to_port, + parsed_args.src_ip, + ) + return + + +class ListSecurityGroupRule(lister.Lister): + """List all security group rules""" + + log = logging.getLogger(__name__ + ".ListSecurityGroupRule") + + def get_parser(self, prog_name): + parser = super(ListSecurityGroupRule, self).get_parser(prog_name) + parser.add_argument( + 'group', + metavar='<group>', + help='Create rule in this security group', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + + # Argh, the rules are not Resources... + rules = [] + for rule in group.rules: + rules.append(security_group_rules.SecurityGroupRule( + compute_client.security_group_rules, + _xform_security_group_rule(rule), + )) + + columns = column_headers = ( + "ID", + "IP Protocol", + "IP Range", + "Port Range", + ) + return (column_headers, + (utils.get_item_properties( + s, columns, + ) for s in rules)) diff --git a/openstackclient/compute/v2/server.py b/openstackclient/compute/v2/server.py index 8f81dfdb..6be97981 100644 --- a/openstackclient/compute/v2/server.py +++ b/openstackclient/compute/v2/server.py @@ -141,6 +141,43 @@ class AddServerVolume(command.Command): ) +class AddServerSecurityGroup(command.Command): + """Add security group to server""" + + log = logging.getLogger(__name__ + '.AddServerSecurityGroup') + + def get_parser(self, prog_name): + parser = super(AddServerSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + help='Name or ID of server to use', + ) + parser.add_argument( + 'group', + metavar='<group>', + help='Name or ID of security group to add to server', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + + server = utils.find_resource( + compute_client.servers, + parsed_args.server, + ) + security_group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + + server.add_security_group(security_group) + return + + class CreateServer(show.ShowOne): """Create a new server""" @@ -731,6 +768,42 @@ class RebuildServer(show.ShowOne): return zip(*sorted(details.iteritems())) +class RemoveServerSecurityGroup(command.Command): + """Remove security group from server""" + + log = logging.getLogger(__name__ + '.RemoveServerSecurityGroup') + + def get_parser(self, prog_name): + parser = super(RemoveServerSecurityGroup, self).get_parser(prog_name) + parser.add_argument( + 'server', + metavar='<server>', + help='Name or ID of server to use', + ) + parser.add_argument( + 'group', + metavar='<group>', + help='Name or ID of security group to remove from server', + ) + return parser + + def take_action(self, parsed_args): + self.log.debug("take_action(%s)" % parsed_args) + + compute_client = self.app.client_manager.compute + + server = utils.find_resource( + compute_client.servers, + parsed_args.server, + ) + security_group = utils.find_resource( + compute_client.security_groups, + parsed_args.group, + ) + + server.remove_security_group(security_group) + + class RemoveServerVolume(command.Command): """Remove volume from server""" |
