update from RIFT as of 696b75d2fe9fb046261b08c616f1bcf6c0b54a9b second try
[osm/SO.git] / rwcal / plugins / vala / rwcal_openstack / rift / rwcal / openstack / utils / network.py
1 #!/usr/bin/python
2
3 #
4 # Copyright 2017 RIFT.IO Inc
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 # http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17 #
18 import gi
19 gi.require_version('RwcalYang', '1.0')
20 from gi.repository import RwcalYang
21 import neutronclient.common.exceptions as NeutronException
22
23
24 class NetworkUtils(object):
25 """
26 Utility class for network operations
27 """
28 def __init__(self, driver):
29 """
30 Constructor for class
31 Arguments:
32 driver: object of OpenstackDriver()
33 """
34 self._driver = driver
35 self.log = driver.log
36
37 @property
38 def driver(self):
39 return self._driver
40
41 def _parse_cp(self, cp_info):
42 """
43 Parse the port_info dictionary returned by neutronclient
44 Arguments:
45 cp_info: A dictionary object representing port attributes
46
47 Returns:
48 Protobuf GI oject of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList_ConnectionPoints()
49 """
50 cp = RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList_ConnectionPoints()
51 if 'name' in cp_info and cp_info['name']:
52 cp.name = cp_info['name']
53
54 if 'id' in cp_info and cp_info['id']:
55 cp.connection_point_id = cp_info['id']
56
57 if ('fixed_ips' in cp_info) and (len(cp_info['fixed_ips']) >= 1):
58 if 'ip_address' in cp_info['fixed_ips'][0]:
59 cp.ip_address = cp_info['fixed_ips'][0]['ip_address']
60
61 if 'mac_address' in cp_info and cp_info['mac_address']:
62 cp.mac_addr = cp_info['mac_address']
63
64 if cp_info['status'] == 'ACTIVE':
65 cp.state = 'active'
66 else:
67 cp.state = 'inactive'
68
69 if 'network_id' in cp_info and cp_info['network_id']:
70 cp.virtual_link_id = cp_info['network_id']
71
72 if 'device_id' in cp_info and cp_info['device_id']:
73 cp.vdu_id = cp_info['device_id']
74
75 if 'allowed_address_pairs' in cp_info and cp_info['allowed_address_pairs']:
76 for vcp in cp_info['allowed_address_pairs']:
77 vcp_info = cp.virtual_cp_info.add()
78 if 'ip_address' in vcp and vcp['ip_address']:
79 vcp_info.ip_address = vcp['ip_address']
80 if 'mac_address' in vcp and vcp['mac_address']:
81 vcp_info.mac_address = vcp['mac_address']
82 return cp
83
84 def _parse_virtual_cp(self, cp_info):
85 """
86 Parse the port_info dictionary returned by neutronclient
87 Arguments:
88 cp_info: A dictionary object representing port attributes
89
90 Returns:
91 Protobuf GI oject of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList_VirtualConnectionPoints()
92 """
93 cp = RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList_VirtualConnectionPoints()
94
95 if 'id' in cp_info and cp_info['id']:
96 cp.connection_point_id = cp_info['id']
97
98 if 'name' in cp_info and cp_info['name']:
99 cp.name = cp_info['name']
100
101 if ('fixed_ips' in cp_info) and (len(cp_info['fixed_ips']) >= 1):
102 if 'ip_address' in cp_info['fixed_ips'][0]:
103 cp.ip_address = cp_info['fixed_ips'][0]['ip_address']
104
105 if 'mac_address' in cp_info and cp_info['mac_address']:
106 cp.mac_address = cp_info['mac_address']
107
108 return cp
109
110 def parse_cloud_virtual_link_info(self, vlink_info, port_list, subnet):
111 """
112 Parse vlink_info dictionary (return by python-client) and put values in GI object for Virtual Link
113
114 Arguments:
115 vlink_info : A dictionary object return by neutronclient library listing network attributes
116
117 Returns:
118 Protobuf GI Object of type RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList()
119 """
120 link = RwcalYang.YangData_RwProject_Project_VnfResources_VirtualLinkInfoList()
121 link.name = vlink_info['name']
122 if 'status' in vlink_info and vlink_info['status'] == 'ACTIVE':
123 link.state = 'active'
124 else:
125 link.state = 'inactive'
126
127 link.virtual_link_id = vlink_info['id']
128 for port in port_list:
129 if ('device_owner' in port) and (port['device_owner'] in ['compute:nova', 'compute:None']):
130 link.connection_points.append(self._parse_cp(port))
131 if ('device_owner' in port) and (port['device_owner'] == ''):
132 link.virtual_connection_points.append(self._parse_virtual_cp(port))
133
134 if subnet is not None:
135 link.subnet = subnet['cidr']
136
137 if ('provider:network_type' in vlink_info) and (vlink_info['provider:network_type'] != None):
138 link.provider_network.overlay_type = vlink_info['provider:network_type'].upper()
139 if ('provider:segmentation_id' in vlink_info) and (vlink_info['provider:segmentation_id']):
140 link.provider_network.segmentation_id = vlink_info['provider:segmentation_id']
141 if ('provider:physical_network' in vlink_info) and (vlink_info['provider:physical_network']):
142 link.provider_network.physical_network = vlink_info['provider:physical_network'].upper()
143
144 return link
145
146 def setup_vdu_networking(self, vdu_params):
147 """
148 This function validates the networking/connectivity setup.
149
150 Arguments:
151 vdu_params: object of RwcalYang.YangData_RwProject_Project_VduInitParams()
152
153 Returns:
154 A list of port_ids and network_ids for VDU
155
156 """
157 port_args = list()
158 network_ids = list()
159 add_mgmt_net = False
160
161 # Sorting Connection Points by given 'port_order'. If 'port_order' is not given then sorting by name.
162 # Please note that the GI Object (vdu_params.connection_points) has been converted into a dictionary object for sorting purposes.
163
164 sorted_connection_points = []
165 if vdu_params.has_field('connection_points'):
166 sorted_connection_points = sorted(vdu_params.as_dict().get('connection_points'), key=lambda k: ("port_order" not in k,
167 k.get("port_order", None), k['name']))
168
169 if vdu_params.mgmt_network is not None:
170 # Setting the mgmt network as found in vdu params.
171 mgmt_network = self.driver.neutron_drv.network_get(network_name=vdu_params.mgmt_network)['id']
172 else:
173 mgmt_network = self.driver._mgmt_network_id
174
175 for cp in sorted_connection_points:
176 if cp['virtual_link_id'] == mgmt_network:
177 ### Remove mgmt_network_id from net_ids
178 add_mgmt_net = True
179 port_args.append(self._create_cp_args(cp))
180 if not add_mgmt_net:
181 network_ids.append(mgmt_network)
182
183 ### Create ports and collect port ids
184 if port_args:
185 port_ids = self.driver.neutron_multi_port_create(port_args)
186 else:
187 port_ids = list()
188 return port_ids, network_ids
189
190
191 def _create_cp_args(self, cp):
192 """
193 Creates a request dictionary for port create call
194 Arguments:
195 cp: Object of Python Dictionary
196 Returns:
197 dict() of request params
198 """
199 args = dict()
200 args['name'] = cp['name']
201
202 args['network_id'] = cp['virtual_link_id']
203 args['admin_state_up'] = True
204
205 if cp['type_yang'] in ['VIRTIO', 'E1000', 'VPORT']:
206 args['binding:vnic_type'] = 'normal'
207 elif cp['type_yang'] == 'SR_IOV':
208 args['binding:vnic_type'] = 'direct'
209 else:
210 raise NotImplementedError("Port Type: %s not supported" %(cp['type_yang']))
211
212 try:
213 if cp['static_ip_address']:
214 args["fixed_ips"] = [{"ip_address" : cp['static_ip_address']}]
215 except Exception as e:
216 pass
217
218 if 'port_security_enabled' in cp:
219 args['port_security_enabled'] = cp['port_security_enabled']
220
221 if 'security_group' in cp:
222 if self.driver._neutron_security_groups:
223 gid = self.driver._neutron_security_groups[0]['id']
224 args['security_groups'] = [ gid ]
225
226 if 'virtual_cps' in cp:
227 args['allowed_address_pairs'] = [ {'ip_address': vcp['ip_address'],
228 'mac_address': vcp['mac_address']}
229 for vcp in cp['virtual_cps'] ]
230
231 return args
232
233 def make_virtual_link_args(self, link_params):
234 """
235 Function to create kwargs required for neutron_network_create API
236
237 Arguments:
238 link_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VirtualLinkReqParams()
239
240 Returns:
241 A kwargs dictionary for network operation
242 """
243 kwargs = dict()
244 kwargs['name'] = link_params.name
245 kwargs['admin_state_up'] = True
246 kwargs['external_router'] = False
247 kwargs['shared'] = False
248
249 if link_params.has_field('provider_network'):
250 if link_params.provider_network.has_field('physical_network'):
251 kwargs['physical_network'] = link_params.provider_network.physical_network
252 if link_params.provider_network.has_field('overlay_type'):
253 kwargs['network_type'] = link_params.provider_network.overlay_type.lower()
254 if link_params.provider_network.has_field('segmentation_id'):
255 kwargs['segmentation_id'] = link_params.provider_network.segmentation_id
256
257 return kwargs
258
259 def make_subnet_args(self, link_params, network_id):
260 """
261 Function to create kwargs required for neutron_subnet_create API
262
263 Arguments:
264 link_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VirtualLinkReqParams()
265
266 Returns:
267 A kwargs dictionary for subnet operation
268 """
269 kwargs = {'network_id' : network_id,
270 'dhcp_params': {'enable_dhcp': True},
271 'gateway_ip' : None,}
272
273 if link_params.ip_profile_params.has_field('ip_version'):
274 kwargs['ip_version'] = 6 if link_params.ip_profile_params.ip_version == 'ipv6' else 4
275 else:
276 kwargs['ip_version'] = 4
277
278 if link_params.ip_profile_params.has_field('subnet_address'):
279 kwargs['cidr'] = link_params.ip_profile_params.subnet_address
280 elif link_params.ip_profile_params.has_field('subnet_prefix_pool'):
281 name = link_params.ip_profile_params.subnet_prefix_pool
282 pools = [ p['id'] for p in self.driver._neutron_subnet_prefix_pool if p['name'] == name ]
283 if not pools:
284 self.log.error("Could not find subnet pool with name :%s to be used for network: %s",
285 link_params.ip_profile_params.subnet_prefix_pool,
286 link_params.name)
287 raise NeutronException.NotFound("SubnetPool with name %s not found"%(link_params.ip_profile_params.subnet_prefix_pool))
288
289 kwargs['subnetpool_id'] = pools[0]
290
291 elif link_params.has_field('subnet'):
292 kwargs['cidr'] = link_params.subnet
293 else:
294 raise NeutronException.NeutronException("No IP Prefix or Pool name specified")
295
296 if link_params.ip_profile_params.has_field('dhcp_params'):
297 if link_params.ip_profile_params.dhcp_params.has_field('enabled'):
298 kwargs['dhcp_params']['enable_dhcp'] = link_params.ip_profile_params.dhcp_params.enabled
299 if link_params.ip_profile_params.dhcp_params.has_field('start_address'):
300 kwargs['dhcp_params']['start_address'] = link_params.ip_profile_params.dhcp_params.start_address
301 if link_params.ip_profile_params.dhcp_params.has_field('count'):
302 kwargs['dhcp_params']['count'] = link_params.ip_profile_params.dhcp_params.count
303
304 if link_params.ip_profile_params.has_field('dns_server'):
305 kwargs['dns_server'] = []
306 for server in link_params.ip_profile_params.dns_server:
307 kwargs['dns_server'].append(server.address)
308
309 if link_params.ip_profile_params.has_field('gateway_address'):
310 kwargs['gateway_ip'] = link_params.ip_profile_params.gateway_address
311
312 return kwargs
313
314 def prepare_virtual_link(self, link_params, network_id):
315 """
316 Function to create additional resources in the network during
317 network-creation process. It involves following steps
318 - Create subnets
319 - Create any virtual ports in network
320
321 Arguments:
322 link_params: Protobuf GI object RwcalYang.YangData_RwProject_Project_VirtualLinkReqParams()
323 network_id: string
324
325 Returns:
326 None
327 """
328 ### Create subnet
329 kwargs = self.make_subnet_args(link_params, network_id)
330 self.driver.neutron_subnet_create(**kwargs)
331
332 ### Create Virtual connection point
333 if link_params.has_field('virtual_cps'):
334 port_args = list()
335 for vcp in link_params.virtual_cps:
336 cp = RwcalYang.YangData_RwProject_Project_VduInitParams_ConnectionPoints()
337 cp.from_dict({k:v for k,v in vcp.as_dict().items()
338 if k in ['name','security_group', 'port_security_enabled', 'static_ip_address', 'type_yang']})
339 cp.virtual_link_id = network_id
340 port_args.append(self._create_cp_args(cp.as_dict()))
341 if port_args:
342 ### Create ports
343 self.driver.neutron_multi_port_create(port_args)
344 return