def test_list_pods_by_tenant(self): pod1, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ + FAKE_AZ, FAKE_TENANT_ID) pods = az_ag.list_pods_by_tenant(self.context, FAKE_TENANT_ID) self.assertEqual(pod1, None) self.assertEqual(len(pods), 0) # TODO(joehuang): tenant bound to multiple pods in one AZ # schedule one pod2, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ, FAKE_TENANT_ID) pods = az_ag.list_pods_by_tenant(self.context, FAKE_TENANT_ID) self.assertDictEqual(pods[0], pod2)
def test_get_pod_by_az_tenant(self): pod1, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ + FAKE_AZ, FAKE_TENANT_ID) self.assertIsNone(pod1) pods = az_ag.list_pods_by_tenant(self.context, FAKE_TENANT_ID) self.assertEqual(len(pods), 0) # schedule one pod2, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ, FAKE_TENANT_ID) pod_bindings = core.query_resource(self.context, models.PodBinding, [{'key': 'tenant_id', 'comparator': 'eq', 'value': FAKE_TENANT_ID}], []) self.assertIsNotNone(pod_bindings) if pod_bindings[0]['pod_id'] == FAKE_SITE_ID: self.assertEqual(pod2['pod_name'], FAKE_SITE_NAME) self.assertEqual(pod2['pod_id'], FAKE_SITE_ID) self.assertEqual(pod2['az_name'], FAKE_AZ) else: self.assertEqual(pod2['pod_name'], FAKE_SITE_NAME_2) self.assertEqual(pod2['pod_id'], FAKE_SITE_ID_2) self.assertEqual(pod2['az_name'], FAKE_AZ) # scheduled one should always be bound pod3, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ, FAKE_TENANT_ID) self.assertEqual(pod2['pod_name'], pod3['pod_name']) self.assertEqual(pod2['pod_id'], pod3['pod_id']) self.assertEqual(pod2['az_name'], pod3['az_name'])
def test_get_pod_by_az_tenant(self): pod1, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ + FAKE_AZ, FAKE_TENANT_ID) self.assertEqual(pod1, None) pods = az_ag.list_pods_by_tenant(self.context, FAKE_TENANT_ID) self.assertEqual(len(pods), 0) # schedule one pod2, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ, FAKE_TENANT_ID) pod_bindings = core.query_resource(self.context, models.PodBinding, [{'key': 'tenant_id', 'comparator': 'eq', 'value': FAKE_TENANT_ID}], []) self.assertIsNotNone(pod_bindings) if pod_bindings[0]['pod_id'] == FAKE_SITE_ID: self.assertEqual(pod2['pod_name'], FAKE_SITE_NAME) self.assertEqual(pod2['pod_id'], FAKE_SITE_ID) self.assertEqual(pod2['az_name'], FAKE_AZ) else: self.assertEqual(pod2['pod_name'], FAKE_SITE_NAME_2) self.assertEqual(pod2['pod_id'], FAKE_SITE_ID_2) self.assertEqual(pod2['az_name'], FAKE_AZ) # scheduled one should always be bound pod3, _ = az_ag.get_pod_by_az_tenant(self.context, FAKE_AZ, FAKE_TENANT_ID) self.assertEqual(pod2['pod_name'], pod3['pod_name']) self.assertEqual(pod2['pod_id'], pod3['pod_id']) self.assertEqual(pod2['az_name'], pod3['az_name'])
def post(self, **kw): context = t_context.extract_context_from_environ() if 'server' not in kw: pecan.abort(400, 'Request body not found') return if 'availability_zone' not in kw['server']: pecan.abort(400, 'Availability zone not set') return pod, b_az = az_ag.get_pod_by_az_tenant( context, kw['server']['availability_zone'], self.project_id) if not pod: pecan.abort(400, 'No pod bound to availability zone') return t_server_dict = kw['server'] self._process_metadata_quota(context, t_server_dict) self._process_injected_file_quota(context, t_server_dict) server_body = self._get_create_server_body(kw['server'], b_az) top_client = self._get_client() sg_filters = [{'key': 'tenant_id', 'comparator': 'eq', 'value': self.project_id}] top_sgs = top_client.list_security_groups(context, sg_filters) top_sg_map = dict((sg['name'], sg) for sg in top_sgs) if 'security_groups' not in kw['server']: security_groups = ['default'] else: security_groups = [] for sg in kw['server']['security_groups']: if 'name' not in sg: pecan.abort(404, 'Security group name not specified') return if sg['name'] not in top_sg_map: pecan.abort(404, 'Security group %s not found' % sg['name']) return security_groups.append(sg['name']) t_sg_ids, b_sg_ids, is_news = self._handle_security_group( context, pod, top_sg_map, security_groups) if 'networks' in kw['server']: server_body['networks'] = [] for net_info in kw['server']['networks']: if 'uuid' in net_info: network = top_client.get_networks(context, net_info['uuid']) if not network: pecan.abort(400, 'Network not found') return if not self._check_network_server_the_same_az( network, kw['server']['availability_zone']): pecan.abort(400, 'Network and server not in the same ' 'availability zone') return subnets = top_client.list_subnets( context, [{'key': 'network_id', 'comparator': 'eq', 'value': network['id']}]) if not subnets: pecan.abort(400, 'Network not contain subnets') return t_port_id, b_port_id = self._handle_network( context, pod, network, subnets, top_sg_ids=t_sg_ids, bottom_sg_ids=b_sg_ids) elif 'port' in net_info: port = top_client.get_ports(context, net_info['port']) if not port: pecan.abort(400, 'Port not found') return t_port_id, b_port_id = self._handle_port( context, pod, port) server_body['networks'].append({'port': b_port_id}) # only for security group first created in a pod, we invoke # _handle_sg_rule_for_new_group to initialize rules in that group, this # method removes all the rules in the new group then add new rules top_sg_id_map = dict((sg['id'], sg) for sg in top_sgs) new_top_sgs = [] new_bottom_sg_ids = [] default_sg = None for t_id, b_id, is_new in zip(t_sg_ids, b_sg_ids, is_news): sg_name = top_sg_id_map[t_id]['name'] if sg_name == 'default': default_sg = top_sg_id_map[t_id] continue if not is_new: continue new_top_sgs.append(top_sg_id_map[t_id]) new_bottom_sg_ids.append(b_id) self._handle_sg_rule_for_new_group(context, pod, new_top_sgs, new_bottom_sg_ids) if default_sg: self._handle_sg_rule_for_default_group( context, pod, default_sg, self.project_id) client = self._get_client(pod['pod_name']) nics = [ {'port-id': _port['port']} for _port in server_body['networks']] server = client.create_servers(context, name=server_body['name'], image=server_body['imageRef'], flavor=server_body['flavorRef'], nics=nics, security_groups=b_sg_ids) with context.session.begin(): core.create_resource(context, models.ResourceRouting, {'top_id': server['id'], 'bottom_id': server['id'], 'pod_id': pod['pod_id'], 'project_id': self.project_id, 'resource_type': constants.RT_SERVER}) pecan.response.status = 202 return {'server': server}
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): context = t_context.extract_context_from_environ() if 'server' not in kw: pecan.abort(400, 'Request body not found') return if 'availability_zone' not in kw['server']: pecan.abort(400, 'Availability zone not set') return pod, b_az = az_ag.get_pod_by_az_tenant( context, kw['server']['availability_zone'], self.project_id) if not pod: pecan.abort(400, 'No pod bound to availability zone') return server_body = self._get_create_server_body(kw['server'], b_az) top_client = self._get_client() if 'networks' in kw['server']: server_body['networks'] = [] for net_info in kw['server']['networks']: if 'uuid' in net_info: network = top_client.get_networks(context, net_info['uuid']) if not network: pecan.abort(400, 'Network not found') return subnets = top_client.list_subnets( context, [{'key': 'network_id', 'comparator': 'eq', 'value': network['id']}]) if not subnets: pecan.abort(400, 'Network not contain subnets') return bottom_port_id = self._handle_network(context, pod, network, subnets) elif 'port' in net_info: port = top_client.get_ports(context, net_info['port']) if not port: pecan.abort(400, 'Port not found') return bottom_port_id = self._handle_port(context, pod, port) server_body['networks'].append({'port': bottom_port_id}) client = self._get_client(pod['pod_name']) nics = [ {'port-id': _port['port']} for _port in server_body['networks']] server = client.create_servers(context, name=server_body['name'], image=server_body['imageRef'], flavor=server_body['flavorRef'], nics=nics) with context.session.begin(): core.create_resource(context, models.ResourceRouting, {'top_id': server['id'], 'bottom_id': server['id'], 'pod_id': pod['pod_id'], 'project_id': self.project_id, 'resource_type': constants.RT_SERVER}) return {'server': server}