]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/rgw_multi/multisite.py
1 from abc
import ABCMeta
, abstractmethod
2 from six
import StringIO
6 from .conn
import get_gateway_connection
9 """ interface to run commands against a distinct ceph cluster """
10 __metaclass__
= ABCMeta
13 def admin(self
, args
= None, **kwargs
):
14 """ execute a radosgw-admin command """
18 """ interface to control a single radosgw instance """
19 __metaclass__
= ABCMeta
21 def __init__(self
, host
= None, port
= None, cluster
= None, zone
= None, proto
= 'http', connection
= None):
24 self
.cluster
= cluster
27 self
.connection
= connection
30 def start(self
, args
= []):
31 """ start the gateway with the given args """
36 """ stop the gateway """
40 return '%s://%s:%d' % (self
.proto
, self
.host
, self
.port
)
43 """ interface for system objects, represented in json format and
44 manipulated with radosgw-admin commands """
45 __metaclass__
= ABCMeta
47 def __init__(self
, data
= None, uuid
= None):
51 self
.load_from_json(data
)
54 def build_command(self
, command
):
55 """ return the command line for the given command, including arguments
56 to specify this object """
60 def load_from_json(self
, data
):
61 """ update internal state based on json data """
64 def command(self
, cluster
, cmd
, args
= None, **kwargs
):
65 """ run the given command and return the output and retcode """
66 args
= self
.build_command(cmd
) + (args
or [])
67 return cluster
.admin(args
, **kwargs
)
69 def json_command(self
, cluster
, cmd
, args
= None, **kwargs
):
70 """ run the given command, parse the output and return the resulting
72 s
, r
= self
.command(cluster
, cmd
, args
or [], **kwargs
)
74 output
= s
.decode('utf-8')
75 output
= output
[output
.find('{'):] # trim extra output before json
76 data
= json
.loads(output
)
77 self
.load_from_json(data
)
81 # mixins for supported commands
83 def create(self
, cluster
, args
= None, **kwargs
):
84 """ create the object with the given arguments """
85 return self
.json_command(cluster
, 'create', args
, **kwargs
)
88 def delete(self
, cluster
, args
= None, **kwargs
):
89 """ delete the object """
90 # not json_command() because delete has no output
91 _
, r
= self
.command(cluster
, 'delete', args
, **kwargs
)
97 def get(self
, cluster
, args
= None, **kwargs
):
98 """ read the object from storage """
99 kwargs
['read_only'] = True
100 return self
.json_command(cluster
, 'get', args
, **kwargs
)
103 def set(self
, cluster
, data
, args
= None, **kwargs
):
104 """ set the object by json """
105 kwargs
['stdin'] = StringIO(json
.dumps(data
))
106 return self
.json_command(cluster
, 'set', args
, **kwargs
)
108 class Modify(object):
109 def modify(self
, cluster
, args
= None, **kwargs
):
110 """ modify the object with the given arguments """
111 return self
.json_command(cluster
, 'modify', args
, **kwargs
)
113 class CreateDelete(Create
, Delete
): pass
114 class GetSet(Get
, Set
): pass
116 class Zone(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
117 def __init__(self
, name
, zonegroup
= None, cluster
= None, data
= None, zone_id
= None, gateways
= None):
119 self
.zonegroup
= zonegroup
120 self
.cluster
= cluster
121 self
.gateways
= gateways
or []
122 super(Zone
, self
).__init
__(data
, zone_id
)
125 """ command-line argument to specify this zone """
126 return ['--rgw-zone', self
.name
]
129 """ command-line arguments to specify this zone/zonegroup/realm """
130 args
= self
.zone_arg()
132 args
+= self
.zonegroup
.zonegroup_args()
135 def build_command(self
, command
):
136 """ build a command line for the given command and args """
137 return ['zone', command
] + self
.zone_args()
139 def load_from_json(self
, data
):
140 """ load the zone from json """
142 self
.name
= data
['name']
144 def start(self
, args
= None):
145 """ start all gateways """
146 for g
in self
.gateways
:
150 """ stop all gateways """
151 for g
in self
.gateways
:
155 return self
.zonegroup
.period
if self
.zonegroup
else None
158 return self
.zonegroup
.realm() if self
.zonegroup
else None
160 def is_read_only(self
):
164 raise NotImplementedError
166 def has_buckets(self
):
169 def get_conn(self
, credentials
):
170 return ZoneConn(self
, credentials
) # not implemented, but can be used
172 class ZoneConn(object):
173 def __init__(self
, zone
, credentials
):
175 self
.name
= zone
.name
176 """ connect to the zone's first gateway """
177 if isinstance(credentials
, list):
178 self
.credentials
= credentials
[0]
180 self
.credentials
= credentials
182 if self
.zone
.gateways
is not None:
183 self
.conn
= get_gateway_connection(self
.zone
.gateways
[0], self
.credentials
)
185 def get_connection(self
):
188 def get_bucket(self
, bucket_name
, credentials
):
189 raise NotImplementedError
191 def check_bucket_eq(self
, zone
, bucket_name
):
192 raise NotImplementedError
194 class ZoneGroup(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
195 def __init__(self
, name
, period
= None, data
= None, zonegroup_id
= None, zones
= None, master_zone
= None):
198 self
.zones
= zones
or []
199 self
.master_zone
= master_zone
200 super(ZoneGroup
, self
).__init
__(data
, zonegroup_id
)
203 self
.zones_by_type
= {}
206 self
.ro_zones
.append(z
)
208 self
.rw_zones
.append(z
)
210 def zonegroup_arg(self
):
211 """ command-line argument to specify this zonegroup """
212 return ['--rgw-zonegroup', self
.name
]
214 def zonegroup_args(self
):
215 """ command-line arguments to specify this zonegroup/realm """
216 args
= self
.zonegroup_arg()
219 args
+= realm
.realm_arg()
222 def build_command(self
, command
):
223 """ build a command line for the given command and args """
224 return ['zonegroup', command
] + self
.zonegroup_args()
226 def zone_by_id(self
, zone_id
):
227 """ return the matching zone by id """
228 for zone
in self
.zones
:
229 if zone
.id == zone_id
:
233 def load_from_json(self
, data
):
234 """ load the zonegroup from json """
236 self
.name
= data
['name']
237 master_id
= data
['master_zone']
238 if not self
.master_zone
or master_id
!= self
.master_zone
.id:
239 self
.master_zone
= self
.zone_by_id(master_id
)
241 def add(self
, cluster
, zone
, args
= None, **kwargs
):
242 """ add an existing zone to the zonegroup """
243 args
= zone
.zone_arg() + (args
or [])
244 data
, r
= self
.json_command(cluster
, 'add', args
, **kwargs
)
246 zone
.zonegroup
= self
247 self
.zones
.append(zone
)
250 def remove(self
, cluster
, zone
, args
= None, **kwargs
):
251 """ remove an existing zone from the zonegroup """
252 args
= zone
.zone_arg() + (args
or [])
253 data
, r
= self
.json_command(cluster
, 'remove', args
, **kwargs
)
255 zone
.zonegroup
= None
256 self
.zones
.remove(zone
)
260 return self
.period
.realm
if self
.period
else None
262 class Period(SystemObject
, SystemObject
.Get
):
263 def __init__(self
, realm
= None, data
= None, period_id
= None, zonegroups
= None, master_zonegroup
= None):
265 self
.zonegroups
= zonegroups
or []
266 self
.master_zonegroup
= master_zonegroup
267 super(Period
, self
).__init
__(data
, period_id
)
269 def zonegroup_by_id(self
, zonegroup_id
):
270 """ return the matching zonegroup by id """
271 for zonegroup
in self
.zonegroups
:
272 if zonegroup
.id == zonegroup_id
:
276 def build_command(self
, command
):
277 """ build a command line for the given command and args """
278 return ['period', command
]
280 def load_from_json(self
, data
):
281 """ load the period from json """
283 master_id
= data
['master_zonegroup']
284 if not self
.master_zonegroup
or master_id
!= self
.master_zonegroup
.id:
285 self
.master_zonegroup
= self
.zonegroup_by_id(master_id
)
287 def update(self
, zone
, args
= None, **kwargs
):
288 """ run 'radosgw-admin period update' on the given zone """
290 args
= zone
.zone_args() + (args
or [])
291 if kwargs
.pop('commit', False):
292 args
.append('--commit')
293 return self
.json_command(zone
.cluster
, 'update', args
, **kwargs
)
295 def commit(self
, zone
, args
= None, **kwargs
):
296 """ run 'radosgw-admin period commit' on the given zone """
298 args
= zone
.zone_args() + (args
or [])
299 return self
.json_command(zone
.cluster
, 'commit', args
, **kwargs
)
301 class Realm(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
):
302 def __init__(self
, name
, period
= None, data
= None, realm_id
= None):
304 self
.current_period
= period
305 super(Realm
, self
).__init
__(data
, realm_id
)
308 """ return the command-line arguments that specify this realm """
309 return ['--rgw-realm', self
.name
]
311 def build_command(self
, command
):
312 """ build a command line for the given command and args """
313 return ['realm', command
] + self
.realm_arg()
315 def load_from_json(self
, data
):
316 """ load the realm from json """
319 def pull(self
, cluster
, gateway
, credentials
, args
= [], **kwargs
):
320 """ pull an existing realm from the given gateway """
321 args
+= ['--url', gateway
.endpoint()]
322 args
+= credentials
.credential_args()
323 return self
.json_command(cluster
, 'pull', args
, **kwargs
)
325 def master_zonegroup(self
):
326 """ return the current period's master zonegroup """
327 if self
.current_period
is None:
329 return self
.current_period
.master_zonegroup
331 def meta_master_zone(self
):
332 """ return the current period's metadata master zone """
333 zonegroup
= self
.master_zonegroup()
334 if zonegroup
is None:
336 return zonegroup
.master_zone
339 def __init__(self
, access_key
, secret
):
340 self
.access_key
= access_key
343 def credential_args(self
):
344 return ['--access-key', self
.access_key
, '--secret', self
.secret
]
346 class User(SystemObject
):
347 def __init__(self
, uid
, data
= None, name
= None, credentials
= None, tenant
= None):
349 self
.credentials
= credentials
or []
351 super(User
, self
).__init
__(data
, uid
)
354 """ command-line argument to specify this user """
355 args
= ['--uid', self
.id]
357 args
+= ['--tenant', self
.tenant
]
360 def build_command(self
, command
):
361 """ build a command line for the given command and args """
362 return ['user', command
] + self
.user_arg()
364 def load_from_json(self
, data
):
365 """ load the user from json """
366 self
.id = data
['user_id']
367 self
.name
= data
['display_name']
368 self
.credentials
= [Credentials(k
['access_key'], k
['secret_key']) for k
in data
['keys']]
370 def create(self
, zone
, args
= None, **kwargs
):
371 """ create the user with the given arguments """
373 args
= zone
.zone_args() + (args
or [])
374 return self
.json_command(zone
.cluster
, 'create', args
, **kwargs
)
376 def info(self
, zone
, args
= None, **kwargs
):
377 """ read the user from storage """
379 args
= zone
.zone_args() + (args
or [])
380 kwargs
['read_only'] = True
381 return self
.json_command(zone
.cluster
, 'info', args
, **kwargs
)
383 def delete(self
, zone
, args
= None, **kwargs
):
384 """ delete the user """
386 args
= zone
.zone_args() + (args
or [])
387 return self
.command(zone
.cluster
, 'delete', args
, **kwargs
)