def rdir_fetch(ns): _check_ns(ns) volume = request.args.get('vol') if not volume: return flask.Response('Missing volume id', 400) pretty = request.args.get('pretty') decoded = flask.request.get_json(force=True) start_after = decoded.get('start_after') limit = decoded.get('limit') if limit is not None and limit <= 0: return flask.Response('limit must be greate than 0', 400) rebuild = decoded.get('rebuild', False) if not isinstance(rebuild, bool): return flask.Response('limit must be true or false', 400) data = get_backend().chunk_fetch(volume, start_after=start_after, limit=limit, rebuild=rebuild) if pretty: body = json.dumps(data, indent=4) else: body = json.dumps(data) return flask.Response(body, mimetype='application/json')
def on_rdir_status(self, req): volume = self._get_volume(req) pretty = req.args.get('pretty') data = self.backend.chunk_status(volume) if pretty: body = json.dumps(data, indent=4) else: body = json.dumps(data) return Response(body, mimetype='application/json')
def rdir_status(ns): _check_ns(ns) volume = request.args.get('vol') if not volume: return flask.Response('Missing volume id', 400) pretty = request.args.get('pretty') data = get_backend().chunk_status(volume) if pretty: body = json.dumps(data, indent=4) else: body = json.dumps(data) return flask.Response(body, mimetype='application/json')
def container_raw_delete(self, acct=None, ref=None, data=None, cid=None, **kwargs): uri = self._make_uri('container/raw_delete') params = self._make_params(acct, ref, cid=cid) data = json.dumps(data) resp, body = self._request( 'POST', uri, data=data, params=params)
def request(self, method, url, data=None, params=None, headers=None, json=None): # Add query string if params: out_param = [] for k, v in params.items(): if v is not None: if isinstance(v, unicode): v = unicode(v).encode('utf-8') out_param.append((k, v)) encoded_args = urlencode(out_param) url += '?' + encoded_args # Convert json and add Content-Type headers = headers if headers else {} if json: headers["Content-Type"] = "application/json" data = jsonlib.dumps(json) out_kwargs = {} out_kwargs['headers'] = headers out_kwargs['body'] = data return self.http_pool.request(method, url, **out_kwargs)
def chunk_push(self, volume_id, container_id, content_id, chunk_id, **data): key = "%s|%s|%s" % (container_id, content_id, chunk_id) value = self._get_db_chunk(volume_id).get(key.encode('utf8')) if value is not None: value = json.loads(value) else: value = dict() for k, v in data.iteritems(): value[k] = v if 'mtime' not in value: # not consistent if 'rtime' in value: # In functionnal test, we can encounter the case where rebuild # update (rtime) arrives before creation update (first mtime) value['mtime'] = value['rtime'] else: raise ServerException("mtime is mandatory") value = json.dumps(value) self._get_db_chunk(volume_id).put(key.encode('utf8'), value.encode('utf8'))
def account_list_containers(): account_id = request.args.get('id') if not account_id: return flask.Response('Missing Account ID', 400) info = get_backend().info_account(account_id) if not info: return "Account not found", 404 marker = request.args.get('marker', '') end_marker = request.args.get('end_marker', '') prefix = request.args.get('prefix', '') limit = int(request.args.get('limit', '1000')) delimiter = request.args.get('delimiter', '') user_list = get_backend().list_containers(account_id, limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, delimiter=delimiter) info['listing'] = user_list result = json.dumps(info) return flask.Response(result, mimetype='text/json')
def http_request(ipaddr, port, method, path, headers=None, query_string=None, body=None): headers = headers or {} if isinstance(body, dict): body = json.dumps(body) headers['Content-Type'] = 'application/json' headers['Content-Length'] = len(body) conn = http_connect(ipaddr, port, method, path, headers=headers, query_string=query_string) conn.send(body) resp = conn.getresponse() body = resp.read() resp.close() conn.close() return resp, body
def content_prepare(self, account=None, reference=None, path=None, size=None, cid=None, stgpol=None, **kwargs): """ Prepare an upload: get URLs of chunks on available rawx. :keyword autocreate: create container if it doesn't exist """ uri = self._make_uri('content/prepare') params = self._make_params(account, reference, path, cid=cid) data = {'size': size} if stgpol: data['policy'] = stgpol data = json.dumps(data) resp, body = self._direct_request('POST', uri, data=data, params=params, **kwargs) resp_headers = extract_content_headers_meta(resp.headers) return resp_headers, body
def del_properties(self, acct=None, ref=None, properties=[], cid=None, **kwargs): uri = self._make_uri('reference/del_properties') params = self._make_params(acct, ref, cid=cid) data = json.dumps(properties) resp, body = self._request( 'POST', uri, data=data, params=params)
def force(self, acct=None, ref=None, srv_type=None, services=None, cid=None, **kwargs): uri = self._make_uri('reference/force') params = self._make_params(acct, ref, cid=cid) data = json.dumps(services) resp, body = self._request( 'POST', uri, data=data, params=params)
def content_set_properties(self, acct=None, ref=None, path=None, properties={}, cid=None, **kwargs): uri = self._make_uri('content/set_properties') params = self._make_params(acct, ref, path, cid=cid) data = json.dumps(properties) resp, body = self._request( 'POST', uri, data=data, params=params)
def container_del_properties(self, account=None, reference=None, properties=[], cid=None, **kwargs): params = self._make_params(account, reference, cid=cid) data = json.dumps(properties) _resp, body = self._request( 'POST', '/del_properties', data=data, params=params, **kwargs) return body
def content_show(self, account=None, reference=None, path=None, properties=None, cid=None, content=None, **kwargs): """ Get a description of the content along with its user properties. """ uri = self._make_uri('content/get_properties') params = self._make_params(account, reference, path, cid=cid, content=content) data = json.dumps(properties) if properties else None resp, body = self._direct_request('POST', uri, data=data, params=params, **kwargs) obj_meta = extract_content_headers_meta(resp.headers) obj_meta.update(body) return obj_meta
def container_get_properties(self, account=None, reference=None, properties=None, cid=None, **kwargs): """ Get information about a container (user and system properties). :param account: account in which the container is :type account: `str` :param reference: name of the container :type reference: `str` :param cid: container id that can be used instead of account and reference :type cid: `str` :keyword headers: extra headers to send to the proxy :type headers: `dict` :returns: a `dict` with "properties" and "system" entries, containing respectively a `dict` of user properties and a `dict` of system properties. """ if not properties: properties = list() params = self._make_params(account, reference, cid=cid) data = json.dumps(properties) _resp, body = self._request('POST', '/get_properties', data=data, params=params, **kwargs) return body
def container_create(self, account, reference, properties=None, **kwargs): """ Create a container. :param account: account in which to create the container :type account: `str` :param reference: name of the container :type reference: `str` :param properties: properties to set on the container :type properties: `dict` :keyword headers: extra headers to send to the proxy :type headers: `dict` :returns: True if the container has been created, False if it already exists """ params = self._make_params(account, reference) headers = gen_headers() headers.update(kwargs.get('headers') or {}) data = json.dumps({ 'properties': properties or {}, 'system': kwargs.get('system', {}) }) resp, body = self._request('POST', '/create', params=params, data=data, headers=headers) if resp.status_code not in (204, 201): raise exceptions.from_response(resp, body) return resp.status_code == 201
def volume_dump(self, volume): info = self.rdir.status(volume) data = {} containers = info.get('container') data['chunk'] = info.get('chunk').get('total') for ct in containers: data['container.%s' % ct] = json.dumps(containers[ct]) return data
def account_info(): account_id = request.args.get('id') if not account_id: return flask.Response('Missing Account ID', 400) raw = get_backend().info_account(account_id) if raw is not None: return flask.Response(json.dumps(raw), mimetype='text/json') return "Account not found", 404
def rdir_admin_show(ns): _check_ns(ns) volume = request.args.get('vol') if not volume: return flask.Response('Missing volume id', 400) data = get_backend().admin_show(volume) return flask.Response(json.dumps(data), 200, mimetype='application/json')
def volume_show(self, volume): info = self.volume.status(volume) data = {} containers = info.get('container') data['chunk'] = info.get('chunk').get('total') for ct in containers: data['container.%s' % ct] = json.dumps(containers[ct]) return data
def content_spare(self, acct=None, ref=None, path=None, data=None, cid=None, **kwargs): uri = self._make_uri('content/spare') params = self._make_params(acct, ref, path, cid=cid) data = json.dumps(data) resp, body = self._request( 'POST', uri, data=data, params=params) return body
def container_del_properties(self, acct=None, ref=None, properties=[], cid=None, **kwargs): uri = self._make_uri('container/del_properties') params = self._make_params(acct, ref, cid=cid) data = json.dumps(properties) resp, body = self._request( 'POST', uri, data=data, params=params) return body
def container_get_properties(self, acct=None, ref=None, properties=[], cid=None, **kwargs): uri = self._make_uri('container/get_properties') params = self._make_params(acct, ref, cid=cid) data = json.dumps(properties) resp, body = self._request( 'POST', uri, data=data, params=params) return body
def process(self, env, cb): data = json.dumps(env) try: self.beanstalk.put(data) except BeanstalkError as e: msg = 'notify failure: %s' % str(e) resp = EventError(event=Event(env), body=msg) return resp(env, cb) return self.app(env, cb)
def to_json(self): """ Serialize the mapping to a JSON string suitable as input for 'meta0_force' request. """ simplified = dict() for pfx, services in self._extend().iteritems(): simplified[pfx] = [x['addr'] for x in services] return json.dumps(simplified)
def to_json(self): """ Serialize the mapping to a JSON string suitable as input for 'meta0_force' request. """ simplified = dict() for pfx, services in self.svc_by_pfx.iteritems(): simplified[pfx] = [x['addr'] for x in services] return json.dumps(simplified)
def container_create(self, acct=None, ref=None, cid=None, metadata=None, **kwargs): uri = self._make_uri('container/create') params = self._make_params(acct, ref, cid=cid) hdrs = gen_headers() metadata = metadata or {} data = json.dumps({'properties': {}}) resp, body = self._request( 'POST', uri, params=params, data=data, headers=hdrs)
def content_delete_many(self, account=None, reference=None, paths=None, cid=None, headers=None, **kwargs): uri = self._make_uri('content/delete_many') params = self._make_params(account, reference, cid=cid) if not headers: headers = dict() headers.update(gen_headers()) unformatted_data = list() for obj in paths: unformatted_data.append({'name': obj}) data = json.dumps({"contents": unformatted_data}) results = list() try: resp, _ = self._direct_request('POST', uri, data=data, params=params, headers=headers) for obj in resp.json()["contents"]: results.append((obj["name"], obj["status"] == 204)) return results except exceptions.NotFound: for obj in paths: rc = self.content_delete(account, reference, obj, cid=cid, headers=headers, **kwargs) results.append((obj, rc)) return results except exceptions.TooLarge: pivot = len(paths) / 2 head = paths[:pivot] tail = paths[pivot:] if head: results += self.content_delete_many(account, reference, head, cid=cid, headers=headers, **kwargs) if tail: results += self.content_delete_many(account, reference, tail, cid=cid, headers=headers, **kwargs) return results except: raise
def content_set_properties(self, account=None, reference=None, path=None, properties={}, cid=None, version=None, **kwargs): uri = self._make_uri('content/set_properties') params = self._make_params(account, reference, path, cid=cid, version=version) data = json.dumps(properties) _resp, _body = self._direct_request( 'POST', uri, data=data, params=params, **kwargs)
def container_create_many(self, account, containers, properties=None, **kwargs): """ Create several containers. :param account: account in which to create the containers :type account: `str` :param containers: names of the containers :type containers: iterable of `str` :param properties: properties to set on the containers :type properties: `dict` :keyword headers: extra headers to send to the proxy :type headers: `dict` """ results = list() try: params = self._make_params(account) unformatted_data = list() for container in containers: unformatted_data.append({'name': container, 'properties': properties or {}, 'system': kwargs.get('system', {})}) data = json.dumps({"containers": unformatted_data}) resp, body = self._request('POST', '/create_many', params=params, data=data, autocreate=True, **kwargs) if resp.status not in (204, 200): raise exceptions.from_response(resp, body) for container in body["containers"]: results.append((container["name"], container["status"] == 201)) return results except exceptions.TooLarge: # Batch too large for the proxy pivot = len(containers) / 2 head = containers[:pivot] tail = containers[pivot:] if head: results += self.container_create_many( account, head, properties=properties, **kwargs) if tail: results += self.container_create_many( account, tail, properties=properties, **kwargs) return results except exceptions.NotFound: # Batches not supported by the proxy for container in containers: try: rc = self.container_create( account, container, properties=properties, **kwargs) results.append((container, rc)) except Exception: results.append((container, False)) return results
def content_spare(self, acct=None, ref=None, path=None, data=None, cid=None, stgpol=None, **kwargs): uri = self._make_uri('content/spare') params = self._make_params(acct, ref, path, cid=cid) if stgpol: params['stgpol'] = stgpol data = json.dumps(data) resp, body = self._request( 'POST', uri, data=data, params=params) return body
def content_prepare(self, acct=None, ref=None, path=None, size=None, cid=None, **kwargs): uri = self._make_uri('content/prepare') params = self._make_params(acct, ref, path, cid=cid) data = {'size': size} data = json.dumps(data) hdrs = gen_headers() resp, body = self._request( 'POST', uri, data=data, params=params, headers=hdrs) return body
def process(self, env, cb): data = json.dumps(env) try: # TODO we could retry the put self.beanstalk.put(data) except ConnectionError: self.logger.warn("beanstalk notify failed") except Exception as e: self.logger.warn("failed to notify event: %s" % str(e)) return EventError(event=Event(env))(env, cb) return self.app(env, cb)
def container_set_properties(self, account=None, reference=None, properties=None, clear=False, cid=None, system=None, **kwargs): params = self._make_params(account, reference, cid=cid) if clear: params["flush"] = 1 data = json.dumps({'properties': properties or {}, 'system': system or {}}) _resp, body = self._request( 'POST', '/set_properties', data=data, params=params, **kwargs) return body
def rdir_admin_incident_get(ns): _check_ns(ns) volume = request.args.get('vol') if not volume: return flask.Response('Missing volume id', 400) date = get_backend().admin_get_incident_date(volume) resp = {} if date: resp = {'date': date} return flask.Response(json.dumps(resp), 200, mimetype='application/json')
def on_account_container_update(self, req): account_id = self._get_account_id(req) d = json.loads(req.get_data()) name = d.get("name") mtime = d.get("mtime") dtime = d.get("dtime") object_count = d.get("objects") bytes_used = d.get("bytes") info = self.backend.update_container(account_id, name, mtime, dtime, object_count, bytes_used) result = json.dumps(info) return Response(result)
def rdir_admin_incident_get(ns): _check_ns(ns) volume = request.args.get("vol") if not volume: return flask.Response("Missing volume id", 400) date = get_backend().admin_get_incident_date(volume) resp = {} if date: resp = {"date": date} return flask.Response(json.dumps(resp), 200, mimetype="application/json")
def content_create(self, acct=None, ref=None, path=None, size=None, checksum=None, data=None, cid=None, **kwargs): uri = self._make_uri('content/create') params = self._make_params(acct, ref, path, cid=cid) data = json.dumps(data) hdrs = gen_headers() hdrs.update({'x-oio-content-meta-length': size, 'x-oio-content-meta-hash': checksum}) resp, body = self._request( 'POST', uri, data=data, params=params, headers=hdrs)
def force(self, acct=None, ref=None, srv_type=None, services=None, cid=None, **kwargs): uri = self._make_uri('reference/force') params = self._make_params(acct, ref, cid=cid) data = json.dumps(services) resp, body = self._request('POST', uri, data=data, params=params)
def container_raw_delete(self, account=None, reference=None, data=None, cid=None, **kwargs): params = self._make_params(account, reference, cid=cid) data = json.dumps(data) resp, body = self._request('POST', '/raw_delete', data=data, params=params)
def on_account_container_update(self, req): account_id = self._get_account_id(req) d = json.loads(req.get_data()) name = d.get('name') mtime = d.get('mtime') dtime = d.get('dtime') object_count = d.get('objects') bytes_used = d.get('bytes') info = self.backend.update_container(account_id, name, mtime, dtime, object_count, bytes_used) result = json.dumps(info) return Response(result)
def on_rdir_fetch(self, req): volume = self._get_volume(req) pretty = req.args.get('pretty') decoded = json.loads(req.get_data()) start_after = decoded.get('start_after') limit = decoded.get('limit') if limit is not None and limit <= 0: return BadRequest('limit must be greater than 0') rebuild = decoded.get('rebuild', False) if not isinstance(rebuild, bool): return BadRequest('rebuild must be true or false') data = self.backend.chunk_fetch(volume, start_after=start_after, limit=limit, rebuild=rebuild) if pretty: body = json.dumps(data, indent=4) else: body = json.dumps(data) return Response(body, mimetype='application/json')
def content_prepare(self, acct=None, ref=None, path=None, size=None, cid=None, stgpol=None, **kwargs): uri = self._make_uri('content/prepare') params = self._make_params(acct, ref, path, cid=cid) data = {'size': size} if stgpol: data['policy'] = stgpol data = json.dumps(data) hdrs = gen_headers() resp, body = self._request( 'POST', uri, data=data, params=params, headers=hdrs) resp_headers = extract_content_headers_meta(resp.headers) return resp_headers, body
def http_request(host, method, path, headers=None, query_string=None, body=None): headers = headers or {} if isinstance(body, dict): body = json.dumps(body) headers['Content-Type'] = 'application/json' headers['Content-Length'] = len(body) conn = http_connect(host, method, path, headers=headers, query_string=query_string) conn.send(body) resp = conn.getresponse() body = resp.read() resp.close() conn.close() return resp, body
def handle_container_destroy(self, event): """ Handle container destroy. :param event: """ self.logger.debug('worker "%s" handle container destroy', self.name) if not self.acct_update: return uri = 'http://%s/v1.0/account/container/update' % self.acct_addr dtime = event.get('when') data = event.get('data') name = data.get('url').get('user') account = data.get('url').get('account') event = {'dtime': dtime, 'name': name} self.session.post(uri, params={'id': account}, data=json.dumps(event))
def handle_container_destroy(self, event): """ Handle container destroy. :param event: """ self.logger.debug('worker "%s" handle container destroy', self.name) if not self.acct_update: return uri = "http://%s/v1.0/account/container/update" % self.acct_addr dtime = event.get("when") data = event.get("data") name = data.get("url").get("user") account = data.get("url").get("account") event = {"dtime": dtime, "name": name} self.session.post(uri, params={"id": account}, data=json.dumps(event))
def on_rdir_admin_clear(self, req): volume = self._get_volume(req) decoded = json.loads(req.get_data()) clear_all = decoded.get('all', False) if not isinstance(clear_all, bool): return BadRequest('"all" must be true or false') lock = self.backend.admin_lock(volume, 'admin_clear') if lock is not None: return Response("Already locked by %s" % lock, 403) nb = self.backend.admin_clear(volume, clear_all) self.backend.admin_unlock(volume) resp = {'removed': nb} return Response(json.dumps(resp), mimetype='application/json')
def on_rdir_admin_incident(self, req): volume = self._get_volume(req) if req.method == 'POST': decoded = json.loads(req.get_data()) date = decoded.get('date') if date is None or not isinstance(date, int): return BadRequest('Missing date or bad format') self.backend.admin_set_incident_date(volume, date) return Response(status=204) else: date = self.backend.admin_get_incident_date(volume) resp = {} if date: resp = {'date': date} return Response(json.dumps(resp), mimetype='application/json')
def handle_container_update(self, event): """ Handle container update. :param event: """ self.logger.debug('worker "%s" handle container update', self.name) if not self.acct_update: return uri = "http://%s/v1.0/account/container/update" % self.acct_addr mtime = event.get("when") data = event.get("data") name = event.get("url").get("user") account = event.get("url").get("account") bytes_count = data.get("bytes-count", 0) object_count = data.get("object-count", 0) event = {"mtime": mtime, "name": name, "bytes": bytes_count, "objects": object_count} self.session.post(uri, params={"id": account}, data=json.dumps(event))
def on_account_containers(self, req): account_id = self._get_account_id(req) info = self.backend.info_account(account_id) if not info: return NotFound("Account not found") marker = req.args.get("marker", "") end_marker = req.args.get("end_marker", "") prefix = req.args.get("prefix", "") limit = int(req.args.get("limit", "1000")) delimiter = req.args.get("delimiter", "") user_list = self.backend.list_containers( account_id, limit=limit, marker=marker, end_marker=end_marker, prefix=prefix, delimiter=delimiter ) info["listing"] = user_list result = json.dumps(info) return Response(result, mimetype="text/json")
def chunk_push(self, volume_id, container_id, content_id, chunk_id, **data): key = "%s|%s|%s" % (container_id, content_id, chunk_id) value = self._get_db_chunk(volume_id).get(key.encode('utf8')) if value is not None: value = json.loads(value) else: value = dict() for k, v in data.iteritems(): value[k] = v if 'mtime' not in value: # not consistent raise ServerException("mtime is mandatory") value = json.dumps(value) self._get_db_chunk(volume_id).put(key.encode('utf8'), value.encode('utf8'))