2
# Licensed under the Apache License, Version 2.0 (the "License"); you may
3
# not use this file except in compliance with the License. You may obtain
4
# a copy of the License at
6
# http://www.apache.org/licenses/LICENSE-2.0
8
# Unless required by applicable law or agreed to in writing, software
9
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
10
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
11
# License for the specific language governing permissions and limitations
14
from heat.common.i18n import _
15
from heat.engine import attributes
16
from heat.engine import constraints
17
from heat.engine import properties
18
from heat.engine import resource
21
class NetworkInterface(resource.Resource):
24
DESCRIPTION, GROUP_SET, PRIVATE_IP_ADDRESS, SOURCE_DEST_CHECK,
27
'Description', 'GroupSet', 'PrivateIpAddress', 'SourceDestCheck',
38
PRIVATE_IP_ADDRESS_ATTR,
44
DESCRIPTION: properties.Schema(
45
properties.Schema.STRING,
46
_('Description for this interface.')
48
GROUP_SET: properties.Schema(
49
properties.Schema.LIST,
50
_('List of security group IDs associated with this interface.'),
53
PRIVATE_IP_ADDRESS: properties.Schema(
54
properties.Schema.STRING
56
SOURCE_DEST_CHECK: properties.Schema(
57
properties.Schema.BOOLEAN,
58
_('Flag indicating if traffic to or from instance is validated.'),
61
SUBNET_ID: properties.Schema(
62
properties.Schema.STRING,
63
_('Subnet ID to associate with this interface.'),
66
constraints.CustomConstraint('neutron.subnet')
69
TAGS: properties.Schema(
70
properties.Schema.LIST,
71
schema=properties.Schema(
72
properties.Schema.MAP,
73
_('List of tags associated with this interface.'),
75
TAG_KEY: properties.Schema(
76
properties.Schema.STRING,
79
TAG_VALUE: properties.Schema(
80
properties.Schema.STRING,
90
PRIVATE_IP_ADDRESS: attributes.Schema(
91
_('Private IP address of the network interface.')
95
default_client_name = 'neutron'
98
def network_id_from_subnet_id(neutronclient, subnet_id):
99
subnet_info = neutronclient.show_subnet(subnet_id)
100
return subnet_info['subnet']['network_id']
102
def __init__(self, name, json_snippet, stack):
103
super(NetworkInterface, self).__init__(name, json_snippet, stack)
104
self.fixed_ip_address = None
106
def handle_create(self):
107
client = self.neutron()
109
subnet_id = self.properties[self.SUBNET_ID]
110
network_id = self.client_plugin().network_id_from_subnet_id(
113
fixed_ip = {'subnet_id': subnet_id}
114
if self.properties[self.PRIVATE_IP_ADDRESS]:
115
fixed_ip['ip_address'] = self.properties[self.PRIVATE_IP_ADDRESS]
118
'name': self.physical_resource_name(),
119
'admin_state_up': True,
120
'network_id': network_id,
121
'fixed_ips': [fixed_ip]
123
# if without group_set, don't set the 'security_groups' property,
124
# neutron will create the port with the 'default' securityGroup,
125
# if has the group_set and the value is [], which means to create the
126
# port without securityGroup(same as the behavior of neutron)
127
if self.properties[self.GROUP_SET] is not None:
128
sgs = self.client_plugin().get_secgroup_uuids(
129
self.properties.get(self.GROUP_SET))
130
props['security_groups'] = sgs
131
port = client.create_port({'port': props})['port']
132
self.resource_id_set(port['id'])
134
def handle_delete(self):
135
if self.resource_id is None:
138
client = self.neutron()
140
client.delete_port(self.resource_id)
141
except Exception as ex:
142
self.client_plugin().ignore_not_found(ex)
144
def handle_update(self, json_snippet, tmpl_diff, prop_diff):
147
if self.GROUP_SET in prop_diff:
148
group_set = prop_diff.get(self.GROUP_SET)
149
# update should keep the same behavior as creation,
150
# if without the GroupSet in update template, we should
151
# update the security_groups property to referent
152
# the 'default' security group
153
if group_set is not None:
154
sgs = self.client_plugin().get_secgroup_uuids(group_set)
156
sgs = self.client_plugin().get_secgroup_uuids(['default'])
158
update_props['security_groups'] = sgs
160
self.neutron().update_port(self.resource_id,
161
{'port': update_props})
163
def _get_fixed_ip_address(self, ):
164
if self.fixed_ip_address is None:
165
client = self.neutron()
167
port = client.show_port(self.resource_id)['port']
168
if port['fixed_ips'] and len(port['fixed_ips']) > 0:
169
self.fixed_ip_address = port['fixed_ips'][0]['ip_address']
170
except Exception as ex:
171
self.client_plugin().ignore_not_found(ex)
173
return self.fixed_ip_address
175
def _resolve_attribute(self, name):
176
if name == self.PRIVATE_IP_ADDRESS:
177
return self._get_fixed_ip_address()
180
def resource_mapping():
182
'AWS::EC2::NetworkInterface': NetworkInterface,