1 # Copyright (c) 2017 Cable Television Laboratories, Inc. ("CableLabs")
2 # and others. All rights reserved.
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at:
8 # http://www.apache.org/licenses/LICENSE-2.0
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
19 from neutronclient.common.exceptions import NotFound, Unauthorized
21 from snaps.config.router import RouterConfig
22 from snaps.openstack.openstack_creator import OpenStackNetworkObject
23 from snaps.openstack.utils import neutron_utils
25 __author__ = 'spisarski'
27 logger = logging.getLogger('OpenStackNetwork')
30 class OpenStackRouter(OpenStackNetworkObject):
32 Class responsible for managing a router in OpenStack
35 def __init__(self, os_creds, router_settings):
37 Constructor - all parameters are required
38 :param os_creds: The credentials to connect with OpenStack
39 :param router_settings: The settings used to create a router object
40 (must be an instance of the RouterConfig
43 super(self.__class__, self).__init__(os_creds)
45 if not router_settings:
46 raise RouterCreationError('router_settings is required')
48 self.router_settings = router_settings
50 # Attributes instantiated on create()
52 self.__internal_subnets = list()
53 self.__internal_router_interface = None
55 # Dict where the port object is the key and any newly created router
56 # interfaces are the value
61 Loads the existing router.
62 :return: the Router domain object
64 super(self.__class__, self).initialize()
67 self.__router = neutron_utils.get_router(
68 self._neutron, self._keystone,
69 router_settings=self.router_settings,
70 project_name=self._os_creds.project_name)
71 except Unauthorized as e:
72 logger.warn('Unable to lookup router with name %s - %s',
73 self.router_settings.name, e)
76 for sub_config in self.router_settings.internal_subnets:
77 internal_subnet = self.__get_internal_subnet(sub_config)
79 self.__internal_subnets.append(internal_subnet)
81 raise RouterCreationError(
82 'Subnet not found with name ' + internal_subnet.name)
84 for port_setting in self.router_settings.port_settings:
85 port = neutron_utils.get_port(
86 self._neutron, self._keystone, port_settings=port_setting,
87 project_name=self._os_creds.project_name)
89 self.__ports.append(port)
95 Responsible for creating the router.
96 :return: the Router domain object
100 if not self.__router:
101 self.__router = neutron_utils.create_router(
102 self._neutron, self._os_creds, self.router_settings)
104 for sub_config in self.router_settings.internal_subnets:
105 internal_subnet = self.__get_internal_subnet(sub_config)
107 self.__internal_subnets.append(internal_subnet)
109 logger.debug('Adding router to subnet...')
110 router_intf = neutron_utils.add_interface_router(
111 self._neutron, self.__router,
112 subnet=internal_subnet)
113 self.__internal_router_interface = router_intf
115 raise RouterCreationError(
116 'Subnet not found with name ' + internal_subnet.name)
118 for port_setting in self.router_settings.port_settings:
119 port = neutron_utils.get_port(
120 self._neutron, self._keystone, port_settings=port_setting,
121 project_name=self._os_creds.project_name)
123 'Retrieved port %s for router - %s', port_setting.name,
124 self.router_settings.name)
126 self.__ports.append(port)
129 port = neutron_utils.create_port(
130 self._neutron, self._os_creds, port_setting)
133 'Created port %s for router - %s',
135 self.router_settings.name)
136 self.__ports.append(port)
137 neutron_utils.add_interface_router(
138 self._neutron, self.__router, port=port)
140 raise RouterCreationError(
141 'Error creating port with name - '
144 self.__router = neutron_utils.get_router_by_id(
145 self._neutron, self.__router.id)
148 def __get_internal_subnet(self, sub_config):
150 returns the Subnet domain object from the subnet configurator
154 if isinstance(sub_config, six.text_type):
155 return neutron_utils.get_subnet_by_name(
156 self._neutron, self._keystone,
157 subnet_name=sub_config)
158 if isinstance(sub_config, dict):
159 sub_dict = sub_config['subnet']
160 network = neutron_utils.get_network(
161 self._neutron, self._keystone,
162 network_name=sub_dict['network_name'],
163 project_name=sub_dict['project_name'])
165 return neutron_utils.get_subnet(
166 self._neutron, network,
167 subnet_name=sub_dict['subnet_name'])
171 Removes and deletes all items created in reverse order.
173 for port in self.__ports:
175 'Removing router interface from router %s and port %s',
176 self.router_settings.name, port.name)
178 neutron_utils.remove_interface_router(self._neutron,
179 self.__router, port=port)
182 self.__ports = list()
184 for internal_subnet in self.__internal_subnets:
186 'Removing router interface from router %s and subnet %s',
187 self.router_settings.name, internal_subnet.name)
189 neutron_utils.remove_interface_router(self._neutron,
191 subnet=internal_subnet)
194 self.__internal_subnets = list()
197 logger.info('Removing router ' + self.router_settings.name)
199 neutron_utils.delete_router(self._neutron, self.__router)
204 super(self.__class__, self).clean()
206 def get_router(self):
208 Returns the OpenStack router object
213 def get_internal_router_interface(self):
215 Returns the OpenStack internal router interface object
218 return self.__internal_router_interface
221 class RouterCreationError(Exception):
223 Exception to be thrown when an router instance cannot be created
227 class RouterSettings(RouterConfig):
229 Class to hold the configuration settings required for creating OpenStack
234 def __init__(self, **kwargs):
235 from warnings import warn
236 warn('Use snaps.config.router.RouterConfig instead',
238 super(self.__class__, self).__init__(**kwargs)