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.
20 from neutronclient
.neutron
import client
as ntclient
22 import neutronclient
.common
.exceptions
as NeutronException
25 class NeutronAPIVersionException(Exception):
26 def __init__(self
, errors
):
28 super(NeutronAPIVersionException
, self
).__init
__("Multiple Exception Received")
31 return self
.__repr
__()
34 msg
= "{} : Following Exception(s) have occured during Neutron API discovery".format(self
.__class
__)
35 for n
,e
in enumerate(self
.errors
):
37 msg
+= " {}: {}".format(n
, str(e
))
41 class NeutronDriver(object):
43 NeutronDriver Class for network orchestration
45 ### List of supported API versions in prioritized order
46 supported_versions
= ["2"]
50 region_name
= 'RegionOne',
51 service_type
= 'network',
54 Constructor for NeutronDriver class
56 sess_handle (instance of class SessionDriver)
57 region_name (string): Region Name
58 service_type(string): Type of service in service catalog
59 logger (instance of logging.Logger)
63 self
.log
= logging
.getLogger('rwcal.openstack.neutron')
64 self
.log
.setLevel(logging
.DEBUG
)
68 self
._sess
_handle
= sess_handle
70 #### Attempt to use API versions in prioritized order defined in
71 #### NeutronDriver.supported_versions
72 def select_version(version
):
74 self
.log
.info("Attempting to use Neutron v%s APIs", version
)
75 ntdrv
= ntclient
.Client(api_version
= version
,
76 region_name
= region_name
,
77 service_type
= service_type
,
78 session
= self
._sess
_handle
.session
,
80 except Exception as e
:
84 self
.log
.info("Neutron API v%s selected", version
)
85 return (version
, ntdrv
)
88 for v
in NeutronDriver
.supported_versions
:
90 (self
._version
, self
._nt
_drv
) = select_version(v
)
91 except Exception as e
:
96 raise NeutronAPIVersionException(errors
)
99 def neutron_endpoint(self
):
100 return self
._nt
_drv
.get_auth_info()['endpoint_url']
103 def project_id(self
):
104 return self
._sess
_handle
.project_id
107 def neutron_quota(self
):
109 Returns Neutron Quota (a dictionary) for project
112 quota
= self
._nt
_drv
.show_quota(self
.project_id
)
113 except Exception as e
:
114 self
.log
.exception("Get Neutron quota operation failed. Exception: %s", str(e
))
118 def extensions_list(self
):
120 Returns a list of available neutron extensions.
124 A list of dictionaries. Each dictionary contains attributes for a single Neutron extension
127 extensions
= self
._nt
_drv
.list_extensions()
128 except Exception as e
:
129 self
.log
.exception("List extension operation failed. Exception: %s", str(e
))
131 if 'extensions' in extensions
:
132 return extensions
['extensions']
136 def _get_neutron_connection(self
):
138 Returns instance of object neutronclient.neutron.client.Client
143 def _network_find(self
, **kwargs
):
145 Returns a network object dictionary based on the filters provided in kwargs
148 kwargs (dictionary): A dictionary of key-value pair filters
151 One or more dictionary object associated with network
154 networks
= self
._nt
_drv
.list_networks(**kwargs
)['networks']
155 except Exception as e
:
156 self
.log
.exception("List network operation failed. Exception: %s", str(e
))
160 def network_list(self
):
162 Returns list of dictionaries. Each dictionary contains the attributes for a network
168 A list of dictionaries
170 return self
._network
_find
(**{'tenant_id':self
.project_id
}) + self
._network
_find
(**{'shared':True})
173 def network_create(self
, **kwargs
):
175 Creates a new network for the project
178 A dictionary with following key-values
180 name (string) : Name of the network
181 admin_state_up(Boolean) : True/False (Defaults: True)
182 external_router(Boolean) : Connectivity with external router. True/False (Defaults: False)
183 shared(Boolean) : Shared among tenants. True/False (Defaults: False)
184 physical_network(string) : The physical network where this network object is implemented (optional).
185 network_type : The type of physical network that maps to this network resource (optional).
186 Possible values are: 'flat', 'vlan', 'vxlan', 'gre'
187 segmentation_id : An isolated segment on the physical network. The network_type attribute
188 defines the segmentation model. For example, if the network_type value
189 is vlan, this ID is a vlan identifier. If the network_type value is gre,
190 this ID is a gre key.
194 {'name' : kwargs
['name'],
195 'admin_state_up' : kwargs
['admin_state_up'],
196 'tenant_id' : self
.project_id
,
197 'shared' : kwargs
['shared'],
198 #'port_security_enabled': port_security_enabled,
199 'router:external' : kwargs
['external_router']}}
201 if 'physical_network' in kwargs
:
202 params
['network']['provider:physical_network'] = kwargs
['physical_network']
203 if 'network_type' in kwargs
:
204 params
['network']['provider:network_type'] = kwargs
['network_type']
205 if 'segmentation_id' in kwargs
:
206 params
['network']['provider:segmentation_id'] = kwargs
['segmentation_id']
209 self
.log
.debug("Calling neutron create_network() with params: %s", str(params
))
210 net
= self
._nt
_drv
.create_network(params
)
211 except Exception as e
:
212 self
.log
.exception("Create Network operation failed. Exception: %s", str(e
))
215 network_id
= net
['network']['id']
217 raise Exception("Empty network id returned from create_network. (params: %s)" % str(params
))
221 def network_delete(self
, network_id
):
223 Deletes a network identified by network_id
226 network_id (string): UUID of the network
231 self
._nt
_drv
.delete_network(network_id
)
232 except Exception as e
:
233 self
.log
.exception("Delete Network operation failed. Exception: %s",str(e
))
237 def network_get(self
, network_id
='', network_name
=''):
239 Returns a dictionary object describing the attributes of the network
242 network_id (string): UUID of the network
245 A dictionary object of the network attributes
247 networks
= self
._network
_find
(**{'id': network_id
, 'name': network_name
})
249 raise NeutronException
.NotFound("Could not find network. Network id: %s, Network name: %s " %(network_id
, network_name
))
253 def subnet_create(self
, **kwargs
):
255 Creates a subnet on the network
258 A dictionary with following key value pairs
260 network_id(string) : UUID of the network where subnet needs to be created
261 subnet_cidr(string) : IPv4 address prefix (e.g. '1.1.1.0/24') for the subnet
262 ip_version (integer): 4 for IPv4 and 6 for IPv6
267 subnet_id (string): UUID of the created subnet
270 params
['network_id'] = kwargs
['network_id']
271 params
['ip_version'] = kwargs
['ip_version']
273 # if params['ip_version'] == 6:
274 # assert 0, "IPv6 is not supported"
276 if 'subnetpool_id' in kwargs
:
277 params
['subnetpool_id'] = kwargs
['subnetpool_id']
279 params
['cidr'] = kwargs
['cidr']
281 if 'gateway_ip' in kwargs
:
282 params
['gateway_ip'] = kwargs
['gateway_ip']
284 params
['gateway_ip'] = None
286 if 'dhcp_params' in kwargs
:
287 params
['enable_dhcp'] = kwargs
['dhcp_params']['enable_dhcp']
288 if 'start_address' in kwargs
['dhcp_params'] and 'count' in kwargs
['dhcp_params']:
289 end_address
= (ipaddress
.IPv4Address(kwargs
['dhcp_params']['start_address']) + kwargs
['dhcp_params']['count']).compressed
290 params
['allocation_pools'] = [ {'start': kwargs
['dhcp_params']['start_address'] ,
291 'end' : end_address
} ]
293 if 'dns_server' in kwargs
:
294 params
['dns_nameservers'] = []
295 for server
in kwargs
['dns_server']:
296 params
['dns_nameservers'].append(server
)
299 subnet
= self
._nt
_drv
.create_subnet({'subnets': [params
]})
300 except Exception as e
:
301 self
.log
.exception("Create Subnet operation failed. Exception: %s",str(e
))
304 return subnet
['subnets'][0]['id']
306 def subnet_list(self
, **kwargs
):
308 Returns a list of dictionaries. Each dictionary contains attributes describing the subnet
313 A dictionary of the objects of subnet attributes
316 subnets
= self
._nt
_drv
.list_subnets(**kwargs
)['subnets']
317 except Exception as e
:
318 self
.log
.exception("List Subnet operation failed. Exception: %s", str(e
))
322 def _subnet_get(self
, subnet_id
):
324 Returns a dictionary object describing the attributes of a subnet.
327 subnet_id (string): UUID of the subnet
330 A dictionary object of the subnet attributes
332 subnets
= self
._nt
_drv
.list_subnets(id=subnet_id
)
333 if not subnets
['subnets']:
334 self
.log
.error("Get subnet operation failed for subnet_id: %s", subnet_id
)
335 #raise NeutronException.NotFound("Could not find subnet_id %s" %(subnet_id))
338 return subnets
['subnets'][0]
340 def subnet_get(self
, subnet_id
):
342 Returns a dictionary object describing the attributes of a subnet.
345 subnet_id (string): UUID of the subnet
348 A dictionary object of the subnet attributes
350 return self
._subnet
_get
(subnet_id
)
352 def subnet_delete(self
, subnet_id
):
354 Deletes a subnet identified by subnet_id
357 subnet_id (string): UUID of the subnet to be deleted
361 assert subnet_id
== self
._subnet
_get
(self
,subnet_id
)
363 self
._nt
_drv
.delete_subnet(subnet_id
)
364 except Exception as e
:
365 self
.log
.exception("Delete Subnet operation failed for subnet_id : %s. Exception: %s", subnet_id
, str(e
))
368 def port_list(self
, **kwargs
):
370 Returns a list of dictionaries. Each dictionary contains attributes describing the port
373 kwargs (dictionary): A dictionary for filters for port_list operation
376 A dictionary of the objects of port attributes
381 kwargs
['tenant_id'] = self
.project_id
384 ports
= self
._nt
_drv
.list_ports(**kwargs
)
385 except Exception as e
:
386 self
.log
.exception("List Port operation failed. Exception: %s",str(e
))
388 return ports
['ports']
390 def port_create(self
, ports
):
392 Create a port in network
396 List of dictionaries of following
398 name (string) : Name of the port
399 network_id(string) : UUID of the network_id identifying the network to which port belongs
400 ip_address(string) : (Optional) Static IP address to assign to the port
401 vnic_type(string) : Possible values are "normal", "direct", "macvtap"
402 admin_state_up : True/False
403 port_security_enabled : True/False
404 security_groups : A List of Neutron security group Ids
407 A list of port_id (string)
410 params
['ports'] = ports
411 self
.log
.debug("Port create params: {}".format(params
))
413 ports
= self
._nt
_drv
.create_port(params
)
414 except Exception as e
:
415 self
.log
.exception("Ports Create operation failed. Exception: %s",str(e
))
417 return [ p
['id'] for p
in ports
['ports'] ]
420 def port_update(self
, port_id
, no_security_groups
=None,port_security_enabled
=None):
422 Update a port in network
426 if no_security_groups
:
427 params
["port"]["security_groups"] = []
428 if port_security_enabled
== False:
429 params
["port"]["port_security_enabled"] = False
430 elif port_security_enabled
== True:
431 params
["port"]["port_security_enabled"] = True
434 port
= self
._nt
_drv
.update_port(port_id
,params
)
435 except Exception as e
:
436 self
.log
.exception("Port Update operation failed. Exception: %s", str(e
))
438 return port
['port']['id']
440 def _port_get(self
, port_id
):
442 Returns a dictionary object describing the attributes of the port
445 port_id (string): UUID of the port
448 A dictionary object of the port attributes
450 port
= self
._nt
_drv
.list_ports(id=port_id
)['ports']
452 raise NeutronException
.NotFound("Could not find port_id %s" %(port_id))
455 def port_get(self
, port_id
):
457 Returns a dictionary object describing the attributes of the port
460 port_id (string): UUID of the port
463 A dictionary object of the port attributes
465 return self
._port
_get
(port_id
)
467 def port_delete(self
, port_id
):
469 Deletes a port identified by port_id
472 port_id (string) : UUID of the port
476 assert port_id
== self
._port
_get
(port_id
)['id']
478 self
._nt
_drv
.delete_port(port_id
)
479 except Exception as e
:
480 self
.log
.exception("Port Delete operation failed for port_id : %s. Exception: %s",port_id
, str(e
))
483 def security_group_list(self
, **kwargs
):
485 Returns a list of dictionaries. Each dictionary contains attributes describing the security group
491 A dictionary of the objects of security group attributes
494 kwargs
['tenant_id'] = self
.project_id
495 group_list
= self
._nt
_drv
.list_security_groups(**kwargs
)
496 except Exception as e
:
497 self
.log
.exception("List Security group operation, Exception: %s", str(e
))
499 return group_list
['security_groups']
502 def subnetpool_list(self
, **kwargs
):
504 Returns a list of dictionaries. Each dictionary contains attributes describing a subnet prefix pool
510 A dictionary of the objects of subnet prefix pool
513 pool_list
= self
._nt
_drv
.list_subnetpools(**kwargs
)
514 except Exception as e
:
515 self
.log
.exception("List SubnetPool operation, Exception: %s",str(e
))
518 if 'subnetpools' in pool_list
:
519 return pool_list
['subnetpools']