As of Ceph version 0.67 (Dumpling) the Ceph Object Gateway aka RADOS Gateway supports regions. This allows you to create a geo-replicated Amazon S3 compatible service.
While working on a setup we decided later in the process that we wanted regions, but we already created about 50 buckets with data in them. We didn’t feel like re-creating all the buckets, so we wanted to change the region of the buckets.
A fresh Object Gateway has a region ‘default’ with one zone ‘default’. We created the region ‘ams02’ (Amsterdam) with one zone called ‘zone01’.
All buckets had the region ‘default’ which we wanted to change to ‘ams02’. No data migrated is required since all the data is on the same Ceph cluster.
This can be done with a couple of ‘radosgw-admin’ commands.
The bucket in these examples is ‘widodh’.
$ radosgw-admin metadata get bucket:widodh
This outputs JSON data:
{ "key": "bucket:widodh", "ver": { "tag": "_2qGuaDCBixHpx2lddTe0g-x", "ver": 1}, "mtime": 1380653343, "data": { "bucket": { "name": "widodh", "pool": ".rgw.buckets", "index_pool": ".rgw.buckets.index", "marker": "default.20111.1", "bucket_id": "default.20111.1"}, "owner": "widodh", "creation_time": 1380653343, "linked": "true", "has_bucket_info": "false"}}
With this information we can get the rest of the information:
$ radosgw-admin metadata get bucket.instance:widodh:default.20111.1
The id at the end is ‘bucket_id’ from the previous command.
This returns us:
{ "key": "bucket.instance:widodh:default.20111.1", "ver": { "tag": "_-HNwyMLAnRALV9tyPqdX5_V", "ver": 1}, "mtime": 1380653343, "data": { "bucket_info": { "bucket": { "name": "widodh", "pool": ".rgw.buckets", "index_pool": ".rgw.buckets.index", "marker": "default.20111.1", "bucket_id": "default.20111.1"}, "creation_time": 1380653343, "owner": "widodh", "flags": 0, "region": "default", "placement_rule": "default-placement", "has_instance_obj": "true"}, "attrs": [ { "key": "user.rgw.acl", "val": "AgKXAAAAAgIgAAAABgAAAHdpZG9kaBIAAABXaWRvIGRlbiBIb2xsYW5kZXIDA2sAAAABAQAAAAYAAAB3aWRvZGgPAAAAAQAAAAYAAAB3aWRvZGgDA0AAAAACAgQAAAAAAAAABgAAAHdpZG9kaAAAAAAAAAAAAgIEAAAADwAAABIAAABXaWRvIGRlbiBIb2xsYW5kZXIAAAAAAAAAAA=="}, { "key": "user.rgw.idtag", "val": ""}, { "key": "user.rgw.manifest", "val": ""}]}}
Save this output to a file and change the ‘region’ value to what you want, in this case I changed ‘default’ to ‘ams02’.
Afterwards you run:
$ radosgw-admin metadata put bucket.instance:widodh:default.20111.1 < bucket.json
Now I could change these configuration variables in the ceph.conf:
[client.radosgw.rgw1] host = rgw1 ... ... rgw zone = zone01 rgw region = ams02 ... ...
We had to change the information of 50 buckets and we didn't feel like doing this manually, so I wrote this script:
#!/usr/bin/env python import rados import os import json import copy import subprocess ceph_id = "admin" ceph_secret = "ADMIN SECRET" ceph_monitor = "MONITOR ADDRESS" ceph_rgw_pool = ".rgw" ceph_rgw_region = "NEW RGW REGION" def change_bucket_region(bucket, region): me = os.popen("radosgw-admin metadata get bucket:" + bucket) meta = json.loads(me.read()) id = meta['data']['bucket']['bucket_id'] mei = os.popen("radosgw-admin metadata get bucket.instance:" + bucket + ":" + id) imeta = json.loads(mei.read()) region = imeta['data']['bucket_info']['region'] if region is not ceph_rgw_region: newmeta = copy.copy(imeta) newmeta['data']['bucket_info']['region'] = ceph_rgw_region stdin = json.dumps(newmeta) process = subprocess.Popen(['radosgw-admin', 'metadata', 'put', "bucket.instance:" + bucket + ":" + id], stdin=subprocess.PIPE, stdout=subprocess.PIPE) process.stdin.write(stdin) process.stdin.close() process.wait() try: r = rados.Rados(rados_id=ceph_id) r.conf_set("mon_host", ceph_monitor) r.conf_set("key", ceph_secret) r.connect() io = r.open_ioctx(ceph_rgw_pool) i = io.list_objects() while True: try: o = i.next() b = str(o.key) if b[0] is not ".": change_bucket_region(b, ceph_rgw_region) except StopIteration: break io.close() r.shutdown() except Exception as e: print "Error" + str(e)
Also available as a download.
Use this script with caution since it will change the region of ALL buckets on your cluster to what you specify.