def test_attach_with_invalid_arguments(self): # Invalid request to attach volume an invalid target body = {"os-attach": {"mountpoint": "/dev/vdc"}} req = webob.Request.blank("/v2/fake/volumes/1/action") req.method = "POST" req.headers["content-type"] = "application/json" req.body = jsonutils.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) # Invalid request to attach volume to an instance and a host body = {"os-attach": {"instance_uuid": "fake", "host_name": "fake_host", "mountpoint": "/dev/vdc"}} req = webob.Request.blank("/v2/fake/volumes/1/action") req.method = "POST" req.headers["content-type"] = "application/json" req.body = jsonutils.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) # Invalid request to attach volume with an invalid mode body = {"os-attach": {"instance_uuid": "fake", "mountpoint": "/dev/vdc", "mode": "rr"}} req = webob.Request.blank("/v2/fake/volumes/1/action") req.method = "POST" req.headers["content-type"] = "application/json" req.body = jsonutils.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400) body = {"os-attach": {"host_name": "fake_host", "mountpoint": "/dev/vdc", "mode": "ww"}} req = webob.Request.blank("/v2/fake/volumes/1/action") req.method = "POST" req.headers["content-type"] = "application/json" req.body = jsonutils.dumps(body) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400)
def _is_serializable(value): """Returns True if value is serializable.""" try: jsonutils.dumps(value) except TypeError: LOG.info(_("Value with type=%s is not serializable") % type(value)) return False return True
def __call__(self, target, creds, enforcer): """Check http: rules by calling to a remote server. This example implementation simply verifies that the response is exactly 'True'. """ url = ('http:' + self.match) % target data = {'target': jsonutils.dumps(target), 'credentials': jsonutils.dumps(creds)} post_data = urlparse.urlencode(data) f = urlrequest.urlopen(url, post_data) return f.read() == "True"
def _check_http(brain, match_kind, match, target_dict, cred_dict): """Check http: rules by calling to a remote server. This example implementation simply verifies that the response is exactly 'True'. A custom brain using response codes could easily be implemented. """ url = 'http:' + (match % target_dict) data = {'target': jsonutils.dumps(target_dict), 'credentials': jsonutils.dumps(cred_dict)} post_data = urllib.urlencode(data) f = urllib2.urlopen(url, post_data) return f.read() == "True"
def _pack_json_msg(self, msg): """Qpid cannot serialize dicts containing strings longer than 65535 characters. This function dumps the message content to a JSON string, which Qpid is able to handle. :param msg: May be either a Qpid Message object or a bare dict. :returns: A Qpid Message with its content field JSON encoded. """ try: msg.content = jsonutils.dumps(msg.content) except AttributeError: # Need to have a Qpid message so we can set the content_type. msg = qpid_messaging.Message(jsonutils.dumps(msg)) msg.content_type = JSON_CONTENT_TYPE return msg
def test_update_all_with_keys_in_uppercase_and_lowercase(self): self.stubs.Set(cinder.db, 'volume_metadata_get', return_create_volume_metadata) self.stubs.Set(cinder.db, 'volume_metadata_update', return_new_volume_metadata) req = fakes.HTTPRequest.blank(self.url) req.method = 'PUT' req.content_type = "application/json" body = { 'metadata': { 'key10': 'value10', 'KEY10': 'value10', 'key99': 'value99', 'KEY20': 'value20', }, } expected = { 'metadata': { 'key10': 'value10', 'key99': 'value99', 'KEY20': 'value20', }, } req.body = jsonutils.dumps(expected) res_dict = self.controller.update_all(req, self.req_id, body) self.assertEqual(expected, res_dict)
def __call__(self, *args): data = jsonutils.dumps({'object': self.obj, 'method': self.method, 'params': args}) auth = ('%s:%s' % (self.user, self.password)).encode('base64')[:-1] headers = {'Content-Type': 'application/json', 'Authorization': 'Basic %s' % (auth,)} LOG.debug(_('Sending JSON data: %s'), data) request = urllib2.Request(self.url, data, headers) response_obj = urllib2.urlopen(request) if response_obj.info().status == 'EOF in headers': if self.auto and self.url.startswith('http://'): LOG.info(_('Auto switching to HTTPS connection to %s'), self.url) self.url = 'https' + self.url[4:] request = urllib2.Request(self.url, data, headers) response_obj = urllib2.urlopen(request) else: LOG.error(_('No headers in server response')) raise NexentaJSONException(_('Bad response from server')) response_data = response_obj.read() LOG.debug(_('Got response: %s'), response_data) response = jsonutils.loads(response_data) if response.get('error') is not None: raise NexentaJSONException(response['error'].get('message', '')) else: return response.get('result')
def serialize_remote_exception(failure_info): """Prepares exception data to be sent over rpc. Failure_info should be a sys.exc_info() tuple. """ tb = traceback.format_exception(*failure_info) failure = failure_info[1] LOG.error(_("Returning exception %s to caller"), unicode(failure)) LOG.error(tb) kwargs = {} if hasattr(failure, 'kwargs'): kwargs = failure.kwargs data = { 'class': str(failure.__class__.__name__), 'module': str(failure.__class__.__module__), 'message': unicode(failure), 'tb': tb, 'args': failure.args, 'kwargs': kwargs } json_data = jsonutils.dumps(data) return json_data
def serialize_msg(raw_msg): # NOTE(russellb) See the docstring for _RPC_ENVELOPE_VERSION for more # information about this format. msg = {_VERSION_KEY: _RPC_ENVELOPE_VERSION, _MESSAGE_KEY: jsonutils.dumps(raw_msg)} return msg
def test_force_delete_snapshot(self): self.stubs.Set(os.path, 'exists', lambda x: True) # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is creating volume = db.volume_create(ctx, {'host': 'test'}) snapshot = db.snapshot_create(ctx, {'status': 'creating', 'volume_size': 1, 'volume_id': volume['id']}) path = '/v2/fake/snapshots/%s/action' % snapshot['id'] req = webob.Request.blank(path) req.method = 'POST' req.headers['content-type'] = 'application/json' req.body = jsonutils.dumps({'os-force_delete': {}}) # attach admin context to request req.environ['cinder.context'] = ctx # start service to handle rpc.cast for 'delete snapshot' svc = self.start_service('volume', host='test') # make request resp = req.get_response(app()) # request is accepted self.assertEqual(resp.status_int, 202) # snapshot is deleted self.assertRaises(exception.NotFound, db.snapshot_get, ctx, snapshot['id']) # cleanup svc.stop()
def test_force_detach_volume(self): # admin context ctx = context.RequestContext("admin", "fake", True) # current status is available volume = db.volume_create(ctx, {"status": "available", "host": "test", "provider_location": ""}) # start service to handle rpc messages for attach requests self.start_service("volume", host="test") self.volume_api.reserve_volume(ctx, volume) self.volume_api.initialize_connection(ctx, volume, {}) mountpoint = "/dev/vbd" self.volume_api.attach(ctx, volume, fakes.FAKE_UUID, mountpoint) # volume is attached volume = db.volume_get(ctx, volume["id"]) self.assertEquals(volume["status"], "in-use") self.assertEquals(volume["instance_uuid"], fakes.FAKE_UUID) self.assertEquals(volume["mountpoint"], mountpoint) self.assertEquals(volume["attach_status"], "attached") # build request to force detach req = webob.Request.blank("/v1/fake/volumes/%s/action" % volume["id"]) req.method = "POST" req.headers["content-type"] = "application/json" # request status of 'error' req.body = jsonutils.dumps({"os-force_detach": None}) # attach admin context to request req.environ["cinder.context"] = ctx # make request resp = req.get_response(app()) # request is accepted self.assertEquals(resp.status_int, 202) volume = db.volume_get(ctx, volume["id"]) # status changed to 'available' self.assertEquals(volume["status"], "available") self.assertEquals(volume["instance_uuid"], None) self.assertEquals(volume["mountpoint"], None) self.assertEquals(volume["attach_status"], "detached")
def format(self, record): message = { "message": record.getMessage(), "asctime": self.formatTime(record, self.datefmt), "name": record.name, "msg": record.msg, "args": record.args, "levelname": record.levelname, "levelno": record.levelno, "pathname": record.pathname, "filename": record.filename, "module": record.module, "lineno": record.lineno, "funcname": record.funcName, "created": record.created, "msecs": record.msecs, "relative_created": record.relativeCreated, "thread": record.thread, "thread_name": record.threadName, "process_name": record.processName, "process": record.process, "traceback": None, } if hasattr(record, "extra"): message["extra"] = record.extra if record.exc_info: message["traceback"] = self.formatException(record.exc_info) return jsonutils.dumps(message)
def __init__(self, session, callback, node_name, node_opts, link_name, link_opts): """Declare a queue on an amqp session. 'session' is the amqp session to use 'callback' is the callback to call when messages are received 'node_name' is the first part of the Qpid address string, before ';' 'node_opts' will be applied to the "x-declare" section of "node" in the address string. 'link_name' goes into the "name" field of the "link" in the address string 'link_opts' will be applied to the "x-declare" section of "link" in the address string. """ self.callback = callback self.receiver = None self.session = None addr_opts = { "create": "always", "node": {"type": "topic", "x-declare": {"durable": True, "auto-delete": True}}, "link": { "name": link_name, "durable": True, "x-declare": {"durable": False, "auto-delete": True, "exclusive": False}, }, } addr_opts["node"]["x-declare"].update(node_opts) addr_opts["link"]["x-declare"].update(link_opts) self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts)) self.reconnect(session)
def __init__(self, session, node_name, node_opts=None): """Init the Publisher class with the exchange_name, routing_key, and other options """ self.sender = None self.session = session addr_opts = { "create": "always", "node": { "type": "topic", "x-declare": { "durable": False, # auto-delete isn't implemented for exchanges in qpid, # but put in here anyway "auto-delete": True, }, }, } if node_opts: addr_opts["node"]["x-declare"].update(node_opts) self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts)) self.reconnect(session)
def format(self, record): message = {'message': record.getMessage(), 'asctime': self.formatTime(record, self.datefmt), 'name': record.name, 'msg': record.msg, 'args': record.args, 'levelname': record.levelname, 'levelno': record.levelno, 'pathname': record.pathname, 'filename': record.filename, 'module': record.module, 'lineno': record.lineno, 'funcname': record.funcName, 'created': record.created, 'msecs': record.msecs, 'relative_created': record.relativeCreated, 'thread': record.thread, 'thread_name': record.threadName, 'process_name': record.processName, 'process': record.process, 'traceback': None} if hasattr(record, 'extra'): message['extra'] = record.extra if record.exc_info: message['traceback'] = self.formatException(record.exc_info) return jsonutils.dumps(message)
def _issue_api_request(self, method_name, params): """All API requests to SolidFire device go through this method Simple json-rpc web based API calls. each call takes a set of paramaters (dict) and returns results in a dict as well. """ host = FLAGS.san_ip # For now 443 is the only port our server accepts requests on port = 443 # NOTE(john-griffith): Probably don't need this, but the idea is # we provide a request_id so we can correlate # responses with requests request_id = int(uuid.uuid4()) # just generate a random number cluster_admin = FLAGS.san_login cluster_password = FLAGS.san_password command = {'method': method_name, 'id': request_id} if params is not None: command['params'] = params payload = jsonutils.dumps(command, ensure_ascii=False) payload.encode('utf-8') # we use json-rpc, webserver needs to see json-rpc in header header = {'Content-Type': 'application/json-rpc; charset=utf-8'} if cluster_password is not None: # base64.encodestring includes a newline character # in the result, make sure we strip it off auth_key = base64.encodestring('%s:%s' % (cluster_admin, cluster_password))[:-1] header['Authorization'] = 'Basic %s' % auth_key LOG.debug(_("Payload for SolidFire API call: %s"), payload) connection = httplib.HTTPSConnection(host, port) connection.request('POST', '/json-rpc/1.0', payload, header) response = connection.getresponse() data = {} if response.status != 200: connection.close() raise exception.SolidFireAPIException(status=response.status) else: data = response.read() try: data = jsonutils.loads(data) except (TypeError, ValueError), exc: connection.close() msg = _("Call to json.loads() raised an exception: %s") % exc raise exception.SfJsonEncodeFailure(msg) connection.close()
def test_retype_volume_no_body(self): # Request with no body should fail req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = 'POST' req.headers['content-type'] = 'application/json' req.body = jsonutils.dumps({'os-retype': None}) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400)
def make_update_readonly_flag_test(self, readonly, return_code): body = {"os-update_readonly_flag": {"readonly": readonly}} req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = "POST" req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, return_code)
def _issue_backup_reset(self, ctx, backup, updated_status): req = webob.Request.blank("/v2/fake/backups/%s/action" % backup["id"]) req.method = "POST" req.headers["content-type"] = "application/json" req.body = jsonutils.dumps({"os-reset_status": updated_status}) req.environ["cinder.context"] = ctx resp = req.get_response(app()) return resp
def _retype_volume_exec(self, expected_status, new_type='foo'): req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = 'POST' req.headers['content-type'] = 'application/json' retype_body = {'new_type': new_type, 'migration_policy': 'never'} req.body = jsonutils.dumps({'os-retype': retype_body}) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, expected_status)
def test_retype_volume_bad_policy(self): # Request with invalid migration policy should fail req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = 'POST' req.headers['content-type'] = 'application/json' retype_body = {'new_type': 'foo', 'migration_policy': 'invalid'} req.body = jsonutils.dumps({'os-retype': retype_body}) res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 400)
def test_update_all_malformed_data(self): self.stubs.Set(cinder.db, "volume_metadata_update", return_create_volume_metadata) req = fakes.HTTPRequest.blank(self.url) req.method = "PUT" req.content_type = "application/json" expected = {"metadata": ["asdf"]} req.body = jsonutils.dumps(expected) self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update_all, req, self.id, expected)
def test_update_all_nonexistent_volume(self): self.stubs.Set(cinder.db, "volume_get", return_volume_nonexistent) req = fakes.HTTPRequest.blank(self.url) req.method = "PUT" req.content_type = "application/json" body = {"metadata": {"key10": "value10"}} req.body = jsonutils.dumps(body) self.assertRaises(webob.exc.HTTPNotFound, self.controller.update_all, req, "100", body)
def test_update_item_nonexistent_volume(self): self.stubs.Set(cinder.db, "volume_get", return_volume_nonexistent) req = fakes.HTTPRequest.blank("/v1.1/fake/volumes/asdf/metadata/key1") req.method = "PUT" body = {"meta": {"key1": "value1"}} req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" self.assertRaises(webob.exc.HTTPNotFound, self.controller.update, req, self.id, "key1", body)
def test_update_item_value_too_long(self): self.stubs.Set(cinder.db, "volume_metadata_update", return_create_volume_metadata) req = fakes.HTTPRequest.blank(self.url + "/key1") req.method = "PUT" body = {"meta": {"key1": ("a" * 260)}} req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, self.controller.update, req, self.id, "key1", body)
def test_update_item_body_uri_mismatch(self): self.stubs.Set(cinder.db, "volume_metadata_update", return_create_volume_metadata) req = fakes.HTTPRequest.blank(self.url + "/bad") req.method = "PUT" body = {"meta": {"key1": "value1"}} req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" self.assertRaises(webob.exc.HTTPBadRequest, self.controller.update, req, self.id, "bad", body)
def _issue_volume_reset(self, ctx, volume, updated_status): req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' req.body = \ jsonutils.dumps({'os-reset_status': updated_status}) req.environ['cinder.context'] = ctx resp = req.get_response(app()) return resp
def _migrate_volume_comp_exec(self, ctx, volume, new_volume, error, expected_status, expected_id, no_body=False): req = webob.Request.blank("/v2/fake/volumes/%s/action" % volume["id"]) req.method = "POST" req.headers["content-type"] = "application/json" body = {"new_volume": new_volume["id"], "error": error} if no_body: req.body = jsonutils.dumps({"": body}) else: req.body = jsonutils.dumps({"os-migrate_volume_completion": body}) req.environ["cinder.context"] = ctx resp = req.get_response(app()) resp_dict = ast.literal_eval(resp.body) # verify status self.assertEqual(resp.status_int, expected_status) if expected_id: self.assertEqual(resp_dict["save_volume_id"], expected_id) else: self.assertNotIn("save_volume_id", resp_dict)
def test_attach_to_instance(self): body = {"os-attach": {"instance_uuid": "fake", "mountpoint": "/dev/vdc", "mode": "rw"}} req = webob.Request.blank("/v2/fake/volumes/1/action") req.method = "POST" req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202)
def test_simple_api_actions(self): app = fakes.wsgi_app() for _action in self._actions: req = webob.Request.blank("/v2/fake/volumes/%s/action" % self.UUID) req.method = "POST" req.body = jsonutils.dumps({_action: None}) req.content_type = "application/json" res = req.get_response(app) self.assertEqual(res.status_int, 202)
def test_attach_to_host(self): # using 'read-write' mode attach volume by default body = { 'os-attach': { 'host_name': 'fake_host', 'mountpoint': '/dev/vdc' } } req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = "POST" req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202)
def test_update_readonly_flag(self): def fake_update_readonly_flag(*args, **kwargs): return {} self.stubs.Set(volume.API, 'update_readonly_flag', fake_update_readonly_flag) body = {'os-update_readonly_flag': {'readonly': True}} req = webob.Request.blank('/v2/fake/volumes/1/action') req.method = "POST" req.body = jsonutils.dumps(body) req.headers["content-type"] = "application/json" res = req.get_response(fakes.wsgi_app()) self.assertEqual(res.status_int, 202)
def test_invalid_metadata_items_on_create(self): self.stubs.Set(db, 'volume_metadata_update', return_create_volume_metadata) req = fakes.HTTPRequest.blank(self.url) req.method = 'POST' req.headers["content-type"] = "application/json" #test for long key data = {"metadata": {"a" * 260: "value1"}} req.body = jsonutils.dumps(data) self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, self.controller.create, req, self.req_id, data) #test for long value data = {"metadata": {"key": "v" * 260}} req.body = jsonutils.dumps(data) self.assertRaises(webob.exc.HTTPRequestEntityTooLarge, self.controller.create, req, self.req_id, data) #test for empty key. data = {"metadata": {"": "value1"}} req.body = jsonutils.dumps(data) self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, req, self.req_id, data)
def _migrate_volume_exec(self, ctx, volume, host, expected_status, force_host_copy=False): admin_ctx = context.get_admin_context() # build request to migrate to host req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' body = {'os-migrate_volume': {'host': host, 'force_host_copy': force_host_copy}} req.body = jsonutils.dumps(body) req.environ['cinder.context'] = ctx resp = req.get_response(app()) # verify status self.assertEqual(resp.status_int, expected_status) volume = db.volume_get(admin_ctx, volume['id']) return volume
def test_create_server_bad_hints(self): req = fakes.HTTPRequest.blank('/v2/fake/volumes') req.method = 'POST' req.content_type = 'application/json' body = { 'volume': { 'id': id, 'volume_type_id': 'cedef40a-ed67-4d10-800e-17455edce175', 'volume_id': '1', 'scheduler_hints': 'a', } } req.body = jsonutils.dumps(body) res = req.get_response(self.app) self.assertEqual(400, res.status_int)
def test_migrate_volume_without_host_parameter(self): expected_status = 400 host = 'test3' ctx = context.RequestContext('admin', 'fake', True) volume = self._migrate_volume_prep() # build request to migrate without host req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' body = {'os-migrate_volume': {'host': host, 'force_host_copy': False}} req.body = jsonutils.dumps(body) req.environ['cinder.context'] = ctx resp = req.get_response(app()) # verify status self.assertEqual(resp.status_int, expected_status)
def get(self, volume_id): """Get volume metadata. Returns a json-encoded dict containing all metadata and the restore version i.e. the version used to decide what actually gets restored from this container when doing a backup restore. """ container = {'version': CONF.backup_metadata_version} self._save_vol_base_meta(container, volume_id) self._save_vol_meta(container, volume_id) self._save_vol_glance_meta(container, volume_id) if container: return jsonutils.dumps(container) else: return None
def _migrate_volume_comp_exec(self, ctx, volume, new_volume, error, expected_status, expected_id): req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' body_dict = {'new_volume': new_volume['id'], 'error': error} req.body = jsonutils.dumps({'os-migrate_volume_completion': body_dict}) req.environ['cinder.context'] = ctx resp = req.get_response(app()) resp_dict = ast.literal_eval(resp.body) # verify status self.assertEqual(resp.status_int, expected_status) if expected_id: self.assertEqual(resp_dict['save_volume_id'], expected_id) else: self.assertNotIn('save_volume_id', resp_dict)
def setUp(self): super(HostFiltersTestCase, self).setUp() self.stubs = stubout.StubOutForTesting() stub_out_https_backend(self.stubs) self.context = context.RequestContext('fake', 'fake') self.json_query = jsonutils.dumps( ['and', ['>=', '$free_capacity_gb', 1024], ['>=', '$total_capacity_gb', 10 * 1024]]) # This has a side effect of testing 'get_filter_classes' # when specifying a method (in this case, our standard filters) filter_handler = filters.HostFilterHandler('cinder.scheduler.filters') classes = filter_handler.get_all_classes() self.class_map = {} for cls in classes: self.class_map[cls.__name__] = cls
def test_update_all(self): self.stubs.Set(cinder.db, 'snapshot_metadata_update', return_create_snapshot_metadata) req = fakes.HTTPRequest.blank(self.url) req.method = 'PUT' req.content_type = "application/json" expected = { 'metadata': { 'key10': 'value10', 'key99': 'value99', }, } req.body = jsonutils.dumps(expected) res_dict = self.controller.update_all(req, self.req_id, expected) self.assertEqual(expected, res_dict)
def test_force_delete(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is creating volume = db.volume_create(ctx, {'size': 1}) req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' req.body = jsonutils.dumps({'os-force_delete': {}}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # request is accepted self.assertEqual(resp.status_int, 202) # volume is deleted self.assertRaises(exception.NotFound, db.volume_get, ctx, volume['id'])
def check_for_delay(self, verb, path, username=None): body = jsonutils.dumps({"verb": verb, "path": path}) headers = {"Content-Type": "application/json"} conn = httplib.HTTPConnection(self.limiter_address) if username: conn.request("POST", "/%s" % (username), body, headers) else: conn.request("POST", "/", body, headers) resp = conn.getresponse() if 200 >= resp.status < 300: return None, None return resp.getheader("X-Wait-Seconds"), resp.read() or None
def test_force_detach_host_attached_volume(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is available volume = db.volume_create(ctx, { 'status': 'available', 'host': 'test', 'provider_location': '' }) connector = {'initiator': 'iqn.2012-07.org.fake:01'} # start service to handle rpc messages for attach requests svc = self.start_service('volume', host='test') self.volume_api.reserve_volume(ctx, volume) self.volume_api.initialize_connection(ctx, volume, connector) mountpoint = '/dev/vbd' host_name = 'fake-host' self.volume_api.attach(ctx, volume, None, host_name, mountpoint) # volume is attached volume = db.volume_get(ctx, volume['id']) self.assertEquals(volume['status'], 'in-use') self.assertEquals(volume['instance_uuid'], None) self.assertEquals(volume['attached_host'], host_name) self.assertEquals(volume['mountpoint'], mountpoint) self.assertEquals(volume['attach_status'], 'attached') # build request to force detach req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # request status of 'error' req.body = jsonutils.dumps({'os-force_detach': None}) # attach admin context to request req.environ['cinder.context'] = ctx # make request resp = req.get_response(app()) # request is accepted self.assertEquals(resp.status_int, 202) volume = db.volume_get(ctx, volume['id']) # status changed to 'available' self.assertEquals(volume['status'], 'available') self.assertEquals(volume['instance_uuid'], None) self.assertEquals(volume['attached_host'], None) self.assertEquals(volume['mountpoint'], None) self.assertEquals(volume['attach_status'], 'detached') # cleanup svc.stop()
def test_reset_status_as_non_admin(self): # current status is 'error' volume = db.volume_create(context.get_admin_context(), {'status': 'error'}) req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # request changing status to available req.body = jsonutils.dumps({'os-reset_status': {'status': 'available'}}) # non-admin context req.environ['cinder.context'] = context.RequestContext('fake', 'fake') resp = req.get_response(app()) # request is not authorized self.assertEquals(resp.status_int, 403) volume = db.volume_get(context.get_admin_context(), volume['id']) # status is still 'error' self.assertEquals(volume['status'], 'error')
def test_create(self): self.stubs.Set(db, 'volume_metadata_get', return_empty_volume_metadata) self.stubs.Set(db, 'volume_metadata_update', return_create_volume_metadata) req = fakes.HTTPRequest.blank('/v2/volume_metadata') req.method = 'POST' req.content_type = "application/json" body = { "metadata": { "key1": "value1", "key2": "value2", "key3": "value3", } } req.body = jsonutils.dumps(body) res_dict = self.controller.create(req, self.req_id, body) self.assertEqual(body, res_dict)
def test_malformed_reset_status_body(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is available volume = db.volume_create(ctx, {'status': 'available', 'size': 1}) req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # malformed request body req.body = jsonutils.dumps({'os-reset_status': {'x-status': 'bad'}}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # bad request self.assertEqual(resp.status_int, 400) volume = db.volume_get(ctx, volume['id']) # status is still 'available' self.assertEqual(volume['status'], 'available')
def test_reset_status_for_missing_volume(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # missing-volume-id req = webob.Request.blank('/v2/fake/volumes/%s/action' % 'missing-volume-id') req.method = 'POST' req.headers['content-type'] = 'application/json' # malformed request body req.body = jsonutils.dumps({'os-reset_status': {'status': 'available'}}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # not found self.assertEquals(resp.status_int, 404) self.assertRaises(exception.NotFound, db.volume_get, ctx, 'missing-volume-id')
def test_reset_status_as_admin(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is available volume = db.volume_create(ctx, {'status': 'available'}) req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # request status of 'error' req.body = jsonutils.dumps({'os-reset_status': {'status': 'error'}}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # request is accepted self.assertEqual(resp.status_int, 202) volume = db.volume_get(ctx, volume['id']) # status changed to 'error' self.assertEqual(volume['status'], 'error')
def test_update_progress(self): ctx = context.RequestContext('admin', 'fake', True) # snapshot in 'error_deleting' volume = db.volume_create(ctx, {}) snapshot = db.snapshot_create(ctx, {'volume_id': volume['id']}) req = webob.Request.blank('/v2/fake/snapshots/%s/action' % snapshot['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # request status of 'error' req.body = jsonutils.dumps({'os-update_progress': 'progress!'}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # request is accepted self.assertEquals(resp.status_int, 202) snapshot = db.snapshot_get(ctx, snapshot['id']) # status changed to 'error' self.assertEquals(snapshot['progress'], 'progress!')
def __init__(self, session, callback, node_name, node_opts, link_name, link_opts): """Declare a queue on an amqp session. 'session' is the amqp session to use 'callback' is the callback to call when messages are received 'node_name' is the first part of the Qpid address string, before ';' 'node_opts' will be applied to the "x-declare" section of "node" in the address string. 'link_name' goes into the "name" field of the "link" in the address string 'link_opts' will be applied to the "x-declare" section of "link" in the address string. """ self.callback = callback self.receiver = None self.session = None addr_opts = { "create": "always", "node": { "type": "topic", "x-declare": { "durable": True, "auto-delete": True, }, }, "link": { "name": link_name, "durable": True, "x-declare": { "durable": False, "auto-delete": True, "exclusive": False, }, }, } addr_opts["node"]["x-declare"].update(node_opts) addr_opts["link"]["x-declare"].update(link_opts) self.address = "%s ; %s" % (node_name, jsonutils.dumps(addr_opts)) self.reconnect(session)
def test_create_server_without_hints(self): @wsgi.response(202) def fake_create(*args, **kwargs): self.assertNotIn('scheduler_hints', kwargs['body']) return self.fake_instance self.stubs.Set(cinder.api.v2.volumes.VolumeController, 'create', fake_create) req = fakes.HTTPRequest.blank('/v2/fake/volumes') req.method = 'POST' req.content_type = 'application/json' body = { 'id': id, 'volume_type_id': 'cedef40a-ed67-4d10-800e-17455edce175', 'volume_id': '1', } req.body = jsonutils.dumps(body) res = req.get_response(self.app) self.assertEqual(202, res.status_int)
def test_invalid_reset_attached_status(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # current status is available volume = db.volume_create(ctx, {'status': 'available', 'attach_status': 'detached'}) req = webob.Request.blank('/v2/fake/volumes/%s/action' % volume['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # 'invalid' is not a valid attach_status body = {'os-reset_status': {'status': 'available', 'attach_status': 'invalid'}} req.body = jsonutils.dumps(body) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # bad request self.assertEquals(resp.status_int, 400) volume = db.volume_get(ctx, volume['id']) # status and attach_status un-modified self.assertEquals(volume['status'], 'available') self.assertEquals(volume['attach_status'], 'detached')
def test_invalid_status_for_snapshot(self): # admin context ctx = context.RequestContext('admin', 'fake', True) # snapshot in 'available' volume = db.volume_create(ctx, {}) snapshot = db.snapshot_create(ctx, {'status': 'available', 'volume_id': volume['id']}) req = webob.Request.blank('/v2/fake/snapshots/%s/action' % snapshot['id']) req.method = 'POST' req.headers['content-type'] = 'application/json' # 'attaching' is not a valid status for snapshots req.body = jsonutils.dumps({'os-reset_status': {'status': 'attaching'}}) # attach admin context to request req.environ['cinder.context'] = ctx resp = req.get_response(app()) # request is accepted self.assertEquals(resp.status_int, 400) snapshot = db.snapshot_get(ctx, snapshot['id']) # status is still 'available' self.assertEquals(snapshot['status'], 'available')
def test_create_with_keys_in_uppercase_and_lowercase(self): # if the keys in uppercase_and_lowercase, should return the one # which server added self.stubs.Set(cinder.db, 'snapshot_metadata_get', return_empty_snapshot_metadata) self.stubs.Set(cinder.db, 'snapshot_metadata_update', return_create_snapshot_metadata_insensitive) req = fakes.HTTPRequest.blank('/v1/snapshot_metadata') req.method = 'POST' req.content_type = "application/json" body = {"metadata": {"key1": "value1", "KEY1": "value1", "key2": "value2", "KEY2": "value2", "key3": "value3", "KEY4": "value4"}} expected = {"metadata": {"key1": "value1", "key2": "value2", "key3": "value3", "KEY4": "value4"}} req.body = jsonutils.dumps(body) res_dict = self.controller.create(req, self.req_id, body) self.assertEqual(expected, res_dict)
def test_put_metadata(self): metadata = {'version': 1} self.driver.put_metadata(self.volume_id, jsonutils.dumps(metadata))
def test_put_invalid_version(self): container = jsonutils.dumps({'version': 2}) self.assertRaises(exception.BackupMetadataUnsupportedVersion, self.bak_meta_api.put, self.volume_id, container)
def _json_dumps(properties, attr): prop = properties[attr] if not isinstance(prop, basestring): properties[attr] = jsonutils.dumps(prop)
def _request_data(self, verb, path): """Get data decribing a limit request verb/path.""" return jsonutils.dumps({"verb": verb, "path": path})
def esm_command(self, request): request['data'] = jsonutils.dumps(request['data']) return self.configure([request])
def test_is_serializable(self): data = {'foo': 'bar'} if self.bak_meta_api._is_serializable(data): jsonutils.dumps(data)