]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/rgw_multi/multisite.py
1 from abc
import ABCMeta
, abstractmethod
2 from cStringIO
import StringIO
5 from conn
import get_gateway_connection
8 """ interface to run commands against a distinct ceph cluster """
9 __metaclass__
= ABCMeta
12 def admin(self
, args
= None, **kwargs
):
13 """ execute a radosgw-admin command """
17 """ interface to control a single radosgw instance """
18 __metaclass__
= ABCMeta
20 def __init__(self
, host
= None, port
= None, cluster
= None, zone
= None, proto
= 'http', connection
= None):
23 self
.cluster
= cluster
26 self
.connection
= connection
29 def start(self
, args
= []):
30 """ start the gateway with the given args """
35 """ stop the gateway """
39 return '%s://%s:%d' % (self
.proto
, self
.host
, self
.port
)
42 """ interface for system objects, represented in json format and
43 manipulated with radosgw-admin commands """
44 __metaclass__
= ABCMeta
46 def __init__(self
, data
= None, uuid
= None):
50 self
.load_from_json(data
)
53 def build_command(self
, command
):
54 """ return the command line for the given command, including arguments
55 to specify this object """
59 def load_from_json(self
, data
):
60 """ update internal state based on json data """
63 def command(self
, cluster
, cmd
, args
= None, **kwargs
):
64 """ run the given command and return the output and retcode """
65 args
= self
.build_command(cmd
) + (args
or [])
66 return cluster
.admin(args
, **kwargs
)
68 def json_command(self
, cluster
, cmd
, args
= None, **kwargs
):
69 """ run the given command, parse the output and return the resulting
71 s
, r
= self
.command(cluster
, cmd
, args
or [], **kwargs
)
73 output
= s
.decode('utf-8')
74 output
= output
[output
.find('{'):] # trim extra output before json
75 data
= json
.loads(output
)
76 self
.load_from_json(data
)
80 # mixins for supported commands
82 def create(self
, cluster
, args
= None, **kwargs
):
83 """ create the object with the given arguments """
84 return self
.json_command(cluster
, 'create', args
, **kwargs
)
87 def delete(self
, cluster
, args
= None, **kwargs
):
88 """ delete the object """
89 # not json_command() because delete has no output
90 _
, r
= self
.command(cluster
, 'delete', args
, **kwargs
)
96 def get(self
, cluster
, args
= None, **kwargs
):
97 """ read the object from storage """
98 kwargs
['read_only'] = True
99 return self
.json_command(cluster
, 'get', args
, **kwargs
)
102 def set(self
, cluster
, data
, args
= None, **kwargs
):
103 """ set the object by json """
104 kwargs
['stdin'] = StringIO(json
.dumps(data
))
105 return self
.json_command(cluster
, 'set', args
, **kwargs
)
107 class Modify(object):
108 def modify(self
, cluster
, args
= None, **kwargs
):
109 """ modify the object with the given arguments """
110 return self
.json_command(cluster
, 'modify', args
, **kwargs
)
112 class CreateDelete(Create
, Delete
): pass
113 class GetSet(Get
, Set
): pass
115 class Zone(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
116 def __init__(self
, name
, zonegroup
= None, cluster
= None, data
= None, zone_id
= None, gateways
= None):
118 self
.zonegroup
= zonegroup
119 self
.cluster
= cluster
120 self
.gateways
= gateways
or []
121 super(Zone
, self
).__init
__(data
, zone_id
)
124 """ command-line argument to specify this zone """
125 return ['--rgw-zone', self
.name
]
128 """ command-line arguments to specify this zone/zonegroup/realm """
129 args
= self
.zone_arg()
131 args
+= self
.zonegroup
.zonegroup_args()
134 def build_command(self
, command
):
135 """ build a command line for the given command and args """
136 return ['zone', command
] + self
.zone_args()
138 def load_from_json(self
, data
):
139 """ load the zone from json """
141 self
.name
= data
['name']
143 def start(self
, args
= None):
144 """ start all gateways """
145 for g
in self
.gateways
:
149 """ stop all gateways """
150 for g
in self
.gateways
:
154 return self
.zonegroup
.period
if self
.zonegroup
else None
157 return self
.zonegroup
.realm() if self
.zonegroup
else None
159 def is_read_only(self
):
163 raise NotImplementedError
165 def has_buckets(self
):
168 def get_conn(self
, credentials
):
169 return ZoneConn(self
, credentials
) # not implemented, but can be used
171 class ZoneConn(object):
172 def __init__(self
, zone
, credentials
):
174 self
.name
= zone
.name
175 """ connect to the zone's first gateway """
176 if isinstance(credentials
, list):
177 self
.credentials
= credentials
[0]
179 self
.credentials
= credentials
181 if self
.zone
.gateways
is not None:
182 self
.conn
= get_gateway_connection(self
.zone
.gateways
[0], self
.credentials
)
184 def get_connection(self
):
187 def get_bucket(self
, bucket_name
, credentials
):
188 raise NotImplementedError
190 def check_bucket_eq(self
, zone
, bucket_name
):
191 raise NotImplementedError
193 class ZoneGroup(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
194 def __init__(self
, name
, period
= None, data
= None, zonegroup_id
= None, zones
= None, master_zone
= None):
197 self
.zones
= zones
or []
198 self
.master_zone
= master_zone
199 super(ZoneGroup
, self
).__init
__(data
, zonegroup_id
)
202 self
.zones_by_type
= {}
205 self
.ro_zones
.append(z
)
207 self
.rw_zones
.append(z
)
209 def zonegroup_arg(self
):
210 """ command-line argument to specify this zonegroup """
211 return ['--rgw-zonegroup', self
.name
]
213 def zonegroup_args(self
):
214 """ command-line arguments to specify this zonegroup/realm """
215 args
= self
.zonegroup_arg()
218 args
+= realm
.realm_arg()
221 def build_command(self
, command
):
222 """ build a command line for the given command and args """
223 return ['zonegroup', command
] + self
.zonegroup_args()
225 def zone_by_id(self
, zone_id
):
226 """ return the matching zone by id """
227 for zone
in self
.zones
:
228 if zone
.id == zone_id
:
232 def load_from_json(self
, data
):
233 """ load the zonegroup from json """
235 self
.name
= data
['name']
236 master_id
= data
['master_zone']
237 if not self
.master_zone
or master_id
!= self
.master_zone
.id:
238 self
.master_zone
= self
.zone_by_id(master_id
)
240 def add(self
, cluster
, zone
, args
= None, **kwargs
):
241 """ add an existing zone to the zonegroup """
242 args
= zone
.zone_arg() + (args
or [])
243 data
, r
= self
.json_command(cluster
, 'add', args
, **kwargs
)
245 zone
.zonegroup
= self
246 self
.zones
.append(zone
)
249 def remove(self
, cluster
, zone
, args
= None, **kwargs
):
250 """ remove an existing zone from the zonegroup """
251 args
= zone
.zone_arg() + (args
or [])
252 data
, r
= self
.json_command(cluster
, 'remove', args
, **kwargs
)
254 zone
.zonegroup
= None
255 self
.zones
.remove(zone
)
259 return self
.period
.realm
if self
.period
else None
261 class Period(SystemObject
, SystemObject
.Get
):
262 def __init__(self
, realm
= None, data
= None, period_id
= None, zonegroups
= None, master_zonegroup
= None):
264 self
.zonegroups
= zonegroups
or []
265 self
.master_zonegroup
= master_zonegroup
266 super(Period
, self
).__init
__(data
, period_id
)
268 def zonegroup_by_id(self
, zonegroup_id
):
269 """ return the matching zonegroup by id """
270 for zonegroup
in self
.zonegroups
:
271 if zonegroup
.id == zonegroup_id
:
275 def build_command(self
, command
):
276 """ build a command line for the given command and args """
277 return ['period', command
]
279 def load_from_json(self
, data
):
280 """ load the period from json """
282 master_id
= data
['master_zonegroup']
283 if not self
.master_zonegroup
or master_id
!= self
.master_zonegroup
.id:
284 self
.master_zonegroup
= self
.zonegroup_by_id(master_id
)
286 def update(self
, zone
, args
= None, **kwargs
):
287 """ run 'radosgw-admin period update' on the given zone """
289 args
= zone
.zone_args() + (args
or [])
290 if kwargs
.pop('commit', False):
291 args
.append('--commit')
292 return self
.json_command(zone
.cluster
, 'update', args
, **kwargs
)
294 def commit(self
, zone
, args
= None, **kwargs
):
295 """ run 'radosgw-admin period commit' on the given zone """
297 args
= zone
.zone_args() + (args
or [])
298 return self
.json_command(zone
.cluster
, 'commit', args
, **kwargs
)
300 class Realm(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
):
301 def __init__(self
, name
, period
= None, data
= None, realm_id
= None):
303 self
.current_period
= period
304 super(Realm
, self
).__init
__(data
, realm_id
)
307 """ return the command-line arguments that specify this realm """
308 return ['--rgw-realm', self
.name
]
310 def build_command(self
, command
):
311 """ build a command line for the given command and args """
312 return ['realm', command
] + self
.realm_arg()
314 def load_from_json(self
, data
):
315 """ load the realm from json """
318 def pull(self
, cluster
, gateway
, credentials
, args
= [], **kwargs
):
319 """ pull an existing realm from the given gateway """
320 args
+= ['--url', gateway
.endpoint()]
321 args
+= credentials
.credential_args()
322 return self
.json_command(cluster
, 'pull', args
, **kwargs
)
324 def master_zonegroup(self
):
325 """ return the current period's master zonegroup """
326 if self
.current_period
is None:
328 return self
.current_period
.master_zonegroup
330 def meta_master_zone(self
):
331 """ return the current period's metadata master zone """
332 zonegroup
= self
.master_zonegroup()
333 if zonegroup
is None:
335 return zonegroup
.master_zone
338 def __init__(self
, access_key
, secret
):
339 self
.access_key
= access_key
342 def credential_args(self
):
343 return ['--access-key', self
.access_key
, '--secret', self
.secret
]
345 class User(SystemObject
):
346 def __init__(self
, uid
, data
= None, name
= None, credentials
= None):
348 self
.credentials
= credentials
or []
349 super(User
, self
).__init
__(data
, uid
)
352 """ command-line argument to specify this user """
353 return ['--uid', self
.id]
355 def build_command(self
, command
):
356 """ build a command line for the given command and args """
357 return ['user', command
] + self
.user_arg()
359 def load_from_json(self
, data
):
360 """ load the user from json """
361 self
.id = data
['user_id']
362 self
.name
= data
['display_name']
363 self
.credentials
= [Credentials(k
['access_key'], k
['secret_key']) for k
in data
['keys']]
365 def create(self
, zone
, args
= None, **kwargs
):
366 """ create the user with the given arguments """
368 args
= zone
.zone_args() + (args
or [])
369 return self
.json_command(zone
.cluster
, 'create', args
, **kwargs
)
371 def info(self
, zone
, args
= None, **kwargs
):
372 """ read the user from storage """
374 args
= zone
.zone_args() + (args
or [])
375 kwargs
['read_only'] = True
376 return self
.json_command(zone
.cluster
, 'info', args
, **kwargs
)
378 def delete(self
, zone
, args
= None, **kwargs
):
379 """ delete the user """
381 args
= zone
.zone_args() + (args
or [])
382 return self
.command(zone
.cluster
, 'delete', args
, **kwargs
)