4 # Copyright 2017 RIFT.IO Inc
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
10 # http://www.apache.org/licenses/LICENSE-2.0
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.
19 gi
.require_version('RwcalYang', '1.0')
20 from gi
.repository
import RwcalYang
21 import neutronclient
.common
.exceptions
as NeutronException
24 class NetworkUtils(object):
26 Utility class for network operations
28 def __init__(self
, driver
):
32 driver: object of OpenstackDriver()
41 def _parse_cp(self
, cp_info
):
43 Parse the port_info dictionary returned by neutronclient
45 cp_info: A dictionary object representing port attributes
48 Protobuf GI oject of type RwcalYang.VirtualLinkInfoParams_ConnectionPoints()
50 cp
= RwcalYang
.VirtualLinkInfoParams_ConnectionPoints()
51 if 'name' in cp_info
and cp_info
['name']:
52 cp
.name
= cp_info
['name']
54 if 'id' in cp_info
and cp_info
['id']:
55 cp
.connection_point_id
= cp_info
['id']
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']
61 if 'mac_address' in cp_info
and cp_info
['mac_address']:
62 cp
.mac_addr
= cp_info
['mac_address']
64 if cp_info
['status'] == 'ACTIVE':
69 if 'network_id' in cp_info
and cp_info
['network_id']:
70 cp
.virtual_link_id
= cp_info
['network_id']
72 if 'device_id' in cp_info
and cp_info
['device_id']:
73 cp
.vdu_id
= cp_info
['device_id']
76 def parse_cloud_virtual_link_info(self
, vlink_info
, port_list
, subnet
):
78 Parse vlink_info dictionary (return by python-client) and put values in GI object for Virtual Link
81 vlink_info : A dictionary object return by neutronclient library listing network attributes
84 Protobuf GI Object of type RwcalYang.VirtualLinkInfoParams()
86 link
= RwcalYang
.VirtualLinkInfoParams()
87 link
.name
= vlink_info
['name']
88 if 'status' in vlink_info
and vlink_info
['status'] == 'ACTIVE':
91 link
.state
= 'inactive'
93 link
.virtual_link_id
= vlink_info
['id']
94 for port
in port_list
:
95 if ('device_owner' in port
) and (port
['device_owner'] == 'compute:None'):
96 link
.connection_points
.append(self
._parse
_cp
(port
))
98 if subnet
is not None:
99 link
.subnet
= subnet
['cidr']
101 if ('provider:network_type' in vlink_info
) and (vlink_info
['provider:network_type'] != None):
102 link
.provider_network
.overlay_type
= vlink_info
['provider:network_type'].upper()
103 if ('provider:segmentation_id' in vlink_info
) and (vlink_info
['provider:segmentation_id']):
104 link
.provider_network
.segmentation_id
= vlink_info
['provider:segmentation_id']
105 if ('provider:physical_network' in vlink_info
) and (vlink_info
['provider:physical_network']):
106 link
.provider_network
.physical_network
= vlink_info
['provider:physical_network'].upper()
110 def setup_vdu_networking(self
, vdu_params
):
112 This function validates the networking/connectivity setup.
115 vdu_params: object of RwcalYang.VDUInitParams()
118 A list of port_ids and network_ids for VDU
124 for cp
in vdu_params
.connection_points
:
125 if cp
.virtual_link_id
== self
.driver
._mgmt
_network
_id
:
126 ### Remove mgmt_network_id from net_ids
128 port_args
.append(self
._create
_cp
_args
(cp
))
131 network_ids
.append(self
.driver
._mgmt
_network
_id
)
133 ### Create ports and collect port ids
134 port_ids
= self
.driver
.neutron_multi_port_create(port_args
)
135 return port_ids
, network_ids
138 def _create_cp_args(self
, cp
):
140 Creates a request dictionary for port create call
142 cp: Object of RwcalYang.VDUInitParams_ConnectionPoints()
144 dict() of request params
147 args
['name'] = cp
.name
148 args
['network_id'] = cp
.virtual_link_id
149 args
['admin_state_up'] = True
151 if cp
.type_yang
== 'VIRTIO' or cp
.type_yang
== 'E1000':
152 args
['binding:vnic_type'] = 'normal'
153 elif cp
.type_yang
== 'SR_IOV':
154 args
['binding:vnic_type'] = 'direct'
156 raise NotImplementedError("Port Type: %s not supported" %(cp
.type_yang
))
158 if cp
.static_ip_address
:
159 args
["fixed_ips"] = [{"ip_address" : cp
.static_ip_address
}]
161 if 'port_security_enabled' in cp
:
162 args
['port_security_enabled'] = cp
.port_security_enabled
164 if cp
.has_field('security_group'):
165 if self
.driver
._neutron
_security
_groups
:
166 gid
= self
.driver
._neutron
_security
_groups
[0]['id']
167 args
['security_groups'] = [ gid
]
170 def make_virtual_link_args(self
, link_params
):
172 Function to create kwargs required for neutron_network_create API
175 link_params: Protobuf GI object RwcalYang.VirtualLinkReqParams()
178 A kwargs dictionary for network operation
181 kwargs
['name'] = link_params
.name
182 kwargs
['admin_state_up'] = True
183 kwargs
['external_router'] = False
184 kwargs
['shared'] = False
186 if link_params
.has_field('provider_network'):
187 if link_params
.provider_network
.has_field('physical_network'):
188 kwargs
['physical_network'] = link_params
.provider_network
.physical_network
189 if link_params
.provider_network
.has_field('overlay_type'):
190 kwargs
['network_type'] = link_params
.provider_network
.overlay_type
.lower()
191 if link_params
.provider_network
.has_field('segmentation_id'):
192 kwargs
['segmentation_id'] = link_params
.provider_network
.segmentation_id
196 def make_subnet_args(self
, link_params
, network_id
):
198 Function to create kwargs required for neutron_subnet_create API
201 link_params: Protobuf GI object RwcalYang.VirtualLinkReqParams()
204 A kwargs dictionary for subnet operation
206 kwargs
= {'network_id' : network_id
,
207 'dhcp_params': {'enable_dhcp': True},
208 'gateway_ip' : None,}
210 if link_params
.ip_profile_params
.has_field('ip_version'):
211 kwargs
['ip_version'] = 6 if link_params
.ip_profile_params
.ip_version
== 'ipv6' else 4
213 kwargs
['ip_version'] = 4
215 if link_params
.ip_profile_params
.has_field('subnet_address'):
216 kwargs
['cidr'] = link_params
.ip_profile_params
.subnet_address
217 elif link_params
.ip_profile_params
.has_field('subnet_prefix_pool'):
218 name
= link_params
.ip_profile_params
.subnet_prefix_pool
219 pools
= [ p
['id'] for p
in self
.driver
._neutron
_subnet
_prefix
_pool
if p
['name'] == name
]
221 self
.log
.error("Could not find subnet pool with name :%s to be used for network: %s",
222 link_params
.ip_profile_params
.subnet_prefix_pool
,
224 raise NeutronException
.NotFound("SubnetPool with name %s not found"%(link_params
.ip_profile_params
.subnet_prefix_pool
))
226 kwargs
['subnetpool_id'] = pools
[0]
228 elif link_params
.has_field('subnet'):
229 kwargs
['cidr'] = link_params
.subnet
231 raise NeutronException
.NeutronException("No IP Prefix or Pool name specified")
233 if link_params
.ip_profile_params
.has_field('dhcp_params'):
234 if link_params
.ip_profile_params
.dhcp_params
.has_field('enabled'):
235 kwargs
['dhcp_params']['enable_dhcp'] = link_params
.ip_profile_params
.dhcp_params
.enabled
236 if link_params
.ip_profile_params
.dhcp_params
.has_field('start_address'):
237 kwargs
['dhcp_params']['start_address'] = link_params
.ip_profile_params
.dhcp_params
.start_address
238 if link_params
.ip_profile_params
.dhcp_params
.has_field('count'):
239 kwargs
['dhcp_params']['count'] = link_params
.ip_profile_params
.dhcp_params
.count
241 if link_params
.ip_profile_params
.has_field('dns_server'):
242 kwargs
['dns_server'] = []
243 for server
in link_params
.ip_profile_params
.dns_server
:
244 kwargs
['dns_server'].append(server
.address
)
246 if link_params
.ip_profile_params
.has_field('gateway_address'):
247 kwargs
['gateway_ip'] = link_params
.ip_profile_params
.gateway_address