summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEtrik Patricella <epatrice@cisco.com>2015-03-17 12:30:32 -0400
committerEtrik Patricella <epatrice@cisco.com>2015-03-17 14:16:53 -0400
commit8f897b9813d798ca5252d71d030f9044cf10241d (patch)
tree23578a101050b7fc488ed5223ec4fec76049acd4
parentbfe8dcc397da0c9cc103752659022e0d0facf0b5 (diff)
downloadopenstack-ansible-modules-8f897b9813d798ca5252d71d030f9044cf10241d.tar.gz
Add support for source groups by name
test
-rw-r--r--neutron_sec_group117
1 files changed, 78 insertions, 39 deletions
diff --git a/neutron_sec_group b/neutron_sec_group
index f397e0a..52e57e3 100644
--- a/neutron_sec_group
+++ b/neutron_sec_group
@@ -64,7 +64,7 @@ options:
description:
- "List of security group rules. Available parameters of a rule:
direction, port_range_min, port_range_max, ethertype, protocol,
- remote_ip_prefix/remote_ip_group"
+ remote_ip_prefix|remote_group_id|remote_group_name"
required: false
default: none
requirements: ["neutronclient", "keystoneclient"]
@@ -93,6 +93,18 @@ neutron_sec_group:
ethertype: "IPv4"
protocol: "tcp"
remote_ip_prefix: "10.0.0.1/24"
+ - direction: "ingress"
+ port_range_min: "22"
+ port_range_max: "22"
+ ethertype: "IPv4"
+ protocol: "tcp"
+ remote_group_id: UUID_OF_GROUP
+ - direction: "ingress"
+ port_range_min: "22"
+ port_range_max: "22"
+ ethertype: "IPv4"
+ protocol: "tcp"
+ remote_group_name: 'default'
'''
try:
@@ -102,13 +114,14 @@ try:
except ImportError:
print "failed=True msg='neutronclient and keystoneclient are required'"
+
def main():
"""
Main function - entry point. The magic starts here ;-)
"""
module = AnsibleModule(
argument_spec=dict(
- auth_url=dict(default="http://127.0.0.1:5000/v2.0/"),
+ auth_url=dict(default='http://127.0.0.1:5000/v2.0/'),
login_username=dict(required=True),
login_password=dict(required=True),
login_tenant_name=dict(required=True),
@@ -117,7 +130,7 @@ def main():
region_name=dict(default=None),
rules=dict(default=None),
tenant_name=dict(required=False),
- state=dict(default="present", choices=['present', 'absent'])
+ state=dict(default='present', choices=['present', 'absent'])
),
supports_check_mode=True
)
@@ -126,35 +139,38 @@ def main():
try:
# Get id of security group (as a result check whether it exists)
+ tenant_id = _get_tenant_id(module, identity_client)
+
params = {
- 'name': module.params['name'],
- 'tenant_id': _get_tenant_id(module, identity_client),
- 'fields': 'id'
+ 'name': module.params['name'],
+ 'tenant_id': tenant_id,
+ 'fields': 'id',
}
- sec_groups = network_client.list_security_groups(**params)["security_groups"]
+
+ sec_groups = network_client.list_security_groups(**params)['security_groups']
if len(sec_groups) > 1:
- raise exceptions.NeutronClientNoUniqueMatch(resource='security_group',name=name)
+ raise exceptions.NeutronClientNoUniqueMatch(resource='security_group', name=name)
elif len(sec_groups) == 0:
- sec_group_exists = False
+ sec_group_exists = False
else:
- sec_group = sec_groups[0]
- sec_group_exists = True
+ sec_group = sec_groups[0]
+ sec_group_exists = True
# state=present -> create or update depending on whether sg exists.
- if module.params['state'] == "present":
+ if module.params['state'] == 'present':
# UPDATE
if sec_group_exists:
- changed, sg = _update_sg(module, network_client, sec_group)
+ changed, sg = _update_sg(module, network_client, sec_group, tenant_id)
if changed:
module.exit_json(sec_group=sg, updated=True, changed=changed)
else:
module.exit_json(sec_group=sg, changed=changed)
# CREATE
else:
- sg = _create_sg(module, network_client, identity_client)
+ sg = _create_sg(module, network_client, tenant_id)
module.exit_json(sec_group=sg, created=True, changed=True)
# DELETE
- elif module.params['state'] == "absent" and sec_group_exists:
+ elif module.params['state'] == 'absent' and sec_group_exists:
_delete_sg(module, network_client, sec_group)
module.exit_json(changed=True)
@@ -165,6 +181,7 @@ def main():
except Exception as exc:
module.fail_json(msg="Error: %s" % str(exc))
+
def _delete_sg(module, network_client, sec_group):
"""
Deletes a security group.
@@ -177,7 +194,7 @@ def _delete_sg(module, network_client, sec_group):
network_client.delete_security_group(sec_group['id'])
-def _create_sg(module, network_client, identity_client):
+def _create_sg(module, network_client, tenant_id):
"""
Creates a security group.
:param module: module to get security group params from.
@@ -188,26 +205,23 @@ def _create_sg(module, network_client, identity_client):
"""
if module.check_mode:
return None
- # NOTE: we don't do explicit rule validation, the API server will take
- # care of that for us :-)
- rules = module.params['rules']
data = {
- "security_group": {
- "name": module.params['name'],
- "description": module.params['description'],
- 'tenant_id': _get_tenant_id(module, identity_client)
+ 'security_group': {
+ 'name': module.params['name'],
+ 'description': module.params['description'],
+ 'tenant_id': tenant_id
}
}
sg = network_client.create_security_group(data)
- sg = sg["security_group"]
+ sg = sg['security_group']
- changed, sg = _update_sg(module, network_client, sg)
+ changed, sg = _update_sg(module, network_client, sg, tenant_id)
return sg
-def _update_sg(module, network_client, sg):
+def _update_sg(module, network_client, sg, tenant_id):
"""
Updates a security group.
:param module: module to get updated security group param from.
@@ -220,17 +234,17 @@ def _update_sg(module, network_client, sg):
sg = sg['security_group']
# We only allow description updating, no name updating
- if module.params["description"] \
+ if module.params['description'] \
and not module.params['description'] == sg['description'] \
and module.check_mode:
changed = True
- elif module.params["description"] \
+ elif module.params['description'] \
and not module.params['description'] == sg['description'] \
and not module.check_mode:
body = {
- "security_group": {
- "description": module.params["description"]
+ 'security_group': {
+ 'description': module.params['description']
}
}
sg = network_client.update_security_group(sg['id'], body)
@@ -287,7 +301,7 @@ def _update_sg_rules(module, network_client, sg, wanted_rules):
new_rules = [rule for rule in wanted_rules if 'done' not in rule]
if len(new_rules):
if not module.check_mode:
- sg = _create_sg_rules(network_client, sg, new_rules)
+ sg = _create_sg_rules(network_client, sg, new_rules, tenant_id)
changed = True
#then delete not ok
@@ -301,7 +315,7 @@ def _update_sg_rules(module, network_client, sg, wanted_rules):
return changed
-def _create_sg_rules(network_client, sg, rules):
+def _create_sg_rules(network_client, sg, rules, tenant_id):
"""
Creates a set of security group rules in a given security group.
:param network_client: network client to use to create rules.
@@ -311,10 +325,15 @@ def _create_sg_rules(network_client, sg, rules):
"""
if rules:
for rule in rules:
+ if 'remote_group_name' in rule:
+ rule['remote_group_id'] = _get_security_group_id(network_client,
+ rule['remote_group_name'],
+ tenant_id)
+ rule.pop('remote_group_name', None)
rule['tenant_id'] = sg['tenant_id']
rule['security_group_id'] = sg['id']
data = {
- "security_group_rule": rule
+ 'security_group_rule': rule
}
network_client.create_security_group_rule(data)
@@ -323,23 +342,43 @@ def _create_sg_rules(network_client, sg, rules):
return sg
+def _get_security_group_id(network_client, group_name, tenant_id):
+ """
+ Lookup the UUID for a named security group. This provides the ability to
+ specify a SourceGroup via remote_group_id.
+
+ http://docs.openstack.org/openstack-ops/content/security_groups.html
+
+ This will return the first match to a group name.
+ :param network_client: network client ot use to lookup group_id
+ :param group_name: The name of the security group to lookup
+ """
+
+ params = {
+ 'name': group_name,
+ 'tenant_id': tenant_id,
+ 'fields': 'id'
+ }
+
+ return network_client.list_security_groups(**params)['security_groups'][0]['id']
+
+
def _get_tenant_id(module, identity_client):
"""
Returns the tenant_id, given tenant_name.
- if tenant_name is not specified in the module params uses tenant_id
- from Keystone session
+ if tenant_name is not specified in the module params uses login_tenant_name
:param identity_client: identity_client used to get the tenant_id from its
name.
:param module_params: module parameters.
"""
if not module.params['tenant_name']:
- tenant_id = identity_client.tenant_id
+ tenant_name = module.params['login_tenant_name']
else:
tenant_name = module.params['tenant_name']
- tenant = _get_tenant(identity_client, tenant_name)
- tenant_id = tenant.id
- return tenant_id
+ tenant = _get_tenant(identity_client, tenant_name)
+
+ return tenant.id
def _get_tenant(identity_client, tenant_name):