def test_get_pod_service_ctx(self): pod_dict = { 'pod_id': 'fake_pod_id', 'pod_name': 'fake_pod_name', 'az_name': 'fake_az' } config_dict = { 'service_id': 'fake_service_id', 'pod_id': 'fake_pod_id', 'service_type': cons.ST_CINDER, 'service_url': 'http://127.0.0.1:8774/v2.1/$(tenant_id)s' } t_url = 'http://127.0.0.1:8774/v2/my_tenant_id/volumes' api.create_pod(self.context, pod_dict) api.create_pod_service_configuration(self.context, config_dict) b_url = 'http://127.0.0.1:8774/v2.1/my_tenant_id/volumes' b_endpoint = hclient.get_pod_service_endpoint(self.context, pod_dict['pod_name'], cons.ST_CINDER) self.assertEqual(b_endpoint, config_dict['service_url']) b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['pod_name'], cons.ST_CINDER) self.assertEqual(b_ctx['t_ver'], 'v2') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], 'v2.1') self.assertEqual(b_ctx['b_url'], b_url) # wrong pod name b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['pod_name'] + '1', cons.ST_CINDER) self.assertEqual(b_ctx['t_ver'], 'v2') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], '') self.assertEqual(b_ctx['b_url'], '') # wrong service_type b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['pod_name'], cons.ST_CINDER + '1') self.assertEqual(b_ctx['t_ver'], 'v2') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], '') self.assertEqual(b_ctx['b_url'], '')
def test_get_pod_service_ctx(self): pod_dict = { 'pod_id': 'fake_pod_id', 'region_name': 'fake_region_name', 'az_name': 'fake_az' } config_dict = { 'service_id': 'fake_service_id', 'pod_id': 'fake_pod_id', 'service_type': cons.ST_NEUTRON, 'service_url': 'http://127.0.0.1:9696/v2.0/networks' } t_url = 'http://127.0.0.1:9696/v2.0/networks' api.create_pod(self.context, pod_dict) api.create_cached_endpoints(self.context, config_dict) b_url = 'http://127.0.0.1:9696/v2.0/networks' b_endpoint = hclient.get_pod_service_endpoint(self.context, pod_dict['region_name'], cons.ST_NEUTRON) self.assertEqual(b_endpoint, config_dict['service_url']) b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['region_name'], cons.ST_NEUTRON) self.assertEqual(b_ctx['t_ver'], 'v2.0') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], 'v2.0') self.assertEqual(b_ctx['b_url'], b_url) # wrong pod name b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['region_name'] + '1', cons.ST_NEUTRON) self.assertEqual(b_ctx['t_ver'], 'v2.0') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], '') self.assertEqual(b_ctx['b_url'], '') # wrong service_type b_ctx = hclient.get_pod_service_ctx(self.context, t_url, pod_dict['region_name'], cons.ST_NEUTRON + '1') self.assertEqual(b_ctx['t_ver'], 'v2.0') self.assertEqual(b_ctx['t_url'], t_url) self.assertEqual(b_ctx['b_ver'], '') self.assertEqual(b_ctx['b_url'], '')
def _get_all(self, context): # TODO(joehuang): query optimization for pagination, sort, etc ret = [] pods = az_ag.list_pods_by_tenant(context, self.tenant_id) for pod in pods: if pod['pod_name'] == '': continue query = urlparse.urlsplit(request.url).query query_filters = urlparse.parse_qsl(query) skip_pod = False for k, v in query_filters: if k == 'availability_zone' and v != pod['az_name']: skip_pod = True break if skip_pod: continue s_ctx = hclient.get_pod_service_ctx( context, request.url, pod['pod_name'], s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': LOG.error(_LE("bottom pod endpoint incorrect %s") % pod['pod_name']) continue # TODO(joehuang): convert header and body content resp = hclient.forward_req(context, 'GET', request.headers, s_ctx['b_url'], request.body) if resp.status_code == 200: routings = db_api.get_bottom_mappings_by_tenant_pod( context, self.tenant_id, pod['pod_id'], cons.RT_VOLUME ) b_ret_body = jsonutils.loads(resp.content) if b_ret_body.get('volumes'): for vol in b_ret_body['volumes']: if not routings.get(vol['id']): b_ret_body['volumes'].remove(vol) continue vol['availability_zone'] = pod['az_name'] ret.extend(b_ret_body['volumes']) return ret
def _get_all(self, context): # TODO(joehuang): query optimization for pagination, sort, etc ret = [] pods = az_ag.list_pods_by_tenant(context, self.tenant_id) for pod in pods: if pod['pod_name'] == '': continue query = urlparse.urlsplit(request.url).query query_filters = urlparse.parse_qsl(query) skip_pod = False for k, v in query_filters: if k == 'availability_zone' and v != pod['az_name']: skip_pod = True break if skip_pod: continue s_ctx = hclient.get_pod_service_ctx(context, request.url, pod['pod_name'], s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': LOG.error( _LE("bottom pod endpoint incorrect %s") % pod['pod_name']) continue # 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) resp = hclient.forward_req(context, 'GET', b_headers, s_ctx['b_url'], request.body) if resp.status_code == 200: routings = db_api.get_bottom_mappings_by_tenant_pod( context, self.tenant_id, pod['pod_id'], cons.RT_VOLUME) b_ret_body = jsonutils.loads(resp.content) if b_ret_body.get('volumes'): for vol in b_ret_body['volumes']: if not routings.get(vol['id']): b_ret_body['volumes'].remove(vol) continue vol['availability_zone'] = pod['az_name'] ret.extend(b_ret_body['volumes']) return ret
def _get_res_routing_ref(self, context, _id, t_url): pod = self._get_pod_by_top_id(context, _id) if not pod: return None pod_name = pod['pod_name'] s_ctx = hclient.get_pod_service_ctx(context, t_url, pod_name, s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': LOG.error(_LE("bottom pod endpoint incorrect %s") % pod_name) return s_ctx
def _get_res_routing_ref(self, context, _id, t_url): pod = self._get_pod_by_top_id(context, _id) if not pod: return None pod_name = pod['pod_name'] s_ctx = hclient.get_pod_service_ctx( context, t_url, pod_name, s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': LOG.error(_LE("bottom pod endpoint incorrect %s") % pod_name) return s_ctx
def post(self, **kw): context = t_context.extract_context_from_environ() if 'volume' not in kw: pecan.abort(400, _('Volume not found in request body')) return if 'availability_zone' not in kw['volume']: pecan.abort(400, _('Availability zone not set in request')) return pod, pod_az = az_ag.get_pod_by_az_tenant( context, az_name=kw['volume']['availability_zone'], tenant_id=self.tenant_id) if not pod: pecan.abort(500, _('Pod not configured or scheduling failure')) LOG.error(_LE("Pod not configured or scheduling failure")) return t_pod = db_api.get_top_pod(context) if not t_pod: pecan.abort(500, _('Top Pod not configured')) LOG.error(_LE("Top Pod not configured")) return # TODO(joehuang): get release from pod configuration, # to convert the content # b_release = pod['release'] # t_release = t_pod['release'] t_release = cons.R_MITAKA b_release = cons.R_MITAKA s_ctx = hclient.get_pod_service_ctx(context, request.url, pod['pod_name'], s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': pecan.abort(500, _('bottom pod endpoint incorrect')) LOG.error( _LE("bottom pod endpoint incorrect %s") % pod['pod_name']) return 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) # convert az to the configured one # remove the AZ parameter to bottom request for default one b_vol_req['availability_zone'] = pod['pod_az_name'] if b_vol_req['availability_zone'] == '': b_vol_req.pop("availability_zone", None) b_body = jsonutils.dumps({'volume': b_vol_req}) resp = hclient.forward_req(context, 'POST', b_headers, s_ctx['b_url'], b_body) b_status = resp.status_code b_ret_body = jsonutils.loads(resp.content) # build routing and convert response from the bottom pod # for different version. response.status = b_status if b_status == 202: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] try: with context.session.begin(): core.create_resource( context, models.ResourceRouting, { 'top_id': b_vol_ret['id'], 'bottom_id': b_vol_ret['id'], 'pod_id': pod['pod_id'], 'project_id': self.tenant_id, 'resource_type': cons.RT_VOLUME }) except Exception as e: LOG.exception( _LE('Failed to create volume ' 'resource routing' 'top_id: %(top_id)s ,' 'bottom_id: %(bottom_id)s ,' 'pod_id: %(pod_id)s ,' '%(exception)s '), { 'top_id': b_vol_ret['id'], 'bottom_id': b_vol_ret['id'], 'pod_id': pod['pod_id'], 'exception': e }) return Response( _('Failed to create volume ' 'resource routing'), 500) ret_vol = self._convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} return {'error': b_ret_body}
def post(self, **kw): context = t_context.extract_context_from_environ() if 'volume' not in kw: pecan.abort(400, _('Volume not found in request body')) return if 'availability_zone' not in kw['volume']: pecan.abort(400, _('Availability zone not set in request')) return pod, pod_az = az_ag.get_pod_by_az_tenant( context, az_name=kw['volume']['availability_zone'], tenant_id=self.tenant_id) if not pod: pecan.abort(500, _('Pod not configured or scheduling failure')) LOG.error(_LE("Pod not configured or scheduling failure")) return t_pod = db_api.get_top_pod(context) if not t_pod: pecan.abort(500, _('Top Pod not configured')) LOG.error(_LE("Top Po not configured")) return # TODO(joehuang): get release from pod configuration, # to convert the content # b_release = pod['release'] # t_release = t_pod['release'] t_release = 'Mitaka' b_release = 'Mitaka' s_ctx = hclient.get_pod_service_ctx( context, request.url, pod['pod_name'], s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': pecan.abort(500, _('bottom pod endpoint incorrect')) LOG.error(_LE("bottom pod endpoint incorrect %s") % pod['pod_name']) return 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) # convert az to the configured one # remove the AZ parameter to bottom request for default one b_vol_req['availability_zone'] = pod['pod_az_name'] if b_vol_req['availability_zone'] == '': b_vol_req.pop("availability_zone", None) b_body = jsonutils.dumps({'volume': b_vol_req}) resp = hclient.forward_req( context, 'POST', b_headers, s_ctx['b_url'], b_body) b_status = resp.status_code b_ret_body = jsonutils.loads(resp.content) # build routing and convert response from the bottom pod # for different version. response.status = b_status if b_status == 202: if b_ret_body.get('volume') is not None: b_vol_ret = b_ret_body['volume'] try: with context.session.begin(): core.create_resource( context, models.ResourceRouting, {'top_id': b_vol_ret['id'], 'bottom_id': b_vol_ret['id'], 'pod_id': pod['pod_id'], 'project_id': self.tenant_id, 'resource_type': cons.RT_VOLUME}) except Exception as e: LOG.error(_LE('Fail to create volume: %(exception)s'), {'exception': e}) return Response(_('Failed to create volume'), 500) ret_vol = self._convert_object(b_release, t_release, b_vol_ret, res_type=cons.RT_VOLUME) ret_vol['availability_zone'] = pod['az_name'] return {'volume': ret_vol} return {'error': b_ret_body}
def post(self, **kw): """Create volume metadata associated with a volume. :param kw: dictionary of values to be created :returns: created volume metadata """ context = t_context.extract_context_from_environ() if 'metadata' not in kw: return utils.format_cinder_error( 400, _("Missing required element 'metadata' in " "request body.")) try: pod = utils.get_pod_by_top_id(context, self.volume_id) if pod is None: return utils.format_cinder_error( 404, _('Volume %(volume_id)s could not be found.') % {'volume_id': self.volume_id}) t_pod = db_api.get_top_pod(context) if not t_pod: LOG.error(_LE("Top Pod not configured")) return utils.format_cinder_error(500, _('Top Pod not configured')) except Exception as e: LOG.exception( _LE('Fail to create metadata for a volume:' '%(volume_id)s' '%(exception)s'), { 'volume_id': self.volume_id, 'exception': e }) return utils.format_cinder_error(500, _('Fail to create metadata')) t_release = cons.R_MITAKA b_release = cons.R_MITAKA s_ctx = hclient.get_pod_service_ctx(context, request.url, pod['pod_name'], s_type=cons.ST_CINDER) if s_ctx['b_url'] == '': LOG.error( _LE("Bottom pod endpoint incorrect %s") % pod['pod_name']) return utils.format_cinder_error( 500, _('Bottom pod endpoint incorrect')) b_headers = hclient.convert_header(t_release, b_release, request.headers) t_metadata = kw['metadata'] # add or remove key-value in the request for diff. version b_vol_req = hclient.convert_object(t_release, b_release, t_metadata, res_type=cons.RT_VOl_METADATA) b_body = jsonutils.dumps({'metadata': b_vol_req}) resp = hclient.forward_req(context, 'POST', b_headers, s_ctx['b_url'], b_body) b_status = resp.status_code b_body_ret = jsonutils.loads(resp.content) # convert response from the bottom pod # for different version. response.status = b_status if b_status == 200: if b_body_ret.get('metadata') is not None: b_metadata_ret = b_body_ret['metadata'] vol_ret = hclient.convert_object(b_release, t_release, b_metadata_ret, res_type=cons.RT_VOl_METADATA) return {'metadata': vol_ret} return b_body_ret