X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=snaps%2Fopenstack%2Fcreate_router.py;h=260fc03f6463ccbc60da4ea630e3a64148350d31;hb=f65dbaef830fe7121173fdb83e5e4dde09b11a8a;hp=ef27fab4d24cc4bf9ec4b22a1888689e951bdc8a;hpb=c52637e0f7e3a11b9ce39aa28ab16ffa57ce5e3c;p=snaps.git diff --git a/snaps/openstack/create_router.py b/snaps/openstack/create_router.py index ef27fab..260fc03 100644 --- a/snaps/openstack/create_router.py +++ b/snaps/openstack/create_router.py @@ -14,18 +14,20 @@ # limitations under the License. import logging -from neutronclient.common.exceptions import NotFound -from snaps.openstack.create_network import PortSettings -from snaps.openstack.utils import neutron_utils, keystone_utils +from neutronclient.common.exceptions import NotFound, Unauthorized + +from snaps.config.router import RouterConfig +from snaps.openstack.openstack_creator import OpenStackNetworkObject +from snaps.openstack.utils import neutron_utils __author__ = 'spisarski' logger = logging.getLogger('OpenStackNetwork') -class OpenStackRouter: +class OpenStackRouter(OpenStackNetworkObject): """ - Class responsible for creating a router in OpenStack + Class responsible for managing a router in OpenStack """ def __init__(self, os_creds, router_settings): @@ -33,16 +35,15 @@ class OpenStackRouter: Constructor - all parameters are required :param os_creds: The credentials to connect with OpenStack :param router_settings: The settings used to create a router object - (must be an instance of the RouterSettings + (must be an instance of the RouterConfig class) """ - self.__os_creds = os_creds + super(self.__class__, self).__init__(os_creds) if not router_settings: raise RouterCreationError('router_settings is required') self.router_settings = router_settings - self.__neutron = None # Attributes instantiated on create() self.__router = None @@ -53,67 +54,116 @@ class OpenStackRouter: # interfaces are the value self.__ports = list() - def create(self, cleanup=False): + def initialize(self): """ - Responsible for creating the router. - :param cleanup: When true, only perform lookups for OpenStack objects. - :return: the router object + Loads the existing router. + :return: the Router domain object """ - self.__neutron = neutron_utils.neutron_client(self.__os_creds) - - logger.debug( - 'Creating Router with name - ' + self.router_settings.name) - existing = False - router_inst = neutron_utils.get_router( - self.__neutron, router_settings=self.router_settings) - if router_inst: - self.__router = router_inst - existing = True - else: - if not cleanup: - self.__router = neutron_utils.create_router( - self.__neutron, self.__os_creds, self.router_settings) - - for internal_subnet_name in self.router_settings.internal_subnets: - internal_subnet = neutron_utils.get_subnet( - self.__neutron, subnet_name=internal_subnet_name) - if internal_subnet: - self.__internal_subnets.append(internal_subnet) - if internal_subnet and not cleanup and not existing: - logger.debug('Adding router to subnet...') - router_intf = neutron_utils.add_interface_router( - self.__neutron, self.__router, subnet=internal_subnet) - self.__internal_router_interface = router_intf - else: - raise RouterCreationError( - 'Subnet not found with name ' + internal_subnet_name) - - for port_setting in self.router_settings.port_settings: - port = neutron_utils.get_port( - self.__neutron, port_settings=port_setting) - logger.info( - 'Retrieved port %s for router - %s', port_setting.name, - self.router_settings.name) - if port: - self.__ports.append(port) - - if not port and not cleanup and not existing: - port = neutron_utils.create_port(self.__neutron, - self.__os_creds, port_setting) + super(self.__class__, self).initialize() + + try: + self.__router = neutron_utils.get_router( + self._neutron, self._keystone, + router_settings=self.router_settings, + project_name=self._os_creds.project_name) + except Unauthorized as e: + logger.warn('Unable to lookup router with name %s - %s', + self.router_settings.name, e) + + if self.__router: + for sub_config in self.router_settings.internal_subnets: + internal_subnet = self.__get_internal_subnet(sub_config) + if internal_subnet: + self.__internal_subnets.append(internal_subnet) + else: + raise RouterCreationError( + 'Subnet not found with name ' + internal_subnet.name) + + for port_setting in self.router_settings.port_settings: + port = neutron_utils.get_port( + self._neutron, self._keystone, port_settings=port_setting, + project_name=self._os_creds.project_name) if port: - logger.info( - 'Created port %s for router - %s', port_setting.name, - self.router_settings.name) self.__ports.append(port) - neutron_utils.add_interface_router(self.__neutron, - self.__router, - port=port) + + return self.__router + + def create(self): + """ + Responsible for creating the router. + :return: the Router domain object + """ + self.initialize() + + if not self.__router: + self.__router = neutron_utils.create_router( + self._neutron, self._os_creds, self.router_settings) + + for sub_config in self.router_settings.internal_subnets: + internal_subnet = self.__get_internal_subnet(sub_config) + if internal_subnet: + self.__internal_subnets.append(internal_subnet) + if internal_subnet: + logger.debug('Adding router to subnet...') + router_intf = neutron_utils.add_interface_router( + self._neutron, self.__router, + subnet=internal_subnet) + self.__internal_router_interface = router_intf else: raise RouterCreationError( - 'Error creating port with name - ' + port_setting.name) + 'Subnet not found with name ' + internal_subnet.name) + + for port_setting in self.router_settings.port_settings: + port = neutron_utils.get_port( + self._neutron, self._keystone, port_settings=port_setting, + project_name=self._os_creds.project_name) + logger.info( + 'Retrieved port %s for router - %s', port_setting.name, + self.router_settings.name) + if port: + self.__ports.append(port) + if not port: + port = neutron_utils.create_port( + self._neutron, self._os_creds, port_setting) + if port: + logger.info( + 'Created port %s for router - %s', + port_setting.name, + self.router_settings.name) + self.__ports.append(port) + neutron_utils.add_interface_router( + self._neutron, self.__router, port=port) + else: + raise RouterCreationError( + 'Error creating port with name - ' + + port_setting.name) + + self.__router = neutron_utils.get_router_by_id( + self._neutron, self.__router.id) return self.__router + def __get_internal_subnet(self, sub_config): + """ + returns the Subnet domain object from the subnet configurator + :param sub_config: + :return: + """ + if isinstance(sub_config, str): + return neutron_utils.get_subnet_by_name( + self._neutron, self._keystone, + subnet_name=sub_config) + if isinstance(sub_config, dict): + sub_dict = sub_config['subnet'] + network = neutron_utils.get_network( + self._neutron, self._keystone, + network_name=sub_dict['network_name'], + project_name=sub_dict['project_name']) + if network: + return neutron_utils.get_subnet( + self._neutron, network, + subnet_name=sub_dict['subnet_name']) + def clean(self): """ Removes and deletes all items created in reverse order. @@ -123,7 +173,7 @@ class OpenStackRouter: 'Removing router interface from router %s and port %s', self.router_settings.name, port.name) try: - neutron_utils.remove_interface_router(self.__neutron, + neutron_utils.remove_interface_router(self._neutron, self.__router, port=port) except NotFound: pass @@ -134,7 +184,7 @@ class OpenStackRouter: 'Removing router interface from router %s and subnet %s', self.router_settings.name, internal_subnet.name) try: - neutron_utils.remove_interface_router(self.__neutron, + neutron_utils.remove_interface_router(self._neutron, self.__router, subnet=internal_subnet) except NotFound: @@ -144,11 +194,13 @@ class OpenStackRouter: if self.__router: logger.info('Removing router ' + self.router_settings.name) try: - neutron_utils.delete_router(self.__neutron, self.__router) + neutron_utils.delete_router(self._neutron, self.__router) except NotFound: pass self.__router = None + super(self.__class__, self).clean() + def get_router(self): """ Returns the OpenStack router object @@ -170,101 +222,15 @@ class RouterCreationError(Exception): """ -class RouterSettings: +class RouterSettings(RouterConfig): """ - Class representing a router configuration + Class to hold the configuration settings required for creating OpenStack + router objects + deprecated """ def __init__(self, **kwargs): - """ - Constructor - all parameters are optional - :param name: The router name. - :param project_name: The name of the project who owns the network. Only - administrative users can specify a project ID - other than their own. You cannot change this value - through authorization policies. - :param external_gateway: Name of the external network to which to route - :param admin_state_up: The administrative status of the router. - True = up / False = down (default True) - :param external_fixed_ips: Dictionary containing the IP address - parameters. - :param internal_subnets: List of subnet names to which to connect this - router for Floating IP purposes - :param port_settings: List of PortSettings objects - :return: - """ - self.name = kwargs.get('name') - self.project_name = kwargs.get('project_name') - self.external_gateway = kwargs.get('external_gateway') - - self.admin_state_up = kwargs.get('admin_state_up') - self.enable_snat = kwargs.get('enable_snat') - self.external_fixed_ips = kwargs.get('external_fixed_ips') - if kwargs.get('internal_subnets'): - self.internal_subnets = kwargs['internal_subnets'] - else: - self.internal_subnets = list() - - self.port_settings = list() - if kwargs.get('interfaces', kwargs.get('port_settings')): - interfaces = kwargs.get('interfaces', kwargs.get('port_settings')) - for interface in interfaces: - if isinstance(interface, PortSettings): - self.port_settings.append(interface) - else: - self.port_settings.append( - PortSettings(**interface['port'])) - - if not self.name: - raise RouterSettingsError('Name is required') - - def dict_for_neutron(self, neutron, os_creds): - """ - Returns a dictionary object representing this object. - This is meant to be converted into JSON designed for use by the Neutron - API - - TODO - expand automated testing to exercise all parameters - :param neutron: The neutron client to retrieve external network - information if necessary - :param os_creds: The OpenStack credentials - :return: the dictionary object - """ - out = dict() - ext_gw = dict() - - if self.name: - out['name'] = self.name - if self.project_name: - keystone = keystone_utils.keystone_client(os_creds) - project = keystone_utils.get_project( - keystone=keystone, project_name=self.project_name) - project_id = None - if project: - project_id = project.id - if project_id: - out['tenant_id'] = project_id - else: - raise RouterSettingsError( - 'Could not find project ID for project named - ' + - self.project_name) - if self.admin_state_up is not None: - out['admin_state_up'] = self.admin_state_up - if self.external_gateway: - ext_net = neutron_utils.get_network( - neutron, network_name=self.external_gateway) - if ext_net: - ext_gw['network_id'] = ext_net.id - out['external_gateway_info'] = ext_gw - else: - raise RouterSettingsError( - 'Could not find the external network named - ' + - self.external_gateway) - - return {'router': out} - - -class RouterSettingsError(Exception): - """ - Exception to be thrown when router settings attributes are incorrect - """ + from warnings import warn + warn('Use snaps.config.router.RouterConfig instead', + DeprecationWarning) + super(self.__class__, self).__init__(**kwargs)