aboutsummaryrefslogtreecommitdiffstats
path: root/aria/multivim-plugin/openstack_plugin_common/security_group.py
blob: 0fa21aa149fa99a30056caf65a940fab35fa9d33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#########
# Copyright (c) 2014 GigaSpaces Technologies Ltd. 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.

import copy
import re

from cloudify import ctx
from cloudify.exceptions import NonRecoverableError

from openstack_plugin_common import (
    get_resource_id,
    use_external_resource,
    delete_resource_and_runtime_properties,
    validate_resource,
    validate_ip_or_range_syntax,
    OPENSTACK_ID_PROPERTY,
    OPENSTACK_TYPE_PROPERTY,
    OPENSTACK_NAME_PROPERTY,
    COMMON_RUNTIME_PROPERTIES_KEYS
)

SECURITY_GROUP_OPENSTACK_TYPE = 'security_group'

# Runtime properties
RUNTIME_PROPERTIES_KEYS = COMMON_RUNTIME_PROPERTIES_KEYS

NODE_NAME_RE = re.compile('^(.*)_.*$')  # Anything before last underscore


def build_sg_data(args=None):
    security_group = {
        'description': None,
        'name': get_resource_id(ctx, SECURITY_GROUP_OPENSTACK_TYPE),
    }

    args = args or {}
    security_group.update(ctx.node.properties['security_group'], **args)

    return security_group


def process_rules(client, sgr_default_values, cidr_field_name,
                  remote_group_field_name, min_port_field_name,
                  max_port_field_name):
    rules_to_apply = ctx.node.properties['rules']
    security_group_rules = []
    for rule in rules_to_apply:
        security_group_rules.append(
            _process_rule(rule, client, sgr_default_values, cidr_field_name,
                          remote_group_field_name, min_port_field_name,
                          max_port_field_name))

    return security_group_rules


def use_external_sg(client):
    return use_external_resource(ctx, client,
                                 SECURITY_GROUP_OPENSTACK_TYPE)


def set_sg_runtime_properties(sg, client):
    ctx.instance.runtime_properties[OPENSTACK_ID_PROPERTY] =\
        client.get_id_from_resource(sg)
    ctx.instance.runtime_properties[OPENSTACK_TYPE_PROPERTY] =\
        SECURITY_GROUP_OPENSTACK_TYPE
    ctx.instance.runtime_properties[OPENSTACK_NAME_PROPERTY] = \
        client.get_name_from_resource(sg)


def delete_sg(client, **kwargs):
    delete_resource_and_runtime_properties(ctx, client,
                                           RUNTIME_PROPERTIES_KEYS)


def sg_creation_validation(client, cidr_field_name, **kwargs):
    validate_resource(ctx, client, SECURITY_GROUP_OPENSTACK_TYPE)

    ctx.logger.debug('validating CIDR for rules with a {0} field'.format(
        cidr_field_name))
    for rule in ctx.node.properties['rules']:
        if cidr_field_name in rule:
            validate_ip_or_range_syntax(ctx, rule[cidr_field_name])


def _process_rule(rule, client, sgr_default_values, cidr_field_name,
                  remote_group_field_name, min_port_field_name,
                  max_port_field_name):
    ctx.logger.debug(
        "Security group rule before transformations: {0}".format(rule))

    sgr = copy.deepcopy(sgr_default_values)
    if 'port' in rule:
        rule[min_port_field_name] = rule['port']
        rule[max_port_field_name] = rule['port']
        del rule['port']
    sgr.update(rule)

    if (remote_group_field_name in sgr) and sgr[remote_group_field_name]:
        sgr[cidr_field_name] = None
    elif ('remote_group_node' in sgr) and sgr['remote_group_node']:
        _, remote_group_node = _capabilities_of_node_named(
            sgr['remote_group_node'])
        sgr[remote_group_field_name] = remote_group_node[OPENSTACK_ID_PROPERTY]
        del sgr['remote_group_node']
        sgr[cidr_field_name] = None
    elif ('remote_group_name' in sgr) and sgr['remote_group_name']:
        sgr[remote_group_field_name] = \
            client.get_id_from_resource(
                client.cosmo_get_named(
                    SECURITY_GROUP_OPENSTACK_TYPE, sgr['remote_group_name']))
        del sgr['remote_group_name']
        sgr[cidr_field_name] = None

    ctx.logger.debug(
        "Security group rule after transformations: {0}".format(sgr))
    return sgr


def _capabilities_of_node_named(node_name):
    result = None
    caps = ctx.capabilities.get_all()
    for node_id in caps:
        match = NODE_NAME_RE.match(node_id)
        if match:
            candidate_node_name = match.group(1)
            if candidate_node_name == node_name:
                if result:
                    raise NonRecoverableError(
                        "More than one node named '{0}' "
                        "in capabilities".format(node_name))
                result = (node_id, caps[node_id])
    if not result:
        raise NonRecoverableError(
            "Could not find node named '{0}' "
            "in capabilities".format(node_name))
    return result