def delete_ag(context, aggregate_id): core.delete_resources(context, models.AggregateMetadata, [{'key': 'aggregate_id', 'comparator': 'eq', 'value': aggregate_id}]) core.delete_resource(context, models.Aggregate, aggregate_id) return
def get_one(self, _id): context = t_context.extract_context_from_environ() if _id == 'detail': return {'volumes': self._get_all(context)} # TODO(joehuang): get the release of top and bottom t_release = cons.R_MITAKA b_release = cons.R_MITAKA b_headers = hclient.convert_header(t_release, b_release, request.headers) s_ctx = hclient.get_res_routing_ref(context, _id, request.url, cons.ST_CINDER) if not s_ctx: return utils.format_cinder_error( 404, _('Volume %s could not be found.') % _id) if s_ctx['b_url'] == '': return utils.format_cinder_error( 404, _('Bottom Pod endpoint incorrect')) resp = hclient.forward_req(context, 'GET', b_headers, s_ctx['b_url'], request.body) b_ret_body = jsonutils.loads(resp.content) b_status = resp.status_code response.status = b_status if b_status == 200: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] ret_vol = hclient.convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) pod = utils.get_pod_by_top_id(context, _id) if pod: ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} # resource not find but routing exist, remove the routing if b_status == 404: filters = [{ 'key': 'top_id', 'comparator': 'eq', 'value': _id }, { 'key': 'resource_type', 'comparator': 'eq', 'value': cons.RT_VOLUME }] with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters) return b_ret_body
def delete_mappings_by_bottom_id(context, bottom_id): with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters=[{ 'key': 'bottom_id', 'comparator': 'eq', 'value': bottom_id }])
def delete_ag(context, aggregate_id): core.delete_resources(context, models.AggregateMetadata, [{ 'key': 'aggregate_id', 'comparator': 'eq', 'value': aggregate_id }]) core.delete_resource(context, models.Aggregate, aggregate_id) return
def _remove_stale_mapping(context, server_id): filters = [{'key': 'top_id', 'comparator': 'eq', 'value': server_id}, {'key': 'resource_type', 'comparator': 'eq', 'value': constants.RT_SERVER}] with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters)
def remove_router_interface(self): context = t_context.extract_context_from_environ() body = {"core_router_interface": request.context['request_data']} attr_info = body_validation.RESOURCE_ATTRIBUTE_MAP.get(self.resource) body_validation.BodyValidationHook.check_request_body( body, True, "core_router_interface", attr_info) fabric = request.context['request_data']['fabric'] try: with context.session.begin(): core.get_resource(context, models.CoreRouter, self.core_router_id) interface_filters = [{ 'key': 'core_router_id', 'comparator': 'eq', 'value': self.core_router_id }, { 'key': 'fabric', 'comparator': 'eq', 'value': fabric }] interfaces = core.query_resource(context, models.CoreRouterInterface, interface_filters, []) if (not len(interfaces) > 0): raise t_exceptions.CoreRouterInterfaceDeleteNotFound( core_router_id=self.core_router_id, fabric=fabric) core.delete_resources(context, models.CoreRouterInterface, interface_filters) return_object = m.SuccessMessage(result={}) return return_object.to_dict() except t_exceptions.ResourceNotFound as e: LOG.exception( 'Failed to delete core_router_interface : ' 'core_router_id %(core_router_id)s ,' '%(exception)s ', { 'core_router_id': self.core_router_id, 'exception': e }) return m.CoreRouterNotFound( core_router_id=self.core_router_id).to_dict() except t_exceptions.CoreRouterInterfaceDeleteNotFound: return m.CoreRouterInterfaceNotFound( core_router_id=self.core_router_id, fabric=fabric).to_dict() except Exception as e: LOG.exception( 'Failed to delete core_router_interface :' 'core_router_id: %(core_router_id)s,' 'fabric: %(fabric)s,' '%(exception)s ', { 'core_router_id': self.core_router_id, 'fabric': fabric, 'exception': e }) return_object = m.FailureMessage() return return_object.to_dict()
def get_one(self, _id): context = t_context.extract_context_from_environ() if _id == 'detail': return {'volumes': self._get_all(context)} # TODO(joehuang): get the release of top and bottom t_release = 'MITATA' b_release = 'MITATA' b_headers = self._convert_header(t_release, b_release, request.headers) s_ctx = self._get_res_routing_ref(context, _id, request.url) if not s_ctx: return Response(_('Failed to find resource'), 404) if s_ctx['b_url'] == '': return Response(_('bottom pod endpoint incorrect'), 404) resp = hclient.forward_req(context, 'GET', b_headers, s_ctx['b_url'], request.body) b_ret_body = jsonutils.loads(resp.content) b_status = resp.status_code response.status = b_status if b_status == 200: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] ret_vol = self._convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) pod = self._get_pod_by_top_id(context, _id) if pod: ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} # resource not find but routing exist, remove the routing if b_status == 404: filters = [{'key': 'top_id', 'comparator': 'eq', 'value': _id}, {'key': 'resource_type', 'comparator': 'eq', 'value': cons.RT_VOLUME}] with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters) return b_ret_body
def delete_pre_created_resource_mapping(context, name): with context.session.begin(): entries = core.query_resource( context, models.ResourceRouting, filters=[{'key': 'top_id', 'comparator': 'eq', 'value': name}], sorts=[]) if entries: core.delete_resources( context, models.ResourceRouting, filters=[{'key': 'top_id', 'comparator': 'eq', 'value': entries[0]['bottom_id']}]) core.delete_resource(context, models.ResourceRouting, entries[0]['id'])
def delete_mappings_by_top_id(context, top_id, pod_id=None): """Delete resource routing entry based on top resource ID If pod ID is also provided, only entry in the specific pod will be deleted :param context: context object :param top_id: top resource ID :param pod_id: optional pod ID :return: None """ filters = [{'key': 'top_id', 'comparator': 'eq', 'value': top_id}] if pod_id: filters.append({'key': 'pod_id', 'comparator': 'eq', 'value': pod_id}) with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters=filters)
def delete_security_group(self, context, sg_id): LOG.debug("lyman--enter delete security group") t_ctx = t_context.get_context_from_neutron_context(context) # check the sg whether in security group super(TricircleSecurityGroupMixin, self).\ get_security_group(context, sg_id) # check the sg whether in deleting dict_para = {'resource_id': sg_id, 'resource_type': t_constants.RT_SG} nt_utils.check_resource_not_in_deleting(context, dict_para) try: with t_ctx.session.begin(): core.create_resource(t_ctx, models.DeletingResources, dict_para) for pod, bottom_security_group_id in ( self.helper.get_real_shadow_resource_iterator( t_ctx, t_constants.RT_SG, sg_id)): self._get_client(pod['region_name']). \ delete_security_groups(t_ctx, bottom_security_group_id) with t_ctx.session.begin(): core.delete_resources(t_ctx, models.ResourceRouting, filters=[{ 'key': 'top_id', 'comparator': 'eq', 'value': sg_id }, { 'key': 'pod_id', 'comparator': 'eq', 'value': pod['pod_id'] }]) with t_ctx.session.begin(): super(TricircleSecurityGroupMixin, self). \ delete_security_group(context, sg_id) except Exception: raise finally: with t_ctx.session.begin(): core.delete_resources(t_ctx, models.DeletingResources, filters=[{ 'key': 'resource_id', 'comparator': 'eq', 'value': sg_id }])
def delete_security_group(self, context, sg_id): LOG.debug("lyman--enter delete security group") t_ctx = t_context.get_context_from_neutron_context(context) # check the sg whether in security group super(TricircleSecurityGroupMixin, self).\ get_security_group(context, sg_id) # check the sg whether in deleting dict_para = {'resource_id': sg_id, 'resource_type': t_constants.RT_SG} nt_utils.check_resource_not_in_deleting(context, dict_para) try: with t_ctx.session.begin(): core.create_resource( t_ctx, models.DeletingResources, dict_para) for pod, bottom_security_group_id in ( self.helper.get_real_shadow_resource_iterator( t_ctx, t_constants.RT_SG, sg_id)): self._get_client(pod['region_name']). \ delete_security_groups(t_ctx, bottom_security_group_id) with t_ctx.session.begin(): core.delete_resources( t_ctx, models.ResourceRouting, filters=[{'key': 'top_id', 'comparator': 'eq', 'value': sg_id}, {'key': 'pod_id', 'comparator': 'eq', 'value': pod['pod_id']}]) with t_ctx.session.begin(): super(TricircleSecurityGroupMixin, self). \ delete_security_group(context, sg_id) except Exception: raise finally: with t_ctx.session.begin(): core.delete_resources( t_ctx, models.DeletingResources, filters=[{ 'key': 'resource_id', 'comparator': 'eq', 'value': sg_id}])
def delete_mappings_by_bottom_id(context, bottom_id): with context.session.begin(): core.delete_resources( context, models.ResourceRouting, filters=[{'key': 'bottom_id', 'comparator': 'eq', 'value': bottom_id}])
def _update_core_router_routes(self, context, core_router_id, core_router): try: with context.session.begin(subtransactions=True): def _combine(ht): return "{}_{}".format(ht['destination'], ht['nexthop']) old_route_list = self._get_routes_by_core_router_id( context, core_router_id) new_route_set = set( [_combine(route) for route in core_router['routes']]) old_route_set = set( [_combine(route) for route in old_route_list]) new_routes = [] for route_str in old_route_set - new_route_set: for route in old_route_list: if _combine(route) == route_str: destination = self.filter_to_str( common_utils.AuthenticIPNetwork( route_str.partition("_")[0])) nexthop = self.filter_to_str( netaddr.IPAddress(route_str.partition("_")[2])) route_filters = [{ 'key': 'core_router_id', 'comparator': 'eq', 'value': core_router_id }, { 'key': 'destination', 'comparator': 'eq', 'value': destination }, { 'key': 'nexthop', 'comparator': 'eq', 'value': nexthop }] core.delete_resources(context, models.CoreRouterRoute, route_filters) for route_str in new_route_set - old_route_set: destination = self.filter_to_str( common_utils.AuthenticIPNetwork( route_str.partition("_")[0])) nexthop = self.filter_to_str( netaddr.IPAddress(route_str.partition("_")[2])) new_core_routerroute = core.create_resource( context, models.CoreRouterRoute, { 'core_router_id': core_router_id, 'destination': destination, 'nexthop': nexthop }) for route_str in new_route_set: new_routes.append({ 'destination': route_str.partition("_")[0], 'nexthop': route_str.partition("_")[2] }) del core_router["routes"] return new_routes except Exception as e: LOG.exception( 'Failed to update core_routerroute : ' 'core_router_id %(core_router_id)s: ' '%(exception)s', { 'core_router_id': core_router_id, 'exception': e }) raise t_exceptions.CoreRouterRoutesUpdateException()
def _setup_router_one_pod(self, ctx, t_pod, b_pod, t_client, t_net, t_router, t_bridge_net, t_bridge_subnet, is_ext_net_pod): # NOTE(zhiyuan) after the bridge network combination, external network # is attached to a separate router, which is created in central plugin, # so is_ext_net_pod is not used in the current implementation, but we # choose to keep this parameter since it's an important attribute of a # pod and we may need to use it later. b_client = self._get_client(b_pod['region_name']) is_distributed = t_router.get('distributed', False) router_body = {'router': {'name': t_router['id'], 'distributed': is_distributed}} project_id = t_router['tenant_id'] # create bottom router in target bottom pod _, b_router_id = self.helper.prepare_bottom_element( ctx, project_id, b_pod, t_router, constants.RT_ROUTER, router_body) # create top bridge port q_ctx = None # no need to pass neutron context when using client t_bridge_port_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_bridge_net['id'], b_router_id) # create bottom bridge port # if target bottom pod is hosting real external network, we create # another bottom router and attach the bridge network as internal # network, but this work is done by central plugin when user sets # router gateway. t_bridge_port = t_client.get_ports(ctx, t_bridge_port_id) (is_new, b_bridge_port_id, b_bridge_subnet_id, b_bridge_net_id) = self.helper.get_bottom_bridge_elements( ctx, project_id, b_pod, t_bridge_net, True, t_bridge_subnet, None) # we attach the bridge port as router gateway # add_gateway is update operation, which can run multiple times gateway_ip = t_bridge_port['fixed_ips'][0]['ip_address'] b_client.action_routers( ctx, 'add_gateway', b_router_id, {'network_id': b_bridge_net_id, 'enable_snat': False, 'external_fixed_ips': [{'subnet_id': b_bridge_subnet_id, 'ip_address': gateway_ip}]}) # attach internal port to bottom router t_ports = self._get_router_interfaces(t_client, ctx, t_router['id'], t_net['id']) b_net_id = db_api.get_bottom_id_by_top_id_region_name( ctx, t_net['id'], b_pod['region_name'], constants.RT_NETWORK) if b_net_id: b_ports = self._get_router_interfaces(b_client, ctx, b_router_id, b_net_id) else: b_ports = [] if not t_ports and b_ports: # remove redundant bottom interface b_port = b_ports[0] request_body = {'port_id': b_port['id']} b_client.action_routers(ctx, 'remove_interface', b_router_id, request_body) elif t_ports and not b_ports: # create new bottom interface t_port = t_ports[0] # only consider ipv4 address currently t_subnet_id = t_port['fixed_ips'][0]['subnet_id'] t_subnet = t_client.get_subnets(ctx, t_subnet_id) if CONF.enable_api_gateway: (b_net_id, subnet_map) = self.helper.prepare_bottom_network_subnets( ctx, q_ctx, project_id, b_pod, t_net, [t_subnet]) else: (b_net_id, subnet_map) = (t_net['id'], {t_subnet['id']: t_subnet['id']}) # the gateway ip of bottom subnet is set to the ip of t_port, so # we just attach the bottom subnet to the bottom router and neutron # server in the bottom pod will create the interface for us, using # the gateway ip. b_client.action_routers(ctx, 'add_interface', b_router_id, {'subnet_id': subnet_map[t_subnet_id]}) if not t_router['external_gateway_info']: return # handle floatingip t_ext_net_id = t_router['external_gateway_info']['network_id'] t_fips = t_client.list_floatingips(ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': t_ext_net_id}]) # skip unbound top floatingip t_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in t_fips if fip['port_id']]) mappings = db_api.get_bottom_mappings_by_top_id(ctx, t_ext_net_id, constants.RT_NETWORK) # bottom external network should exist b_ext_pod, b_ext_net_id = mappings[0] b_ext_client = self._get_client(b_ext_pod['region_name']) b_fips = b_ext_client.list_floatingips( ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': b_ext_net_id}]) b_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in b_fips]) add_fips = [ip for ip in t_ip_fip_map if ip not in b_ip_fip_map] del_fips = [ip for ip in b_ip_fip_map if ip not in t_ip_fip_map] for add_fip in add_fips: fip = t_ip_fip_map[add_fip] t_int_port_id = fip['port_id'] b_int_port_id = db_api.get_bottom_id_by_top_id_region_name( ctx, t_int_port_id, b_pod['region_name'], constants.RT_PORT) if not b_int_port_id: LOG.warning(_LW('Port %(port_id)s associated with floating ip ' '%(fip)s is not mapped to bottom pod'), {'port_id': t_int_port_id, 'fip': add_fip}) continue t_int_port = t_client.get_ports(ctx, t_int_port_id) if t_int_port['network_id'] != t_net['id']: # only handle floating ip association for the given top network continue if b_ext_pod['pod_id'] != b_pod['pod_id']: # if the internal port is not located in the external network # pod, we need to create a copied port in that pod for floating # ip association purpose t_int_net_id = t_int_port['network_id'] t_int_subnet_id = t_int_port['fixed_ips'][0]['subnet_id'] port_body = { 'port': { 'tenant_id': project_id, 'admin_state_up': True, 'name': constants.shadow_port_name % t_int_port['id'], 'network_id': t_int_net_id, 'fixed_ips': [{'ip_address': t_int_port[ 'fixed_ips'][0]['ip_address']}] } } self.helper.prepare_bottom_element( ctx, project_id, b_ext_pod, t_int_port, constants.RT_SD_PORT, port_body) # create routing entries for copied network and subnet so we # can easily find them during central network and subnet # deletion, create_resource_mapping will catch DBDuplicateEntry # exception and ignore it so it's safe to call this function # multiple times db_api.create_resource_mapping(ctx, t_int_net_id, t_int_net_id, b_ext_pod['pod_id'], project_id, constants.RT_SD_NETWORK) db_api.create_resource_mapping(ctx, t_int_subnet_id, t_int_subnet_id, b_ext_pod['pod_id'], project_id, constants.RT_SD_SUBNET) self._safe_create_bottom_floatingip( ctx, b_pod, b_ext_client, b_ext_net_id, add_fip, b_int_port_id) for del_fip in del_fips: fip = b_ip_fip_map[del_fip] if b_ext_pod['pod_id'] != b_pod['pod_id'] and fip['port_id']: # expire the routing entry for copy port with ctx.session.begin(): core.update_resources( ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': fip['port_id']}, {'key': 'resource_type', 'comparator': 'eq', 'value': constants.RT_SD_PORT}], {'bottom_id': None, 'created_at': constants.expire_time, 'updated_at': constants.expire_time}) # delete copy port b_ext_client.delete_ports(ctx, fip['port_id']) # delete the expired entry, even if this deletion fails, we # still have a chance that lock_handle module will delete it with ctx.session.begin(): core.delete_resources(ctx, models.ResourceRouting, [{'key': 'top_id', 'comparator': 'eq', 'value': fip['port_id']}, {'key': 'resource_type', 'comparator': 'eq', 'value': constants.RT_SD_PORT}]) # delete port before floating ip disassociation, copy # network and copy subnet are deleted during central # network and subnet deletion b_ext_client.delete_floatingips(ctx, fip['id'])
def put(self, _id, **kw): context = t_context.extract_context_from_environ() # TODO(joehuang): Implement API multi-version compatibility # currently _convert_header and _convert_object are both dummy # functions and API versions are hard coded. After multi-version # compatibility is implemented, API versions will be retrieved from # top and bottom API server, also, _convert_header and _convert_object # will do the real job to convert the request header and body # according to the API versions. t_release = cons.R_MITAKA b_release = cons.R_MITAKA s_ctx = self._get_res_routing_ref(context, _id, request.url) if not s_ctx: return Response(_('Resource not found'), 404) if s_ctx['b_url'] == '': return Response(_('Bottom pod endpoint incorrect'), 404) b_headers = self._convert_header(t_release, b_release, request.headers) t_vol = kw['volume'] # add or remove key-value in the request for diff. version b_vol_req = self._convert_object(t_release, b_release, t_vol, res_type=cons.RT_VOLUME) b_body = jsonutils.dumps({'volume': b_vol_req}) resp = hclient.forward_req(context, 'PUT', b_headers, s_ctx['b_url'], b_body) b_status = resp.status_code b_ret_body = jsonutils.loads(resp.content) response.status = b_status if b_status == 200: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] ret_vol = self._convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) pod = self._get_pod_by_top_id(context, _id) if pod: ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} # resource not found but routing exist, remove the routing if b_status == 404: filters = [{'key': 'top_id', 'comparator': 'eq', 'value': _id}, {'key': 'resource_type', 'comparator': 'eq', 'value': cons.RT_VOLUME}] with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters) return b_ret_body
def _setup_router_one_pod(self, ctx, t_pod, b_pod, t_client, t_net, t_router, t_ew_bridge_net, t_ew_bridge_subnet, need_ns_bridge): b_client = self._get_client(b_pod['pod_name']) router_body = {'router': {'name': t_router['id'], 'distributed': False}} project_id = t_router['tenant_id'] # create bottom router in target bottom pod _, b_router_id = self.helper.prepare_bottom_element( ctx, project_id, b_pod, t_router, 'router', router_body) # handle E-W networking # create top E-W bridge port q_ctx = None # no need to pass neutron context when using client t_ew_bridge_port_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ew_bridge_net['id'], b_router_id, None, True) # create bottom E-W bridge port t_ew_bridge_port = t_client.get_ports(ctx, t_ew_bridge_port_id) (is_new, b_ew_bridge_port_id, _, _) = self.helper.get_bottom_bridge_elements( ctx, project_id, b_pod, t_ew_bridge_net, False, t_ew_bridge_subnet, t_ew_bridge_port) # attach bottom E-W bridge port to bottom router if is_new: # only attach bridge port the first time b_client.action_routers(ctx, 'add_interface', b_router_id, {'port_id': b_ew_bridge_port_id}) else: # still need to check if the bridge port is bound port = b_client.get_ports(ctx, b_ew_bridge_port_id) if not port.get('device_id'): b_client.action_routers(ctx, 'add_interface', b_router_id, {'port_id': b_ew_bridge_port_id}) # handle N-S networking if need_ns_bridge: t_ns_bridge_net_name = constants.ns_bridge_net_name % project_id t_ns_bridge_subnet_name = constants.ns_bridge_subnet_name % ( project_id) t_ns_bridge_net = self._get_resource_by_name( t_client, ctx, 'network', t_ns_bridge_net_name) t_ns_bridge_subnet = self._get_resource_by_name( t_client, ctx, 'subnet', t_ns_bridge_subnet_name) # create bottom N-S bridge network and subnet (_, _, b_ns_bridge_subnet_id, b_ns_bridge_net_id) = self.helper.get_bottom_bridge_elements( ctx, project_id, b_pod, t_ns_bridge_net, True, t_ns_bridge_subnet, None) # create top N-S bridge gateway port t_ns_bridge_gateway_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ns_bridge_net['id'], b_router_id, None, False) t_ns_bridge_gateway = t_client.get_ports(ctx, t_ns_bridge_gateway_id) # add external gateway for bottom router # add gateway is update operation, can run multiple times gateway_ip = t_ns_bridge_gateway['fixed_ips'][0]['ip_address'] b_client.action_routers( ctx, 'add_gateway', b_router_id, {'network_id': b_ns_bridge_net_id, 'external_fixed_ips': [{'subnet_id': b_ns_bridge_subnet_id, 'ip_address': gateway_ip}]}) # attach internal port to bottom router t_ports = self._get_router_interfaces(t_client, ctx, t_router['id'], t_net['id']) b_net_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_net['id'], b_pod['pod_name'], constants.RT_NETWORK) if b_net_id: b_ports = self._get_router_interfaces(b_client, ctx, b_router_id, b_net_id) else: b_ports = [] if not t_ports and b_ports: # remove redundant bottom interface b_port = b_ports[0] request_body = {'port_id': b_port['id']} b_client.action_routers(ctx, 'remove_interface', b_router_id, request_body) elif t_ports and not b_ports: # create new bottom interface t_port = t_ports[0] # only consider ipv4 address currently t_subnet_id = t_port['fixed_ips'][0]['subnet_id'] t_subnet = t_client.get_subnets(ctx, t_subnet_id) (b_net_id, subnet_map) = self.helper.prepare_bottom_network_subnets( ctx, q_ctx, project_id, b_pod, t_net, [t_subnet]) # the gateway ip of bottom subnet is set to the ip of t_port, so # we just attach the bottom subnet to the bottom router and neutron # server in the bottom pod will create the interface for us, using # the gateway ip. b_client.action_routers(ctx, 'add_interface', b_router_id, {'subnet_id': subnet_map[t_subnet_id]}) if not t_router['external_gateway_info']: return # handle floatingip t_ext_net_id = t_router['external_gateway_info']['network_id'] t_fips = t_client.list_floatingips(ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': t_ext_net_id}]) # skip unbound top floatingip t_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in t_fips if fip['port_id']]) mappings = db_api.get_bottom_mappings_by_top_id(ctx, t_ext_net_id, constants.RT_NETWORK) # bottom external network should exist b_ext_pod, b_ext_net_id = mappings[0] b_ext_client = self._get_client(b_ext_pod['pod_name']) b_fips = b_ext_client.list_floatingips( ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': b_ext_net_id}]) # skip unbound bottom floatingip b_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in b_fips if fip['port_id']]) add_fips = [ip for ip in t_ip_fip_map if ip not in b_ip_fip_map] del_fips = [ip for ip in b_ip_fip_map if ip not in t_ip_fip_map] for add_fip in add_fips: fip = t_ip_fip_map[add_fip] t_int_port_id = fip['port_id'] b_int_port_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_int_port_id, b_pod['pod_name'], constants.RT_PORT) if not b_int_port_id: LOG.warning(_LW('Port %(port_id)s associated with floating ip ' '%(fip)s is not mapped to bottom pod'), {'port_id': t_int_port_id, 'fip': add_fip}) continue t_int_port = t_client.get_ports(ctx, t_int_port_id) if t_int_port['network_id'] != t_net['id']: # only handle floating ip association for the given top network continue if need_ns_bridge: # create top N-S bridge interface port t_ns_bridge_port_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ns_bridge_net['id'], None, b_int_port_id, False) t_ns_bridge_port = t_client.get_ports(ctx, t_ns_bridge_port_id) b_ext_bridge_net_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_ns_bridge_net['id'], b_ext_pod['pod_name'], constants.RT_NETWORK) port_body = { 'port': { 'tenant_id': project_id, 'admin_state_up': True, 'name': 'ns_bridge_port', 'network_id': b_ext_bridge_net_id, 'fixed_ips': [{'ip_address': t_ns_bridge_port[ 'fixed_ips'][0]['ip_address']}] } } _, b_ns_bridge_port_id = self.helper.prepare_bottom_element( ctx, project_id, b_ext_pod, t_ns_bridge_port, constants.RT_PORT, port_body) self._safe_create_bottom_floatingip( ctx, b_ext_pod, b_ext_client, b_ext_net_id, add_fip, b_ns_bridge_port_id) self._safe_create_bottom_floatingip( ctx, b_pod, b_client, b_ns_bridge_net_id, t_ns_bridge_port['fixed_ips'][0]['ip_address'], b_int_port_id) else: self._safe_create_bottom_floatingip( ctx, b_pod, b_client, b_ext_net_id, add_fip, b_int_port_id) for del_fip in del_fips: fip = b_ip_fip_map[del_fip] if need_ns_bridge: b_ns_bridge_port = b_ext_client.get_ports(ctx, fip['port_id']) entries = core.query_resource( ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': b_ns_bridge_port['id']}, {'key': 'pod_id', 'comparator': 'eq', 'value': b_ext_pod['pod_id']}], []) t_ns_bridge_port_id = entries[0]['top_id'] b_int_fips = b_client.list_floatingips( ctx, [{'key': 'floating_ip_address', 'comparator': 'eq', 'value': b_ns_bridge_port['fixed_ips'][0]['ip_address']}, {'key': 'floating_network_id', 'comparator': 'eq', 'value': b_ns_bridge_net_id}]) if b_int_fips: b_client.delete_floatingips(ctx, b_int_fips[0]['id']) b_ext_client.update_floatingips( ctx, fip['id'], {'floatingip': {'port_id': None}}) # for bridge port, we have two resource routing entries, one # for bridge port in top pod, another for bridge port in bottom # pod. calling t_client.delete_ports will delete bridge port in # bottom pod as well as routing entry for it, but we also need # to remove routing entry for bridge port in top pod, bridge # network will be deleted when deleting router # first we update the routing entry to set bottom_id to None # and expire the entry, so if we succeed to delete the bridge # port next, this expired entry will be deleted; otherwise, we # fail to delete the bridge port, when the port is accessed via # lock_handle module, that module will find the port and update # the entry with ctx.session.begin(): core.update_resources( ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': t_ns_bridge_port_id}], {'bottom_id': None, 'created_at': constants.expire_time, 'updated_at': constants.expire_time}) # delete bridge port t_client.delete_ports(ctx, t_ns_bridge_port_id) # delete the expired entry, even if this deletion fails, we # still have a chance that lock_handle module will delete it with ctx.session.begin(): core.delete_resources(ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': t_ns_bridge_port_id}]) else: b_client.update_floatingips(ctx, fip['id'], {'floatingip': {'port_id': None}})
def _update_route_entry_destination_cidrs(self, context, route_entry_id, route_entry): def _combine(ht): return "{}".format(ht['destination']) try: with context.session.begin(subtransactions=True): old_route_list = self._get_destination_cidrs_by_route_entry_id( context, route_entry_id) new_route_set = set([ _combine(route) for route in route_entry['destination_cidr_list'] ]) old_route_set = set( [_combine(route) for route in old_route_list]) new_routes = [] for route_str in old_route_set - new_route_set: for route in old_route_list: if _combine(route) == route_str: destination = self.filter_to_str( common_utils.AuthenticIPNetwork( route_str.partition("_")[0])) route_filters = [{ 'key': 'route_entry_id', 'comparator': 'eq', 'value': route_entry_id }, { 'key': 'destination', 'comparator': 'eq', 'value': destination }] core.delete_resources(context, models.DestinationCidr, route_filters) for route_str in new_route_set - old_route_set: destination = self.filter_to_str( common_utils.AuthenticIPNetwork( route_str.partition("_")[0])) new_core_routerroute = core.create_resource( context, models.DestinationCidr, { 'route_entry_id': route_entry_id, 'destination': destination }) for route_str in new_route_set: new_routes.append({'destination': route_str}) del route_entry["destination_cidr_list"] return new_routes except Exception as e: LOG.exception( 'Failed to update destination_cidr: ' 'route_entry_id %(route_entry_id)s: ' '%(exception)s', { 'route_entry_id': route_entry_id, 'exception': e }) raise t_exceptions.RouteEntryDestinationCidrsUpdateException()
def _setup_router_one_pod(self, ctx, t_pod, b_pod, t_client, t_net, t_router, t_ew_bridge_net, t_ew_bridge_subnet, need_ns_bridge): b_client = self._get_client(b_pod['pod_name']) router_body = {'router': {'name': t_router['id'], 'distributed': False}} project_id = t_router['tenant_id'] # create bottom router in target bottom pod _, b_router_id = self.helper.prepare_bottom_element( ctx, project_id, b_pod, t_router, 'router', router_body) # handle E-W networking # create top E-W bridge port q_ctx = None # no need to pass neutron context when using client t_ew_bridge_port_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ew_bridge_net['id'], b_router_id, None, True) # create bottom E-W bridge port t_ew_bridge_port = t_client.get_ports(ctx, t_ew_bridge_port_id) (is_new, b_ew_bridge_port_id, _, _) = self.helper.get_bottom_bridge_elements( ctx, project_id, b_pod, t_ew_bridge_net, False, t_ew_bridge_subnet, t_ew_bridge_port) # attach bottom E-W bridge port to bottom router if is_new: # only attach bridge port the first time b_client.action_routers(ctx, 'add_interface', b_router_id, {'port_id': b_ew_bridge_port_id}) else: # still need to check if the bridge port is bound port = b_client.get_ports(ctx, b_ew_bridge_port_id) if not port.get('device_id'): b_client.action_routers(ctx, 'add_interface', b_router_id, {'port_id': b_ew_bridge_port_id}) # handle N-S networking if need_ns_bridge: t_ns_bridge_net_name = constants.ns_bridge_net_name % project_id t_ns_bridge_subnet_name = constants.ns_bridge_subnet_name % ( project_id) t_ns_bridge_net = self._get_resource_by_name( t_client, ctx, 'network', t_ns_bridge_net_name) t_ns_bridge_subnet = self._get_resource_by_name( t_client, ctx, 'subnet', t_ns_bridge_subnet_name) # create bottom N-S bridge network and subnet (_, _, b_ns_bridge_subnet_id, b_ns_bridge_net_id) = self.helper.get_bottom_bridge_elements( ctx, project_id, b_pod, t_ns_bridge_net, True, t_ns_bridge_subnet, None) # create top N-S bridge gateway port t_ns_bridge_gateway_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ns_bridge_net['id'], b_router_id, None, False) t_ns_bridge_gateway = t_client.get_ports(ctx, t_ns_bridge_gateway_id) # add external gateway for bottom router # add gateway is update operation, can run multiple times gateway_ip = t_ns_bridge_gateway['fixed_ips'][0]['ip_address'] b_client.action_routers( ctx, 'add_gateway', b_router_id, {'network_id': b_ns_bridge_net_id, 'external_fixed_ips': [{'subnet_id': b_ns_bridge_subnet_id, 'ip_address': gateway_ip}]}) # attach internal port to bottom router t_ports = self._get_router_interfaces(t_client, ctx, t_router['id'], t_net['id']) b_net_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_net['id'], b_pod['pod_name'], constants.RT_NETWORK) if b_net_id: b_ports = self._get_router_interfaces(b_client, ctx, b_router_id, b_net_id) else: b_ports = [] if not t_ports and b_ports: # remove redundant bottom interface b_port = b_ports[0] request_body = {'port_id': b_port['id']} b_client.action_routers(ctx, 'remove_interface', b_router_id, request_body) elif t_ports and not b_ports: # create new bottom interface t_port = t_ports[0] # only consider ipv4 address currently t_subnet_id = t_port['fixed_ips'][0]['subnet_id'] t_subnet = t_client.get_subnets(ctx, t_subnet_id) if CONF.enable_api_gateway: (b_net_id, subnet_map) = self.helper.prepare_bottom_network_subnets( ctx, q_ctx, project_id, b_pod, t_net, [t_subnet]) else: (b_net_id, subnet_map) = (t_net['id'], {t_subnet['id']: t_subnet['id']}) # the gateway ip of bottom subnet is set to the ip of t_port, so # we just attach the bottom subnet to the bottom router and neutron # server in the bottom pod will create the interface for us, using # the gateway ip. b_client.action_routers(ctx, 'add_interface', b_router_id, {'subnet_id': subnet_map[t_subnet_id]}) if not t_router['external_gateway_info']: return # handle floatingip t_ext_net_id = t_router['external_gateway_info']['network_id'] t_fips = t_client.list_floatingips(ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': t_ext_net_id}]) # skip unbound top floatingip t_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in t_fips if fip['port_id']]) mappings = db_api.get_bottom_mappings_by_top_id(ctx, t_ext_net_id, constants.RT_NETWORK) # bottom external network should exist b_ext_pod, b_ext_net_id = mappings[0] b_ext_client = self._get_client(b_ext_pod['pod_name']) b_fips = b_ext_client.list_floatingips( ctx, [{'key': 'floating_network_id', 'comparator': 'eq', 'value': b_ext_net_id}]) b_ip_fip_map = dict([(fip['floating_ip_address'], fip) for fip in b_fips]) add_fips = [ip for ip in t_ip_fip_map if ip not in b_ip_fip_map] del_fips = [ip for ip in b_ip_fip_map if ip not in t_ip_fip_map] for add_fip in add_fips: fip = t_ip_fip_map[add_fip] t_int_port_id = fip['port_id'] b_int_port_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_int_port_id, b_pod['pod_name'], constants.RT_PORT) if not b_int_port_id: LOG.warning(_LW('Port %(port_id)s associated with floating ip ' '%(fip)s is not mapped to bottom pod'), {'port_id': t_int_port_id, 'fip': add_fip}) continue t_int_port = t_client.get_ports(ctx, t_int_port_id) if t_int_port['network_id'] != t_net['id']: # only handle floating ip association for the given top network continue if need_ns_bridge: # create top N-S bridge interface port t_ns_bridge_port_id = self.helper.get_bridge_interface( ctx, q_ctx, project_id, t_pod, t_ns_bridge_net['id'], None, b_int_port_id, False) t_ns_bridge_port = t_client.get_ports(ctx, t_ns_bridge_port_id) b_ext_bridge_net_id = db_api.get_bottom_id_by_top_id_pod_name( ctx, t_ns_bridge_net['id'], b_ext_pod['pod_name'], constants.RT_NETWORK) port_body = { 'port': { 'tenant_id': project_id, 'admin_state_up': True, 'name': 'ns_bridge_port', 'network_id': b_ext_bridge_net_id, 'fixed_ips': [{'ip_address': t_ns_bridge_port[ 'fixed_ips'][0]['ip_address']}] } } _, b_ns_bridge_port_id = self.helper.prepare_bottom_element( ctx, project_id, b_ext_pod, t_ns_bridge_port, constants.RT_PORT, port_body) # swap these two lines self._safe_create_bottom_floatingip( ctx, b_pod, b_client, b_ns_bridge_net_id, t_ns_bridge_port['fixed_ips'][0]['ip_address'], b_int_port_id) self._safe_create_bottom_floatingip( ctx, b_ext_pod, b_ext_client, b_ext_net_id, add_fip, b_ns_bridge_port_id) else: self._safe_create_bottom_floatingip( ctx, b_pod, b_client, b_ext_net_id, add_fip, b_int_port_id) for del_fip in del_fips: fip = b_ip_fip_map[del_fip] if not fip['port_id']: b_ext_client.delete_floatingips(ctx, fip['id']) continue if need_ns_bridge: b_ns_bridge_port = b_ext_client.get_ports(ctx, fip['port_id']) entries = core.query_resource( ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': b_ns_bridge_port['id']}, {'key': 'pod_id', 'comparator': 'eq', 'value': b_ext_pod['pod_id']}], []) t_ns_bridge_port_id = entries[0]['top_id'] b_int_fips = b_client.list_floatingips( ctx, [{'key': 'floating_ip_address', 'comparator': 'eq', 'value': b_ns_bridge_port['fixed_ips'][0]['ip_address']}, {'key': 'floating_network_id', 'comparator': 'eq', 'value': b_ns_bridge_net_id}]) if b_int_fips: b_client.delete_floatingips(ctx, b_int_fips[0]['id']) # for bridge port, we have two resource routing entries, one # for bridge port in top pod, another for bridge port in bottom # pod. calling t_client.delete_ports will delete bridge port in # bottom pod as well as routing entry for it, but we also need # to remove routing entry for bridge port in top pod, bridge # network will be deleted when deleting router # first we update the routing entry to set bottom_id to None # and expire the entry, so if we succeed to delete the bridge # port next, this expired entry will be deleted; otherwise, we # fail to delete the bridge port, when the port is accessed via # lock_handle module, that module will find the port and update # the entry with ctx.session.begin(): core.update_resources( ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': t_ns_bridge_port_id}], {'bottom_id': None, 'created_at': constants.expire_time, 'updated_at': constants.expire_time}) # delete bridge port t_client.delete_ports(ctx, t_ns_bridge_port_id) # delete the expired entry, even if this deletion fails, we # still have a chance that lock_handle module will delete it with ctx.session.begin(): core.delete_resources(ctx, models.ResourceRouting, [{'key': 'bottom_id', 'comparator': 'eq', 'value': t_ns_bridge_port_id}]) b_ext_client.delete_floatingips(ctx, fip['id'])
def put(self, _id, **kw): context = t_context.extract_context_from_environ() # TODO(joehuang): Implement API multi-version compatibility # currently _convert_header and _convert_object are both dummy # functions and API versions are hard coded. After multi-version # compatibility is implemented, API versions will be retrieved from # top and bottom API server, also, _convert_header and _convert_object # will do the real job to convert the request header and body # according to the API versions. t_release = cons.R_MITAKA b_release = cons.R_MITAKA s_ctx = self._get_res_routing_ref(context, _id, request.url) if not s_ctx: return Response(_('Resource not found'), 404) if s_ctx['b_url'] == '': return Response(_('Bottom pod endpoint incorrect'), 404) b_headers = self._convert_header(t_release, b_release, request.headers) t_vol = kw['volume'] # add or remove key-value in the request for diff. version b_vol_req = self._convert_object(t_release, b_release, t_vol, res_type=cons.RT_VOLUME) b_body = jsonutils.dumps({'volume': b_vol_req}) resp = hclient.forward_req(context, 'PUT', b_headers, s_ctx['b_url'], b_body) b_status = resp.status_code b_ret_body = jsonutils.loads(resp.content) response.status = b_status if b_status == 200: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] ret_vol = self._convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) pod = self._get_pod_by_top_id(context, _id) if pod: ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} # resource not found but routing exist, remove the routing if b_status == 404: filters = [{ 'key': 'top_id', 'comparator': 'eq', 'value': _id }, { 'key': 'resource_type', 'comparator': 'eq', 'value': cons.RT_VOLUME }] with context.session.begin(): core.delete_resources(context, models.ResourceRouting, filters) return b_ret_body