]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/rgw/rgw_multi/multisite.py
3f8b727bbe8b5be6a69a839874c05c609213b7e2
1 from abc
import ABCMeta
, abstractmethod
5 """ interface to run commands against a distinct ceph cluster """
6 __metaclass__
= ABCMeta
9 def admin(self
, args
= None, **kwargs
):
10 """ execute a radosgw-admin command """
14 """ interface to control a single radosgw instance """
15 __metaclass__
= ABCMeta
17 def __init__(self
, host
= None, port
= None, cluster
= None, zone
= None, proto
= 'http', connection
= None):
20 self
.cluster
= cluster
23 self
.connection
= connection
26 def start(self
, args
= []):
27 """ start the gateway with the given args """
32 """ stop the gateway """
36 return '%s://%s:%d' % (self
.proto
, self
.host
, self
.port
)
39 """ interface for system objects, represented in json format and
40 manipulated with radosgw-admin commands """
41 __metaclass__
= ABCMeta
43 def __init__(self
, data
= None, uuid
= None):
47 self
.load_from_json(data
)
50 def build_command(self
, command
):
51 """ return the command line for the given command, including arguments
52 to specify this object """
56 def load_from_json(self
, data
):
57 """ update internal state based on json data """
60 def command(self
, cluster
, cmd
, args
= None, **kwargs
):
61 """ run the given command and return the output and retcode """
62 args
= self
.build_command(cmd
) + (args
or [])
63 return cluster
.admin(args
, **kwargs
)
65 def json_command(self
, cluster
, cmd
, args
= None, **kwargs
):
66 """ run the given command, parse the output and return the resulting
68 (s
, r
) = self
.command(cluster
, cmd
, args
or [], **kwargs
)
70 output
= s
.decode('utf-8')
71 output
= output
[output
.find('{'):] # trim extra output before json
72 data
= json
.loads(output
)
73 self
.load_from_json(data
)
77 # mixins for supported commands
79 def create(self
, cluster
, args
= None, **kwargs
):
80 """ create the object with the given arguments """
81 return self
.json_command(cluster
, 'create', args
, **kwargs
)
84 def delete(self
, cluster
, args
= None, **kwargs
):
85 """ delete the object """
86 # not json_command() because delete has no output
87 (_
, r
) = self
.command(cluster
, 'delete', args
, **kwargs
)
93 def get(self
, cluster
, args
= None, **kwargs
):
94 """ read the object from storage """
95 kwargs
['read_only'] = True
96 return self
.json_command(cluster
, 'get', args
, **kwargs
)
99 def set(self
, cluster
, data
, args
= None, **kwargs
):
100 """ set the object by json """
101 kwargs
['stdin'] = StringIO(json
.dumps(data
))
102 return self
.json_command(cluster
, 'set', args
, **kwargs
)
104 class Modify(object):
105 def modify(self
, cluster
, args
= None, **kwargs
):
106 """ modify the object with the given arguments """
107 return self
.json_command(cluster
, 'modify', args
, **kwargs
)
109 class CreateDelete(Create
, Delete
): pass
110 class GetSet(Get
, Set
): pass
112 class Zone(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
113 def __init__(self
, name
, zonegroup
= None, cluster
= None, data
= None, zone_id
= None, gateways
= None):
115 self
.zonegroup
= zonegroup
116 self
.cluster
= cluster
117 self
.gateways
= gateways
or []
118 super(Zone
, self
).__init
__(data
, zone_id
)
121 """ command-line argument to specify this zone """
122 return ['--rgw-zone', self
.name
]
125 """ command-line arguments to specify this zone/zonegroup/realm """
126 args
= self
.zone_arg()
128 args
+= self
.zonegroup
.zonegroup_args()
131 def build_command(self
, command
):
132 """ build a command line for the given command and args """
133 return ['zone', command
] + self
.zone_args()
135 def load_from_json(self
, data
):
136 """ load the zone from json """
138 self
.name
= data
['name']
140 def start(self
, args
= None):
141 """ start all gateways """
142 for g
in self
.gateways
:
146 """ stop all gateways """
147 for g
in self
.gateways
:
151 return self
.zonegroup
.period
if self
.zonegroup
else None
154 return self
.zonegroup
.realm() if self
.zonegroup
else None
156 class ZoneGroup(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
, SystemObject
.Modify
):
157 def __init__(self
, name
, period
= None, data
= None, zonegroup_id
= None, zones
= None, master_zone
= None):
160 self
.zones
= zones
or []
161 self
.master_zone
= master_zone
162 super(ZoneGroup
, self
).__init
__(data
, zonegroup_id
)
164 def zonegroup_arg(self
):
165 """ command-line argument to specify this zonegroup """
166 return ['--rgw-zonegroup', self
.name
]
168 def zonegroup_args(self
):
169 """ command-line arguments to specify this zonegroup/realm """
170 args
= self
.zonegroup_arg()
173 args
+= realm
.realm_arg()
176 def build_command(self
, command
):
177 """ build a command line for the given command and args """
178 return ['zonegroup', command
] + self
.zonegroup_args()
180 def zone_by_id(self
, zone_id
):
181 """ return the matching zone by id """
182 for zone
in self
.zones
:
183 if zone
.id == zone_id
:
187 def load_from_json(self
, data
):
188 """ load the zonegroup from json """
190 self
.name
= data
['name']
191 master_id
= data
['master_zone']
192 if not self
.master_zone
or master_id
!= self
.master_zone
.id:
193 self
.master_zone
= self
.zone_by_id(master_id
)
195 def add(self
, cluster
, zone
, args
= None, **kwargs
):
196 """ add an existing zone to the zonegroup """
197 args
= zone
.zone_arg() + (args
or [])
198 (data
, r
) = self
.json_command(cluster
, 'add', args
, **kwargs
)
200 zone
.zonegroup
= self
201 self
.zones
.append(zone
)
204 def remove(self
, cluster
, zone
, args
= None, **kwargs
):
205 """ remove an existing zone from the zonegroup """
206 args
= zone
.zone_arg() + (args
or [])
207 (data
, r
) = self
.json_command(cluster
, 'remove', args
, **kwargs
)
209 zone
.zonegroup
= None
210 self
.zones
.remove(zone
)
214 return self
.period
.realm
if self
.period
else None
216 class Period(SystemObject
, SystemObject
.Get
):
217 def __init__(self
, realm
= None, data
= None, period_id
= None, zonegroups
= None, master_zonegroup
= None):
219 self
.zonegroups
= zonegroups
or []
220 self
.master_zonegroup
= master_zonegroup
221 super(Period
, self
).__init
__(data
, period_id
)
223 def zonegroup_by_id(self
, zonegroup_id
):
224 """ return the matching zonegroup by id """
225 for zonegroup
in self
.zonegroups
:
226 if zonegroup
.id == zonegroup_id
:
230 def build_command(self
, command
):
231 """ build a command line for the given command and args """
232 return ['period', command
]
234 def load_from_json(self
, data
):
235 """ load the period from json """
237 master_id
= data
['master_zonegroup']
238 if not self
.master_zonegroup
or master_id
!= self
.master_zonegroup
.id:
239 self
.master_zonegroup
= self
.zonegroup_by_id(master_id
)
241 def update(self
, zone
, args
= None, **kwargs
):
242 """ run 'radosgw-admin period update' on the given zone """
244 args
= zone
.zone_args() + (args
or [])
245 if kwargs
.pop('commit', False):
246 args
.append('--commit')
247 return self
.json_command(zone
.cluster
, 'update', args
, **kwargs
)
249 def commit(self
, zone
, args
= None, **kwargs
):
250 """ run 'radosgw-admin period commit' on the given zone """
252 args
= zone
.zone_args() + (args
or [])
253 return self
.json_command(zone
.cluster
, 'commit', args
, **kwargs
)
255 class Realm(SystemObject
, SystemObject
.CreateDelete
, SystemObject
.GetSet
):
256 def __init__(self
, name
, period
= None, data
= None, realm_id
= None):
258 self
.current_period
= period
259 super(Realm
, self
).__init
__(data
, realm_id
)
262 """ return the command-line arguments that specify this realm """
263 return ['--rgw-realm', self
.name
]
265 def build_command(self
, command
):
266 """ build a command line for the given command and args """
267 return ['realm', command
] + self
.realm_arg()
269 def load_from_json(self
, data
):
270 """ load the realm from json """
273 def pull(self
, cluster
, gateway
, credentials
, args
= [], **kwargs
):
274 """ pull an existing realm from the given gateway """
275 args
+= ['--url', gateway
.endpoint()]
276 args
+= credentials
.credential_args()
277 return self
.json_command(cluster
, 'pull', args
, **kwargs
)
279 def master_zonegroup(self
):
280 """ return the current period's master zonegroup """
281 if self
.current_period
is None:
283 return self
.current_period
.master_zonegroup
285 def meta_master_zone(self
):
286 """ return the current period's metadata master zone """
287 zonegroup
= self
.master_zonegroup()
288 if zonegroup
is None:
290 return zonegroup
.master_zone
293 def __init__(self
, access_key
, secret
):
294 self
.access_key
= access_key
297 def credential_args(self
):
298 return ['--access-key', self
.access_key
, '--secret', self
.secret
]
300 class User(SystemObject
):
301 def __init__(self
, uid
, data
= None, name
= None, credentials
= None):
303 self
.credentials
= credentials
or []
304 super(User
, self
).__init
__(data
, uid
)
307 """ command-line argument to specify this user """
308 return ['--uid', self
.id]
310 def build_command(self
, command
):
311 """ build a command line for the given command and args """
312 return ['user', command
] + self
.user_arg()
314 def load_from_json(self
, data
):
315 """ load the user from json """
316 self
.id = data
['user_id']
317 self
.name
= data
['display_name']
318 self
.credentials
= [Credentials(k
['access_key'], k
['secret_key']) for k
in data
['keys']]
320 def create(self
, zone
, args
= None, **kwargs
):
321 """ create the user with the given arguments """
323 args
= zone
.zone_args() + (args
or [])
324 return self
.json_command(zone
.cluster
, 'create', args
, **kwargs
)
326 def info(self
, zone
, args
= None, **kwargs
):
327 """ read the user from storage """
329 args
= zone
.zone_args() + (args
or [])
330 kwargs
['read_only'] = True
331 return self
.json_command(zone
.cluster
, 'info', args
, **kwargs
)
333 def delete(self
, zone
, args
= None, **kwargs
):
334 """ delete the user """
336 args
= zone
.zone_args() + (args
or [])
337 return self
.command(zone
.cluster
, 'delete', args
, **kwargs
)