Revision de73876b
b/kamaki/cli/__init__.py | ||
---|---|---|
57 | 57 |
spec = getargspec(cls.main.im_func) |
58 | 58 |
args = spec.args[1:] |
59 | 59 |
n = len(args) - len(spec.defaults or ()) |
60 |
required = ' '.join('<%s>' % x\ |
|
61 |
.replace('____', '[:')\ |
|
62 |
.replace('___', ':')\ |
|
63 |
.replace('__', ']').\ |
|
64 |
replace('_', ' ') for x in args[:n]) |
|
65 |
optional = ' '.join('[%s]' % x\ |
|
66 |
.replace('____', '[:')\ |
|
67 |
.replace('___', ':')\ |
|
68 |
.replace('__', ']').\ |
|
69 |
replace('_', ' ') for x in args[n:]) |
|
60 |
required = ' '.join( |
|
61 |
'<%s>' % x.replace( |
|
62 |
'____', '[:').replace( |
|
63 |
'___', ':').replace( |
|
64 |
'__', ']').replace( |
|
65 |
'_', ' ') for x in args[:n]) |
|
66 |
optional = ' '.join( |
|
67 |
'[%s]' % x.replace( |
|
68 |
'____', '[:').replace( |
|
69 |
'___', ':').replace( |
|
70 |
'__', ']').replace( |
|
71 |
'_', ' ') for x in args[n:]) |
|
70 | 72 |
cls.syntax = ' '.join(x for x in [required, optional] if x) |
71 | 73 |
if spec.varargs: |
72 | 74 |
cls.syntax += ' <%s ...>' % spec.varargs |
... | ... | |
144 | 146 |
kloger.warning('%s failed max_len test' % cls_name) |
145 | 147 |
return None |
146 | 148 |
|
147 |
cls.description, sep, cls.long_description\ |
|
148 |
= cls.__doc__.partition('\n') |
|
149 |
( |
|
150 |
cls.description, sep, cls.long_description |
|
151 |
) = cls.__doc__.partition('\n') |
|
149 | 152 |
_construct_command_syntax(cls) |
150 | 153 |
|
151 | 154 |
cmd_tree.add_command(cls_name, cls.description, cls) |
... | ... | |
240 | 243 |
cmds = None |
241 | 244 |
try: |
242 | 245 |
cmds = [ |
243 |
cmd for cmd in getattr(pkg, '_commands')\
|
|
244 |
if arguments['config'].get(cmd.name, 'cli') |
|
246 |
cmd for cmd in getattr(pkg, '_commands') |
|
247 |
if arguments['config'].get(cmd.name, 'cli')
|
|
245 | 248 |
] |
246 | 249 |
except AttributeError: |
247 | 250 |
if _debug: |
... | ... | |
260 | 263 |
|
261 | 264 |
def _load_all_commands(cmd_tree, arguments): |
262 | 265 |
_config = arguments['config'] |
263 |
for spec in [spec for spec in _config.get_groups()\
|
|
264 |
if _config.get(spec, 'cli')]:
|
|
266 |
for spec in [spec for spec in _config.get_groups() |
|
267 |
if _config.get(spec, 'cli')]: |
|
265 | 268 |
try: |
266 | 269 |
spec_module = _load_spec_module(spec, arguments, '_commands') |
267 | 270 |
spec_commands = getattr(spec_module, '_commands') |
... | ... | |
304 | 307 |
else: |
305 | 308 |
parser.syntax += ' <...>' |
306 | 309 |
if cmd.has_description: |
307 |
parser.parser.description = cmd.help\
|
|
308 |
+ (('\n%s' % description) if description else '')
|
|
310 |
parser.parser.description = cmd.help + (
|
|
311 |
('\n%s' % description) if description else '')
|
|
309 | 312 |
else: |
310 | 313 |
parser.parser.description = description |
311 | 314 |
|
b/kamaki/cli/argument.py | ||
---|---|---|
129 | 129 |
action = 'append' if self.arity < 0\ |
130 | 130 |
else 'store_true' if self.arity == 0\ |
131 | 131 |
else 'store' |
132 |
parser.add_argument(*self.parsed_name, dest=name, action=action, |
|
133 |
default=self.default, help=self.help) |
|
132 |
parser.add_argument( |
|
133 |
*self.parsed_name, |
|
134 |
dest=name, |
|
135 |
action=action, |
|
136 |
default=self.default, |
|
137 |
help=self.help) |
|
134 | 138 |
|
135 | 139 |
def main(self): |
136 | 140 |
"""Overide this method to give functionality to your args""" |
... | ... | |
189 | 193 |
for option in options: |
190 | 194 |
keypath, sep, val = option.partition('=') |
191 | 195 |
if not sep: |
192 |
raiseCLIError(CLISyntaxError('Argument Syntax Error '), |
|
196 |
raiseCLIError( |
|
197 |
CLISyntaxError('Argument Syntax Error '), |
|
193 | 198 |
details=['%s is missing a "="', |
194 | 199 |
' (usage: -o section.key=val)' % option] |
195 | 200 |
) |
... | ... | |
237 | 242 |
try: |
238 | 243 |
self._value = int(newvalue) |
239 | 244 |
except ValueError: |
240 |
raiseCLIError(CLISyntaxError('IntArgument Error', |
|
245 |
raiseCLIError( |
|
246 |
CLISyntaxError('IntArgument Error', |
|
241 | 247 |
details=['Value %s not an int' % newvalue])) |
242 | 248 |
|
243 | 249 |
|
... | ... | |
248 | 254 |
:value returns: same date in first of DATE_FORMATS |
249 | 255 |
""" |
250 | 256 |
|
251 |
DATE_FORMATS = ["%a %b %d %H:%M:%S %Y", |
|
257 |
DATE_FORMATS = [ |
|
258 |
"%a %b %d %H:%M:%S %Y", |
|
252 | 259 |
"%A, %d-%b-%y %H:%M:%S GMT", |
253 | 260 |
"%a, %d %b %Y %H:%M:%S GMT"] |
254 | 261 |
|
... | ... | |
272 | 279 |
continue |
273 | 280 |
self._value = t.strftime(self.DATE_FORMATS[0]) |
274 | 281 |
return |
275 |
raiseCLIError(None, |
|
282 |
raiseCLIError( |
|
283 |
None, |
|
276 | 284 |
'Date Argument Error', |
277 | 285 |
details='%s not a valid date. correct formats:\n\t%s'\ |
278 | 286 |
% (datestr, self.INPUT_FORMATS)) |
... | ... | |
321 | 329 |
for pair in keyvalue_pairs: |
322 | 330 |
key, sep, val = pair.partition('=') |
323 | 331 |
if not sep: |
324 |
raiseCLIError(CLISyntaxError('Argument syntax error '), |
|
332 |
raiseCLIError( |
|
333 |
CLISyntaxError('Argument syntax error '), |
|
325 | 334 |
details='%s is missing a "=" (usage: key1=val1 )\n' % pair) |
326 | 335 |
self._value[key.strip()] = val.strip() |
327 | 336 |
|
... | ... | |
374 | 383 |
mybar.finish() |
375 | 384 |
|
376 | 385 |
|
377 |
_arguments = dict(config=_config_arg, |
|
386 |
_arguments = dict( |
|
387 |
config=_config_arg, |
|
378 | 388 |
help=Argument(0, 'Show help message', ('-h', '--help')), |
379 | 389 |
debug=FlagArgument('Include debug output', ('-d', '--debug')), |
380 |
include=FlagArgument('Include raw connection data in the output', |
|
390 |
include=FlagArgument( |
|
391 |
'Include raw connection data in the output', |
|
381 | 392 |
('-i', '--include')), |
382 | 393 |
silent=FlagArgument('Do not output anything', ('-s', '--silent')), |
383 | 394 |
verbose=FlagArgument('More info at response', ('-v', '--verbose')), |
384 | 395 |
version=VersionArgument('Print current version', ('-V', '--version')), |
385 |
options=CmdLineConfigArgument(_config_arg, |
|
396 |
options=CmdLineConfigArgument( |
|
397 |
_config_arg, |
|
386 | 398 |
'Override a config value', |
387 | 399 |
('-o', '--options')) |
388 | 400 |
) |
... | ... | |
416 | 428 |
:param arguments: (dict) if given, overrides the global _argument as |
417 | 429 |
the parsers arguments specification |
418 | 430 |
""" |
419 |
self.parser = ArgumentParser(add_help=False, |
|
431 |
self.parser = ArgumentParser( |
|
432 |
add_help=False, |
|
420 | 433 |
formatter_class=RawDescriptionHelpFormatter) |
421 | 434 |
self.syntax = '%s <cmd_group> [<cmd_subbroup> ...] <cmd>' % exe |
422 | 435 |
if arguments: |
b/kamaki/cli/command_shell.py | ||
---|---|---|
79 | 79 |
|
80 | 80 |
def precmd(self, line): |
81 | 81 |
if line.startswith('/'): |
82 |
cur_cmd_path = self.prompt.replace(' ',
|
|
83 |
'_')[len(self._prefix):-len(self._suffix)]
|
|
82 |
start, end = len(self._prefix), -len(self._suffix)
|
|
83 |
cur_cmd_path = self.prompt.replace(' ', '_')[start:end]
|
|
84 | 84 |
if cur_cmd_path != self.cmd_tree.name: |
85 | 85 |
cur_cmd = self.cmd_tree.get_command(cur_cmd_path) |
86 | 86 |
self._context_stack.append(self._backup()) |
... | ... | |
94 | 94 |
return line |
95 | 95 |
|
96 | 96 |
def greet(self, version): |
97 |
print('kamaki v%s - Interactive Shell\n\t(exit or ^D to exit)\n'\ |
|
98 |
% version) |
|
97 |
print('kamaki v%s - Interactive Shell\n' % version) |
|
98 |
print('\t\exit \tterminate kamaki') |
|
99 |
print('\texit or ^D\texit context') |
|
100 |
print('\t? or help \tavailable commands') |
|
101 |
print('\t?command \thelp on command') |
|
102 |
print('\t!<command>\texecute OS shell command') |
|
103 |
print('') |
|
99 | 104 |
|
100 | 105 |
def set_prompt(self, new_prompt): |
101 | 106 |
self.prompt = '%s%s%s' % (self._prefix, new_prompt, self._suffix) |
... | ... | |
111 | 116 |
|
112 | 117 |
def do_exit(self, line): |
113 | 118 |
print('') |
114 |
if self.prompt[len(self._prefix):-len(self._suffix)]\
|
|
115 |
== self.cmd_tree.name: |
|
119 |
start, end = len(self._prefix), -len(self._suffix)
|
|
120 |
if self.prompt[start:end] == self.cmd_tree.name:
|
|
116 | 121 |
exit(0) |
117 | 122 |
return True |
118 | 123 |
|
... | ... | |
198 | 203 |
cmd_parser.parse(cmd_args) |
199 | 204 |
|
200 | 205 |
for name, arg in instance.arguments.items(): |
201 |
arg.value = getattr(cmd_parser.parsed, name, |
|
206 |
arg.value = getattr( |
|
207 |
cmd_parser.parsed, |
|
208 |
name, |
|
202 | 209 |
arg.default) |
203 | 210 |
|
204 | 211 |
exec_cmd( |
... | ... | |
209 | 216 |
# if not term.startswith('-')], |
210 | 217 |
except (ClientError, CLIError) as err: |
211 | 218 |
print_error_message(err) |
212 |
elif ('-h' in cmd_args or '--help' in cmd_args) \
|
|
213 |
or len(cmd_args): # print options
|
|
219 |
elif ('-h' in cmd_args or '--help' in cmd_args) or len(cmd_args):
|
|
220 |
# print options
|
|
214 | 221 |
print('%s' % cmd.help) |
215 | 222 |
print_subcommands_help(cmd) |
216 | 223 |
else: # change context |
... | ... | |
259 | 266 |
instance = cls(dict(arguments)) |
260 | 267 |
empty, sep, subname = subcmd.path.partition(cmd.path) |
261 | 268 |
cmd_name = '%s %s' % (cmd.name, subname.replace('_', ' ')) |
262 |
print('\n%s\nSyntax:\t%s %s'\ |
|
263 |
% (cls.description, cmd_name, cls.syntax)) |
|
269 |
print('\n%s\nSyntax:\t%s %s' % ( |
|
270 |
cls.description, |
|
271 |
cmd_name, |
|
272 |
cls.syntax)) |
|
264 | 273 |
cmd_args = {} |
265 | 274 |
for arg in instance.arguments.values(): |
266 | 275 |
cmd_args[','.join(arg.parsed_name)] = arg.help |
b/kamaki/cli/command_tree.py | ||
---|---|---|
115 | 115 |
return cmd, args[index:] |
116 | 116 |
|
117 | 117 |
def pretty_print(self, recursive=False): |
118 |
print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s'\ |
|
119 |
% (self.path, self.name, self.is_command, self.help)) |
|
118 |
print('Path: %s (Name: %s) is_cmd: %s\n\thelp: %s' % ( |
|
119 |
self.path, |
|
120 |
self.name, |
|
121 |
self.is_command, |
|
122 |
self.help)) |
|
120 | 123 |
for cmd in self.get_subcommands(): |
121 | 124 |
cmd.pretty_print(recursive) |
122 | 125 |
|
... | ... | |
204 | 207 |
return self._all_commands[path].get_class() |
205 | 208 |
|
206 | 209 |
def get_subnames(self, path=None): |
207 |
return self.get_group_names() if path in (None, '') \ |
|
208 |
else self._all_commands[path].get_subnames() |
|
210 |
if path in (None, ''): |
|
211 |
return self.get_group_names() |
|
212 |
return self._all_commands[path].get_subnames() |
|
209 | 213 |
|
210 | 214 |
def get_subcommands(self, path=None): |
211 |
return self.get_groups() if path in (None, '') \ |
|
212 |
else self._all_commands[path].get_subcommands() |
|
215 |
if path in (None, ''): |
|
216 |
return self.get_groups() |
|
217 |
return self._all_commands[path].get_subcommands() |
|
213 | 218 |
|
214 | 219 |
def get_parent(self, path): |
215 | 220 |
if '_' not in path: |
b/kamaki/cli/commands/cyclades_cli.py | ||
---|---|---|
44 | 44 |
from os.path import exists |
45 | 45 |
|
46 | 46 |
|
47 |
server_cmds = CommandTree('server', |
|
48 |
'Compute/Cyclades API server commands') |
|
49 |
flavor_cmds = CommandTree('flavor', |
|
50 |
'Compute/Cyclades API flavor commands') |
|
51 |
image_cmds = CommandTree('image', |
|
52 |
'Compute/Cyclades or Glance API image commands') |
|
53 |
network_cmds = CommandTree('network', |
|
54 |
'Compute/Cyclades API network commands') |
|
47 |
server_cmds = CommandTree('server', 'Compute/Cyclades API server commands') |
|
48 |
flavor_cmds = CommandTree('flavor', 'Compute/Cyclades API flavor commands') |
|
49 |
image_cmds = CommandTree('image', 'Cyclades/Plankton API image commands') |
|
50 |
network_cmds = CommandTree('network', 'Compute/Cyclades API network commands') |
|
55 | 51 |
_commands = [server_cmds, flavor_cmds, image_cmds, network_cmds] |
56 | 52 |
|
57 | 53 |
|
... | ... | |
186 | 182 |
for i, terms in enumerate(newvalue): |
187 | 183 |
termlist = terms.split(',') |
188 | 184 |
if len(termlist) > 5: |
189 |
raiseCLIError( |
|
190 |
CLISyntaxError('Wrong number of terms (should be 1 to 5)'), |
|
191 |
details=howto_personality) |
|
185 |
msg = 'Wrong number of terms (should be 1 to 5)' |
|
186 |
raiseCLIError(CLISyntaxError(msg), details=howto_personality) |
|
192 | 187 |
path = termlist[0] |
193 | 188 |
if not exists(path): |
194 |
raiseCLIError(None, |
|
189 |
raiseCLIError( |
|
190 |
None, |
|
195 | 191 |
'--personality: File %s does not exist' % path, |
196 | 192 |
importance=1, |
197 | 193 |
details=howto_personality) |
... | ... | |
497 | 493 |
detail=FlagArgument('show detailed output', '-l'), |
498 | 494 |
limit=IntArgument('limit the number of flavors to list', '-n'), |
499 | 495 |
more=FlagArgument( |
500 |
'output results in pages (-n to set items per page, default 10)', |
|
501 |
'--more') |
|
496 |
'output results in pages (-n to set items per page, default 10)',
|
|
497 |
'--more')
|
|
502 | 498 |
) |
503 | 499 |
|
504 | 500 |
@errors.generic.all |
... | ... | |
580 | 576 |
if self['detail']: |
581 | 577 |
self._make_results_pretty(networks) |
582 | 578 |
if self['more']: |
583 |
print_items(networks, |
|
584 |
page_size=self['limit'] if self['limit'] else 10) |
|
579 |
print_items(networks, page_size=self['limit'] or 10) |
|
585 | 580 |
elif self['limit']: |
586 | 581 |
print_items(networks[:self['limit']]) |
587 | 582 |
else: |
... | ... | |
607 | 602 |
@errors.cyclades.connection |
608 | 603 |
@errors.cyclades.network_max |
609 | 604 |
def _run(self, name): |
610 |
r = self.client.create_network(name, |
|
605 |
r = self.client.create_network( |
|
606 |
name, |
|
611 | 607 |
cidr=self['cidr'], |
612 | 608 |
gateway=self['gateway'], |
613 | 609 |
dhcp=self['dhcp'], |
b/kamaki/cli/commands/errors.py | ||
---|---|---|
82 | 82 |
if not client: |
83 | 83 |
raise |
84 | 84 |
url = getattr(client, 'base_url', '<empty>') |
85 |
raiseCLIError(ce, |
|
86 |
'Invalid service url %s' % url, |
|
87 |
details=[ |
|
85 |
msg = 'Invalid service url %s' % url |
|
86 |
raiseCLIError(ce, msg, details=[ |
|
88 | 87 |
'Please, check if service url is correctly set', |
89 | 88 |
'* to get current url: /config get compute.url', |
90 | 89 |
'* to set url: /config set compute.url <URL>']) |
... | ... | |
112 | 111 |
kloger.warning( |
113 | 112 |
'No permanent token (try: kamaki config set token <tkn>)') |
114 | 113 |
if not getattr(client, 'base_url', False): |
115 |
raise CLIError('Missing astakos server URL',
|
|
116 |
importance=3,
|
|
117 |
details=['Check if astakos.url is set correctly',
|
|
114 |
msg = 'Missing astakos server URL'
|
|
115 |
raise CLIError(msg, importance=3, details=[
|
|
116 |
'Check if astakos.url is set correctly', |
|
118 | 117 |
'To get astakos url: /config get astakos.url', |
119 | 118 |
'To set astakos url: /config set astakos.url <URL>']) |
120 | 119 |
return r |
... | ... | |
128 | 127 |
except ClientError as ce: |
129 | 128 |
if ce.status == 401: |
130 | 129 |
token = kwargs.get('custom_token', 0) or self.client.token |
131 |
raiseCLIError(ce, |
|
132 |
'Authorization failed for token %s' % token if token\ |
|
133 |
else 'No token provided', |
|
134 |
details=[] if token else this._token_details) |
|
130 |
msg = ( |
|
131 |
'Authorization failed for token %s' % token |
|
132 |
) if token else 'No token provided', |
|
133 |
details = [] if token else this._token_details |
|
134 |
raiseCLIError(ce, msg, details=details) |
|
135 | 135 |
self._raise = foo |
136 | 136 |
return r |
137 | 137 |
return _raise |
... | ... | |
151 | 151 |
def _get_cmd_ids(this, foo): |
152 | 152 |
def _raise(self, cmd_ids, *args, **kwargs): |
153 | 153 |
if not cmd_ids: |
154 |
raise CLISyntaxError('Usage: <id1|id1-id2> [id3|id3-id4] ...', |
|
154 |
raise CLISyntaxError( |
|
155 |
'Usage: <id1|id1-id2> [id3|id3-id4] ...', |
|
155 | 156 |
details=self.__doc__.split('\n')) |
156 | 157 |
return foo(self, cmd_ids, *args, **kwargs) |
157 | 158 |
return _raise |
... | ... | |
193 | 194 |
network_id = int(network_id) |
194 | 195 |
return foo(self, *args, **kwargs) |
195 | 196 |
except ValueError as ve: |
196 |
raiseCLIError(ve, 'Invalid network id %s ' % network_id,
|
|
197 |
details='network id must be a positive integer',
|
|
198 |
importance=1)
|
|
197 |
msg = 'Invalid network id %s ' % network_id
|
|
198 |
details = ['network id must be a positive integer']
|
|
199 |
raiseCLIError(ve, msg, details=details, importance=1)
|
|
199 | 200 |
except ClientError as ce: |
200 |
if network_id and ce.status == 404 and\
|
|
201 |
'network' in ('%s' % ce).lower():
|
|
202 |
raiseCLIError(ce,
|
|
203 |
'No network with id %s found' % network_id,
|
|
204 |
details=this.about_network_id)
|
|
201 |
if network_id and ce.status == 404 and (
|
|
202 |
'network' in ('%s' % ce).lower() |
|
203 |
):
|
|
204 |
msg = 'No network with id %s found' % network_id,
|
|
205 |
raiseCLIError(ce, msg, details=this.about_network_id)
|
|
205 | 206 |
raise |
206 | 207 |
return _raise |
207 | 208 |
|
... | ... | |
212 | 213 |
return foo(self, *args, **kwargs) |
213 | 214 |
except ClientError as ce: |
214 | 215 |
if ce.status == 413: |
215 |
raiseCLIError(ce,
|
|
216 |
'Cannot create another network',
|
|
217 |
details=['Maximum number of networks reached',
|
|
218 |
'* to get a list of networks: /network list',
|
|
219 |
'* to delete a network: /network delete <net id>'])
|
|
216 |
msg = 'Cannot create another network',
|
|
217 |
details = ['Maximum number of networks reached',
|
|
218 |
'* to get a list of networks: /network list',
|
|
219 |
'* to delete a network: /network delete <net id>']
|
|
220 |
raiseCLIError(ce, msg, details=details)
|
|
220 | 221 |
raise |
221 | 222 |
return _raise |
222 | 223 |
|
... | ... | |
228 | 229 |
return foo(self, *args, **kwargs) |
229 | 230 |
except ClientError as ce: |
230 | 231 |
if network_id and ce.status == 400: |
231 |
raiseCLIError(ce, |
|
232 |
'Network with id %s does not exist' % network_id, |
|
233 |
details=self.about_network_id) |
|
232 |
msg = 'Network with id %s does not exist' % network_id, |
|
233 |
raiseCLIError(ce, msg, details=self.about_network_id) |
|
234 | 234 |
elif network_id or ce.status == 421: |
235 |
raiseCLIError(ce, |
|
236 |
'Network with id %s is in use' % network_id, |
|
237 |
details=[ |
|
238 |
'Disconnect all nics/VMs of this network first', |
|
239 |
'* to get nics: /network info %s' % network_id, |
|
240 |
'. (under "attachments" section)', |
|
241 |
'* to disconnect: /network disconnect <nic id>']) |
|
235 |
msg = 'Network with id %s is in use' % network_id, |
|
236 |
raiseCLIError(ce, msg, details=[ |
|
237 |
'Disconnect all nics/VMs of this network first', |
|
238 |
'* to get nics: /network info %s' % network_id, |
|
239 |
'. (under "attachments" section)', |
|
240 |
'* to disconnect: /network disconnect <nic id>']) |
|
242 | 241 |
raise |
243 | 242 |
return _raise |
244 | 243 |
|
... | ... | |
250 | 249 |
flavor_id = int(flavor_id) |
251 | 250 |
return foo(self, *args, **kwargs) |
252 | 251 |
except ValueError as ve: |
253 |
raiseCLIError(ve, 'Invalid flavor id %s ' % flavor_id,
|
|
254 |
details='Flavor id must be a positive integer',
|
|
255 |
importance=1)
|
|
252 |
msg = 'Invalid flavor id %s ' % flavor_id,
|
|
253 |
details = 'Flavor id must be a positive integer',
|
|
254 |
raiseCLIError(ve, msg, details=details, importance=1)
|
|
256 | 255 |
except ClientError as ce: |
257 |
if flavor_id and ce.status == 404 and\
|
|
258 |
'flavor' in ('%s' % ce).lower():
|
|
259 |
raiseCLIError(ce,
|
|
260 |
'No flavor with id %s found' % flavor_id,
|
|
261 |
details=this.about_flavor_id)
|
|
256 |
if flavor_id and ce.status == 404 and (
|
|
257 |
'flavor' in ('%s' % ce).lower() |
|
258 |
):
|
|
259 |
msg = 'No flavor with id %s found' % flavor_id,
|
|
260 |
raiseCLIError(ce, msg, details=this.about_flavor_id)
|
|
262 | 261 |
raise |
263 | 262 |
return _raise |
264 | 263 |
|
... | ... | |
270 | 269 |
server_id = int(server_id) |
271 | 270 |
return foo(self, *args, **kwargs) |
272 | 271 |
except ValueError as ve: |
273 |
raiseCLIError(ve, |
|
274 |
'Invalid server(VM) id %s' % server_id, |
|
275 |
details=['id must be a positive integer'], |
|
276 |
importance=1) |
|
272 |
msg = 'Invalid server(VM) id %s' % server_id, |
|
273 |
details = ['id must be a positive integer'], |
|
274 |
raiseCLIError(ve, msg, details=details, importance=1) |
|
277 | 275 |
except ClientError as ce: |
278 | 276 |
err_msg = ('%s' % ce).lower() |
279 |
if (ce.status == 404 and 'server' in err_msg)\ |
|
280 |
or (ce.status == 400 and 'not found' in err_msg): |
|
281 |
raiseCLIError(ce, |
|
282 |
'server(VM) with id %s not found' % server_id, |
|
283 |
details=[ |
|
284 |
'* to get existing VM ids: /server list', |
|
285 |
'* to get VM details: /server info <VM id>']) |
|
277 |
if ( |
|
278 |
ce.status == 404 and 'server' in err_msg |
|
279 |
) or ( |
|
280 |
ce.status == 400 and 'not found' in err_msg |
|
281 |
): |
|
282 |
msg = 'server(VM) with id %s not found' % server_id, |
|
283 |
raiseCLIError(ce, msg, details=[ |
|
284 |
'* to get existing VM ids: /server list', |
|
285 |
'* to get VM details: /server info <VM id>']) |
|
286 | 286 |
raise |
287 | 287 |
return _raise |
288 | 288 |
|
... | ... | |
293 | 293 |
try: |
294 | 294 |
return foo(self, *args, **kwargs) |
295 | 295 |
except ClientError as ce: |
296 |
if ce.status == 400 and profile\ |
|
297 |
and 'firewall' in ('%s' % ce).lower(): |
|
298 |
raiseCLIError(ce, |
|
299 |
'%s is an invalid firewall profile term' % profile, |
|
300 |
details=['Try one of the following:', |
|
301 |
'* DISABLED: Shutdown firewall', |
|
302 |
'* ENABLED: Firewall in normal mode', |
|
303 |
'* PROTECTED: Firewall in secure mode']) |
|
296 |
if ce.status == 400 and profile and ( |
|
297 |
'firewall' in ('%s' % ce).lower() |
|
298 |
): |
|
299 |
msg = '%s is an invalid firewall profile term' % profile |
|
300 |
raiseCLIError(ce, msg, details=[ |
|
301 |
'Try one of the following:', |
|
302 |
'* DISABLED: Shutdown firewall', |
|
303 |
'* ENABLED: Firewall in normal mode', |
|
304 |
'* PROTECTED: Firewall in secure mode']) |
|
304 | 305 |
raise |
305 | 306 |
return _raise |
306 | 307 |
|
... | ... | |
311 | 312 |
return foo(self, *args, **kwargs) |
312 | 313 |
except ClientError as ce: |
313 | 314 |
nic_id = kwargs.get('nic_id', None) |
314 |
if nic_id and ce.status == 404\ |
|
315 |
and 'network interface' in ('%s' % ce).lower(): |
|
315 |
if nic_id and ce.status == 404 and ( |
|
316 |
'network interface' in ('%s' % ce).lower() |
|
317 |
): |
|
316 | 318 |
server_id = kwargs.get('server_id', '<no server>') |
317 | 319 |
err_msg = 'No nic %s on server(VM) with id %s' % ( |
318 | 320 |
nic_id, |
... | ... | |
333 | 335 |
return foo(self, *args, **kwargs) |
334 | 336 |
except IndexError as ie: |
335 | 337 |
nic_id = kwargs.get('nic_id', None) |
336 |
raiseCLIError(ie, |
|
337 |
'Invalid format for network interface (nic) %s' % nic_id, |
|
338 |
importance=1, |
|
339 |
details=[ |
|
340 |
'nid_id format: nic-<server id>-<nic id>', |
|
341 |
'* get nics of a network: /network info <net id>', |
|
342 |
' (listed the "attachments" section)']) |
|
338 |
msg = 'Invalid format for network interface (nic) %s' % nic_id |
|
339 |
raiseCLIError(ie, msg, importance=1, details=[ |
|
340 |
'nid_id format: nic-<server id>-<nic id>', |
|
341 |
'* get nics of a network: /network info <net id>', |
|
342 |
' (listed the "attachments" section)']) |
|
343 | 343 |
return _raise |
344 | 344 |
|
345 | 345 |
@classmethod |
... | ... | |
349 | 349 |
try: |
350 | 350 |
foo(self, *args, **kwargs) |
351 | 351 |
except ClientError as ce: |
352 |
if key and ce.status == 404\ |
|
353 |
and 'metadata' in ('%s' % ce).lower(): |
|
352 |
if key and ce.status == 404 and ( |
|
353 |
'metadata' in ('%s' % ce).lower() |
|
354 |
): |
|
354 | 355 |
raiseCLIError(ce, 'No VM metadata with key %s' % key) |
355 | 356 |
raise |
356 | 357 |
return _raise |
... | ... | |
358 | 359 |
|
359 | 360 |
class plankton(object): |
360 | 361 |
|
361 |
about_image_id = ['How to pick a suitable image:', |
|
362 |
about_image_id = [ |
|
363 |
'How to pick a suitable image:', |
|
362 | 364 |
'* get a list of image ids: /image list', |
363 | 365 |
'* details of image: /flavor info <image id>'] |
364 | 366 |
|
... | ... | |
373 | 375 |
try: |
374 | 376 |
foo(self, *args, **kwargs) |
375 | 377 |
except ClientError as ce: |
376 |
if image_id and (ce.status == 404\ |
|
377 |
or (ce.status == 400 and |
|
378 |
'image not found' in ('%s' % ce).lower())\ |
|
379 |
or ce.status == 411): |
|
380 |
raiseCLIError(ce, |
|
381 |
'No image with id %s found' % image_id, |
|
382 |
details=this.about_image_id) |
|
378 |
if image_id and ( |
|
379 |
ce.status == 404 |
|
380 |
or ( |
|
381 |
ce.status == 400 |
|
382 |
and 'image not found' in ('%s' % ce).lower()) |
|
383 |
or ce.status == 411 |
|
384 |
): |
|
385 |
msg = 'No image with id %s found' % image_id |
|
386 |
raiseCLIError(ce, msg, details=this.about_image_id) |
|
383 | 387 |
raise |
384 | 388 |
return _raise |
385 | 389 |
|
... | ... | |
390 | 394 |
try: |
391 | 395 |
foo(self, *args, **kwargs) |
392 | 396 |
except ClientError as ce: |
393 |
if ce.status == 404 or ((ce.status == 400\
|
|
394 |
and 'metadata' in ('%s' % ce).lower())): |
|
395 |
raiseCLIError(ce,
|
|
396 |
'No properties with key %s in this image' % key)
|
|
397 |
if ce.status == 404 or ( |
|
398 |
(ce.status == 400 and 'metadata' in ('%s' % ce).lower())):
|
|
399 |
msg = 'No properties with key %s in this image' % key
|
|
400 |
raiseCLIError(ce, msg)
|
|
397 | 401 |
raise |
398 | 402 |
return _raise |
399 | 403 |
|
400 | 404 |
|
401 | 405 |
class pithos(object): |
402 |
container_howto = ['To specify a container:', |
|
403 |
' 1. Set store.container variable (permanent)', |
|
404 |
' /config set store.container <container>', |
|
405 |
' 2. --container=<container> (temporary, overrides 1)', |
|
406 |
' 3. Use the container:path format (temporary, overrides all)', |
|
407 |
'For a list of containers: /store list'] |
|
406 |
container_howto = [ |
|
407 |
"" 'To specify a container:', |
|
408 |
' 1. Set store.container variable (permanent)', |
|
409 |
' /config set store.container <container>', |
|
410 |
' 2. --container=<container> (temporary, overrides 1)', |
|
411 |
' 3. Use the container:path format (temporary, overrides all)', |
|
412 |
'For a list of containers: /store list'] |
|
408 | 413 |
|
409 | 414 |
@classmethod |
410 | 415 |
def connection(this, foo): |
... | ... | |
435 | 440 |
return foo(self, *args, **kwargs) |
436 | 441 |
except ClientError as ce: |
437 | 442 |
if ce.status == 404 and 'container' in ('%s' % ce).lower(): |
438 |
cont = '%s or %s' % (self.container, dst_cont)\
|
|
439 |
if dst_cont else self.container
|
|
440 |
raiseCLIError(ce,
|
|
441 |
'Is container %s in current account?' % (cont),
|
|
442 |
details=this.container_howto)
|
|
443 |
cont = ('%s or %s' % (
|
|
444 |
self.container,
|
|
445 |
dst_cont)) if dst_cont else self.container
|
|
446 |
msg = 'Is container %s in current account?' % (cont),
|
|
447 |
raiseCLIError(ce, msg, details=this.container_howto)
|
|
443 | 448 |
raise |
444 | 449 |
return _raise |
445 | 450 |
|
... | ... | |
450 | 455 |
try: |
451 | 456 |
return foo(self, *args, **kwargs) |
452 | 457 |
except IOError as ioe: |
453 |
raiseCLIError(ioe, |
|
454 |
'Failed to access file %s' % local_path, |
|
455 |
importance=2) |
|
458 |
msg = 'Failed to access file %s' % local_path, |
|
459 |
raiseCLIError(ioe, msg, importance=2) |
|
456 | 460 |
return _raise |
457 | 461 |
|
458 | 462 |
@classmethod |
... | ... | |
462 | 466 |
return foo(self, *args, **kwargs) |
463 | 467 |
except ClientError as ce: |
464 | 468 |
err_msg = ('%s' % ce).lower() |
465 |
if (ce.status == 404 or ce.status == 500)\ |
|
466 |
and 'object' in err_msg and 'not' in err_msg: |
|
467 |
raiseCLIError(ce, |
|
468 |
'No object %s in container %s'\ |
|
469 |
% (self.path, self.container), |
|
470 |
details=this.container_howto) |
|
469 |
if ( |
|
470 |
ce.status == 404 or ce.status == 500 |
|
471 |
) and 'object' in err_msg and 'not' in err_msg: |
|
472 |
msg = 'No object %s in container %s' % ( |
|
473 |
self.path, |
|
474 |
self.container) |
|
475 |
raiseCLIError(ce, msg, details=this.container_howto) |
|
471 | 476 |
raise |
472 | 477 |
return _raise |
473 | 478 |
|
... | ... | |
481 | 486 |
try: |
482 | 487 |
size = int(size) |
483 | 488 |
except ValueError as ve: |
484 |
raiseCLIError(ve, |
|
485 |
'Invalid file size %s ' % size, |
|
486 |
details=['size must be a positive integer'], |
|
487 |
importance=1) |
|
489 |
msg = 'Invalid file size %s ' % size |
|
490 |
details = ['size must be a positive integer'] |
|
491 |
raiseCLIError(ve, msg, details=details, importance=1) |
|
488 | 492 |
else: |
489 | 493 |
try: |
490 | 494 |
start = int(start) |
491 | 495 |
except ValueError as e: |
492 |
raiseCLIError(e, |
|
493 |
'Invalid start value %s in range' % start, |
|
494 |
details=['size must be a positive integer'], |
|
495 |
importance=1) |
|
496 |
msg = 'Invalid start value %s in range' % start, |
|
497 |
details = ['size must be a positive integer'], |
|
498 |
raiseCLIError(e, msg, details=details, importance=1) |
|
496 | 499 |
try: |
497 | 500 |
end = int(end) |
498 | 501 |
except ValueError as e: |
499 |
raiseCLIError(e, |
|
500 |
'Invalid end value %s in range' % end, |
|
501 |
details=['size must be a positive integer'], |
|
502 |
importance=1) |
|
502 |
msg = 'Invalid end value %s in range' % end |
|
503 |
details = ['size must be a positive integer'] |
|
504 |
raiseCLIError(e, msg, details=details, importance=1) |
|
503 | 505 |
if start > end: |
504 | 506 |
raiseCLIError( |
505 | 507 |
'Invalid range %s-%s' % (start, end), |
... | ... | |
511 | 513 |
except ClientError as ce: |
512 | 514 |
err_msg = ('%s' % ce).lower() |
513 | 515 |
if size and (ce.status == 416 or |
514 |
(ce.status == 400 and\
|
|
516 |
(ce.status == 400 and |
|
515 | 517 |
'object length is smaller than range length' in err_msg)): |
516 |
raiseCLIError(ce, |
|
517 |
'Remote object %s:%s <= %s %s' % ( |
|
518 |
raiseCLIError(ce, 'Remote object %s:%s <= %s %s' % ( |
|
518 | 519 |
self.container, |
519 | 520 |
self.path, |
520 | 521 |
format_size(size), |
b/kamaki/cli/commands/history_cli.py | ||
---|---|---|
172 | 172 |
instance.config = self.config |
173 | 173 |
prs = ArgumentParseManager(cmd.path.split(), |
174 | 174 |
dict(instance.arguments)) |
175 |
prs.syntax = '%s %s' % (cmd.path.replace('_', ' '), |
|
175 |
prs.syntax = '%s %s' % ( |
|
176 |
cmd.path.replace('_', ' '), |
|
176 | 177 |
cmd.get_class().syntax) |
177 | 178 |
prs.parse(args) |
178 | 179 |
exec_cmd(instance, prs.unparsed, prs.parser.print_help) |
b/kamaki/cli/commands/image_cli.py | ||
---|---|---|
100 | 100 |
'name', |
101 | 101 |
'size_min', |
102 | 102 |
'size_max', |
103 |
'status' |
|
104 |
]).intersection(self.arguments): |
|
103 |
'status']).intersection(self.arguments): |
|
105 | 104 |
filters[arg] = self[arg] |
106 | 105 |
|
107 | 106 |
order = self['order'] |
... | ... | |
190 | 189 |
'id', |
191 | 190 |
'owner', |
192 | 191 |
'size', |
193 |
'is_public' |
|
194 |
]).intersection(self.arguments): |
|
192 |
'is_public']).intersection(self.arguments): |
|
195 | 193 |
params[key] = self[key] |
196 | 194 |
|
197 | 195 |
properties = self['properties'] |
b/kamaki/cli/commands/pithos_cli.py | ||
---|---|---|
81 | 81 |
' to set the service url: /config set store.url <url>', |
82 | 82 |
' ', |
83 | 83 |
' to get authentication token: /config get token', |
84 |
' to set authentication token: /config set token <token>' |
|
85 |
]) |
|
84 |
' to set authentication token: /config set token <token>']) |
|
86 | 85 |
elif e.status == 413: |
87 | 86 |
raiseCLIError(e, details=[ |
88 | 87 |
'Get quotas:', |
89 | 88 |
'- total quota: /store quota', |
90 | 89 |
'- container quota: /store quota <container>', |
91 | 90 |
'Users shall set a higher container quota, if available:', |
92 |
'- /store setquota <quota>[unit] <container>' |
|
93 |
]) |
|
91 |
'- /store setquota <quota>[unit] <container>']) |
|
94 | 92 |
|
95 | 93 |
|
96 | 94 |
class DelimiterArgument(ValueArgument): |
... | ... | |
142 | 140 |
details='Incorrect format', |
143 | 141 |
importance=1) |
144 | 142 |
if key.lower() not in ('read', 'write'): |
145 |
raiseCLIError(err, 'Error in --sharing',
|
|
146 |
details='Invalid permission key %s' % key,
|
|
147 |
importance=1)
|
|
143 |
msg = 'Error in --sharing'
|
|
144 |
raiseCLIError(err, msg, importance=1, details=[
|
|
145 |
'Invalid permission key %s' % key])
|
|
148 | 146 |
val_list = val.split(',') |
149 | 147 |
if not key in perms: |
150 | 148 |
perms[key] = [] |
... | ... | |
189 | 187 |
self._set_account() |
190 | 188 |
self.container = self.config.get('store', 'container')\ |
191 | 189 |
or self.config.get('global', 'container') |
192 |
self.client = PithosClient(base_url=self.base_url, |
|
190 |
self.client = PithosClient( |
|
191 |
base_url=self.base_url, |
|
193 | 192 |
token=self.token, |
194 | 193 |
account=self.account, |
195 | 194 |
container=self.container) |
... | ... | |
245 | 244 |
dst = dest_container_path.split(':') |
246 | 245 |
return (dst[0], dst[1]) if len(dst) > 1 else (None, dst[0]) |
247 | 246 |
|
248 |
def extract_container_and_path(self, |
|
247 |
def extract_container_and_path( |
|
248 |
self, |
|
249 | 249 |
container_with_path, |
250 | 250 |
path_is_optional=True): |
251 | 251 |
"""Contains all heuristics for deciding what should be used as |
... | ... | |
366 | 366 |
def print_objects(self, object_list): |
367 | 367 |
limit = int(self['limit']) if self['limit'] > 0 else len(object_list) |
368 | 368 |
for index, obj in enumerate(object_list): |
369 |
if (self['exact_match'] and self.path and\
|
|
370 |
obj['name'] != self.path) or 'content_type' not in obj: |
|
369 |
if (self['exact_match'] and self.path and (
|
|
370 |
obj['name'] != self.path) or 'content_type' not in obj):
|
|
371 | 371 |
continue |
372 | 372 |
pretty_obj = obj.copy() |
373 | 373 |
index += 1 |
... | ... | |
407 | 407 |
|
408 | 408 |
else: |
409 | 409 |
if 'count' in container and 'bytes' in container: |
410 |
print('%s (%s, %s objects)'\ |
|
411 |
% (cname, size, container['count'])) |
|
410 |
print('%s (%s, %s objects)' % ( |
|
411 |
cname, |
|
412 |
size, |
|
413 |
container['count'])) |
|
412 | 414 |
else: |
413 | 415 |
print(cname) |
414 | 416 |
if self['more']: |
... | ... | |
511 | 513 |
@errors.pithos.connection |
512 | 514 |
@errors.pithos.container |
513 | 515 |
def _run(self): |
514 |
self.client.container_put(quota=self['quota'], |
|
516 |
self.client.container_put( |
|
517 |
quota=self['quota'], |
|
515 | 518 |
versioning=self['versioning'], |
516 | 519 |
metadata=self['meta']) |
517 | 520 |
|
... | ... | |
573 | 576 |
if len(r.json) == 1: |
574 | 577 |
obj = r.json[0] |
575 | 578 |
return [(obj['name'], dst_path or obj['name'])] |
576 |
return [(obj['name'], '%s%s' % ( |
|
579 |
return [( |
|
580 |
obj['name'], |
|
581 |
'%s%s' % ( |
|
577 | 582 |
dst_path, |
578 | 583 |
obj['name'][len(self.path) if self['replace'] else 0:]) |
579 |
) for obj in r.json]
|
|
584 |
) for obj in r.json] |
|
580 | 585 |
|
581 | 586 |
@errors.generic.all |
582 | 587 |
@errors.pithos.connection |
... | ... | |
598 | 603 |
self.path, |
599 | 604 |
self.container)) |
600 | 605 |
|
601 |
def main(self, |
|
606 |
def main( |
|
607 |
self, |
|
602 | 608 |
source_container___path, |
603 | 609 |
destination_container___path=None): |
604 | 610 |
super(self.__class__, self)._run( |
... | ... | |
652 | 658 |
if len(r.json) == 1: |
653 | 659 |
obj = r.json[0] |
654 | 660 |
return [(obj['name'], dst_path or obj['name'])] |
655 |
return [(obj['name'], '%s%s' % ( |
|
656 |
dst_path, |
|
657 |
obj['name'][len(self.path) if self['replace'] else 0:]) |
|
658 |
) for obj in r.json] |
|
661 |
return [( |
|
662 |
obj['name'], |
|
663 |
'%s%s' % ( |
|
664 |
dst_path, |
|
665 |
obj['name'][len(self.path) if self['replace'] else 0:] |
|
666 |
)) for obj in r.json] |
|
659 | 667 |
|
660 | 668 |
@errors.generic.all |
661 | 669 |
@errors.pithos.connection |
... | ... | |
677 | 685 |
self.path, |
678 | 686 |
self.container)) |
679 | 687 |
|
680 |
def main(self, |
|
688 |
def main( |
|
689 |
self, |
|
681 | 690 |
source_container___path, |
682 | 691 |
destination_container___path=None): |
683 | 692 |
super(self.__class__, self)._run( |
... | ... | |
823 | 832 |
'--content-type', |
824 | 833 |
default='application/octet-stream'), |
825 | 834 |
sharing=SharingArgument( |
826 |
'define object sharing policy \n' +\ |
|
827 |
' ( "read=user1,grp1,user2,... write=user1,grp2,..." )', |
|
835 |
'\n'.join([ |
|
836 |
'define object sharing policy', |
|
837 |
' ( "read=user1,grp1,user2,... write=user1,grp2,..." )']), |
|
828 | 838 |
'--sharing'), |
829 | 839 |
public=FlagArgument('make object publicly accessible', '--public') |
830 | 840 |
) |
... | ... | |
867 | 877 |
'--content-disposition'), |
868 | 878 |
content_type=ValueArgument('specify content type', '--content-type'), |
869 | 879 |
sharing=SharingArgument( |
870 |
help='define sharing object policy \n' +\ |
|
871 |
'( "read=user1,grp1,user2,... write=user1,grp2,... )', |
|
880 |
help='\n'.join([ |
|
881 |
'define sharing object policy', |
|
882 |
'( "read=user1,grp1,user2,... write=user1,grp2,... )']), |
|
872 | 883 |
parsed_name='--sharing'), |
873 | 884 |
public=FlagArgument('make object publicly accessible', '--public'), |
874 | 885 |
poolsize=IntArgument('set pool size', '--with-pool-size'), |
... | ... | |
928 | 939 |
if progress_bar: |
929 | 940 |
hash_bar = progress_bar.clone() |
930 | 941 |
hash_cb = hash_bar.get_generator( |
931 |
'Calculating block hashes') |
|
942 |
'Calculating block hashes' |
|
943 |
) |
|
932 | 944 |
else: |
933 | 945 |
hash_cb = None |
934 | 946 |
self.client.upload_object( |
... | ... | |
1049 | 1061 |
if_unmodified_since=self['if_unmodified_since']) |
1050 | 1062 |
return [( |
1051 | 1063 |
'%s/%s' % (outpath, remote['name']), |
1052 |
None if self._is_dir(remote) else remote['name'])\
|
|
1053 |
for remote in remotes.json]
|
|
1064 |
None if self._is_dir(remote) else remote['name']
|
|
1065 |
) for remote in remotes.json]
|
|
1054 | 1066 |
raiseCLIError('Illegal destination location %s' % local_path) |
1055 | 1067 |
|
1056 | 1068 |
@errors.generic.all |
... | ... | |
1201 | 1213 |
@errors.pithos.object_path |
1202 | 1214 |
def _run(self): |
1203 | 1215 |
if self.path: |
1204 |
if self['yes'] or ask_user( |
|
1205 |
'Delete %s:%s ?' % (self.container, self.path)): |
|
1216 |
if self['yes'] or ask_user('Delete %s:%s ?' % ( |
|
1217 |
self.container, |
|
1218 |
self.path)): |
|
1206 | 1219 |
self.client.del_object( |
1207 | 1220 |
self.path, |
1208 | 1221 |
until=self['until'], |
... | ... | |
1210 | 1223 |
else: |
1211 | 1224 |
print('Aborted') |
1212 | 1225 |
else: |
1213 |
ask_msg = 'Delete contents of container'\ |
|
1214 |
if self['recursive'] else 'Delete container' |
|
1226 |
if self['resursive']: |
|
1227 |
ask_msg = 'Delete container contents' |
|
1228 |
else: |
|
1229 |
ask_msg = 'Delete container' |
|
1215 | 1230 |
if self['yes'] or ask_user('%s %s ?' % (ask_msg, self.container)): |
1216 | 1231 |
self.client.del_container( |
1217 | 1232 |
until=self['until'], |
... | ... | |
1344 | 1359 |
read = False |
1345 | 1360 |
write = False |
1346 | 1361 |
if not (read or write): |
1347 |
raiseCLIError(None,
|
|
1348 |
'Usage:\tread=<groups,users> write=<groups,users>')
|
|
1362 |
msg = 'Usage:\tread=<groups,users> write=<groups,users>'
|
|
1363 |
raiseCLIError(None, msg)
|
|
1349 | 1364 |
return (read, write) |
1350 | 1365 |
|
1351 | 1366 |
@errors.generic.all |
... | ... | |
1459 | 1474 |
r['object-meta'] = pretty_keys(ometa, '-') |
1460 | 1475 |
else: |
1461 | 1476 |
if self['detail']: |
1462 |
r = self.client.get_object_info(self.path, |
|
1477 |
r = self.client.get_object_info( |
|
1478 |
self.path, |
|
1463 | 1479 |
version=self['object_version']) |
1464 | 1480 |
else: |
1465 |
r = self.client.get_object_meta(self.path, |
|
1481 |
r = self.client.get_object_meta( |
|
1482 |
self.path, |
|
1466 | 1483 |
version=self['object_version']) |
1467 | 1484 |
if r: |
1468 | 1485 |
r = pretty_keys(pretty_keys(r, '-')) |
... | ... | |
1529 | 1546 |
|
1530 | 1547 |
arguments = dict( |
1531 | 1548 |
in_bytes=FlagArgument('Show result in bytes', ('-b', '--bytes')) |
1532 |
)
|
|
1549 |
) |
|
1533 | 1550 |
|
1534 | 1551 |
@errors.generic.all |
1535 | 1552 |
@errors.pithos.connection |
... | ... | |
1574 | 1591 |
try: |
1575 | 1592 |
return to_bytes(quota, format) |
1576 | 1593 |
except Exception as qe: |
1577 |
raiseCLIError(qe, |
|
1578 |
'Failed to convert %s to bytes' % user_input, |
|
1579 |
details=[ |
|
1580 |
'Syntax: setquota <quota>[format] [container]', |
|
1581 |
'e.g.: setquota 2.3GB mycontainer', |
|
1582 |
'Acceptable formats:', |
|
1583 |
'(*1024): B, KiB, MiB, GiB, TiB', |
|
1584 |
'(*1000): B, KB, MB, GB, TB']) |
|
1594 |
msg = 'Failed to convert %s to bytes' % user_input, |
|
1595 |
raiseCLIError(qe, msg, details=[ |
|
1596 |
'Syntax: setquota <quota>[format] [container]', |
|
1597 |
'e.g.: setquota 2.3GB mycontainer', |
|
1598 |
'Acceptable formats:', |
|
1599 |
'(*1024): B, KiB, MiB, GiB, TiB', |
|
1600 |
'(*1000): B, KB, MB, GB, TB']) |
|
1585 | 1601 |
return quota |
1586 | 1602 |
|
1587 | 1603 |
@errors.generic.all |
... | ... | |
1705 | 1721 |
@errors.pithos.connection |
1706 | 1722 |
def _run(self): |
1707 | 1723 |
accounts = self.client.get_sharing_accounts(marker=self['marker']) |
1708 |
print_items(accounts if self['detail']\
|
|
1724 |
print_items(accounts if self['detail'] |
|
1709 | 1725 |
else [acc['name'] for acc in accounts]) |
1710 | 1726 |
|
1711 | 1727 |
def main(self): |
b/kamaki/cli/commands/test_cli.py | ||
---|---|---|
156 | 156 |
|
157 | 157 |
l2 = [d2, l1, d1] |
158 | 158 |
|
159 |
d3 = {'dict 1': d1, 'dict 2': d2, 'list2': l2,
|
|
160 |
'long key of size 75 characters is used to' +\
|
|
161 |
' check the effects on total result': l1}
|
|
159 |
spr_msg = 'long key of size 75 characters is used to check the effects on'
|
|
160 |
spr_msg += ' total result for long messages that drive pep8 completely mad'
|
|
161 |
d3 = {'dict 1': d1, 'dict 2': d2, 'list2': l2, spr_msg: l1}
|
|
162 | 162 |
|
163 | 163 |
@errors.generic.all |
164 | 164 |
def _run(self): |
... | ... | |
191 | 191 |
print_list(self.l2, with_enumeration=True) |
192 | 192 |
print('- - -\n') |
193 | 193 |
print('\nTest print_items with id:\n- - -') |
194 |
print_items([{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
194 |
print_items([ |
|
195 |
{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
195 | 196 |
{'id': '142', 'title': 'lalakis 2', 'content': self.d2}]) |
196 | 197 |
print('- - -') |
197 | 198 |
print('\nTest print_items with id and enumeration:\n- - -') |
198 |
print_items([{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
199 |
{'id': '142', 'title': 'lalakis 2', 'content': self.d2}], |
|
199 |
print_items([ |
|
200 |
{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
201 |
{'id': '142', 'title': 'lalakis 2', 'content': self.d2}], |
|
200 | 202 |
with_enumeration=True) |
201 | 203 |
print('- - -') |
202 | 204 |
print('\nTest print_items with id, title and redundancy:\n- - -') |
203 |
print_items([{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
204 |
{'id': '142', 'title': 'lalakis 2', 'content': self.d2}], |
|
205 |
print_items([ |
|
206 |
{'id': '42', 'title': 'lalakis 1', 'content': self.d1}, |
|
207 |
{'id': '142', 'title': 'lalakis 2', 'content': self.d2}], |
|
205 | 208 |
title=('id', 'title'), |
206 | 209 |
with_redundancy=True) |
207 | 210 |
print('- - -') |
b/kamaki/cli/errors.py | ||
---|---|---|
67 | 67 |
|
68 | 68 |
|
69 | 69 |
class CLICmdSpecError(CLIError): |
70 |
def __init__(self, |
|
71 |
message='Command Specification Error', details=[], importance=0): |
|
70 |
def __init__( |
|
71 |
self, |
|
72 |
message='Command Specification Error', |
|
73 |
details=[], |
|
74 |
importance=0): |
|
72 | 75 |
super(CLICmdSpecError, self).__init__(message, details, importance) |
73 | 76 |
|
74 | 77 |
|
75 | 78 |
class CLICmdIncompleteError(CLICmdSpecError): |
76 |
def __init__(self, |
|
77 |
message='Incomplete Command Error', details=[], importance=1): |
|
79 |
def __init__( |
|
80 |
self, |
|
81 |
message='Incomplete Command Error', |
|
82 |
details=[], |
|
83 |
importance=1): |
|
78 | 84 |
super(CLICmdSpecError, self).__init__(message, details, importance) |
79 | 85 |
|
80 | 86 |
|
b/kamaki/cli/history.py | ||
---|---|---|
49 | 49 |
|
50 | 50 |
def get(self, match_terms=None, limit=0): |
51 | 51 |
f = open(self.filepath, 'r') |
52 |
result = ['%s. \t%s' % (index + 1, line)\
|
|
53 |
for index, line in enumerate(f.readlines())\
|
|
52 |
result = ['%s. \t%s' % (index + 1, line) |
|
53 |
for index, line in enumerate(f.readlines()) |
|
54 | 54 |
if self._match(line, match_terms)] |
55 | 55 |
offset = len(result) - limit if limit and len(result) > limit else 0 |
56 | 56 |
return result[offset:] |
b/kamaki/cli/utils.py | ||
---|---|---|
71 | 71 |
return new_d |
72 | 72 |
|
73 | 73 |
|
74 |
def print_dict(d, |
|
74 |
def print_dict( |
|
75 |
d, |
|
75 | 76 |
exclude=(), |
76 | 77 |
ident=0, |
77 | 78 |
with_enumeration=False, |
... | ... | |
96 | 97 |
raiseCLIError(TypeError('Cannot dict_print a non-dict object')) |
97 | 98 |
|
98 | 99 |
if d: |
99 |
margin = max(len(unicode(key).strip())\
|
|
100 |
margin = max(len(unicode(key).strip()) |
|
100 | 101 |
for key in d.keys() if key not in exclude) |
101 | 102 |
|
102 | 103 |
counter = 1 |
... | ... | |
113 | 114 |
print_str += ': ' |
114 | 115 |
if isinstance(val, dict): |
115 | 116 |
print(print_str) |
116 |
print_dict(val, |
|
117 |
print_dict( |
|
118 |
val, |
|
117 | 119 |
exclude=exclude, |
118 | 120 |
ident=margin + ident, |
119 | 121 |
with_enumeration=recursive_enumeration, |
120 | 122 |
recursive_enumeration=recursive_enumeration) |
121 | 123 |
elif isinstance(val, list): |
122 | 124 |
print(print_str) |
123 |
print_list(val, |
|
125 |
print_list( |
|
126 |
val, |
|
124 | 127 |
exclude=exclude, |
125 | 128 |
ident=margin + ident, |
126 | 129 |
with_enumeration=recursive_enumeration, |
... | ... | |
129 | 132 |
print print_str + ' ' + unicode(val).strip() |
130 | 133 |
|
131 | 134 |
|
132 |
def print_list(l, |
|
135 |
def print_list( |
|
136 |
l, |
|
133 | 137 |
exclude=(), |
134 | 138 |
ident=0, |
135 | 139 |
with_enumeration=False, |
... | ... | |
155 | 159 |
|
156 | 160 |
if l: |
157 | 161 |
try: |
158 |
margin = max(len(unicode(item).strip()) for item in l\
|
|
159 |
if not (isinstance(item, dict)\
|
|
160 |
or isinstance(item, list)\
|
|
162 |
margin = max(len(unicode(item).strip()) for item in l |
|
163 |
if not (isinstance(item, dict) |
|
164 |
or isinstance(item, list) |
|
161 | 165 |
or item in exclude)) |
162 | 166 |
except ValueError: |
163 | 167 |
margin = (2 + len(unicode(len(l)))) if enumerate else 1 |
... | ... | |
176 | 180 |
if isinstance(item, dict): |
177 | 181 |
if with_enumeration: |
178 | 182 |
print(prefix) |
179 |
print_dict(item, |
|
183 |
print_dict( |
|
184 |
item, |
|
180 | 185 |
exclude=exclude, |
181 | 186 |
ident=margin + ident, |
182 | 187 |
with_enumeration=recursive_enumeration, |
... | ... | |
184 | 189 |
elif isinstance(item, list): |
185 | 190 |
if with_enumeration: |
186 | 191 |
print(prefix) |
187 |
print_list(item, |
|
192 |
print_list( |
|
193 |
item, |
|
188 | 194 |
exclude=exclude, |
189 | 195 |
ident=margin + ident, |
190 | 196 |
with_enumeration=recursive_enumeration, |
... | ... | |
214 | 220 |
return True |
215 | 221 |
|
216 | 222 |
|
217 |
def print_items(items, |
|
223 |
def print_items( |
|
224 |
items, |
|
218 | 225 |
title=('id', 'name'), |
219 | 226 |
with_enumeration=False, |
220 | 227 |
with_redundancy=False, |
... | ... | |
408 | 415 |
yield |
409 | 416 |
|
410 | 417 |
if __name__ == '__main__': |
411 |
examples = ['la_la le_le li_li', |
|
418 |
examples = [ |
|
419 |
'la_la le_le li_li', |
|
412 | 420 |
'\'la la\' \'le le\' \'li li\'', |
413 | 421 |
'\'la la\' le_le \'li li\'', |
414 | 422 |
'la_la \'le le\' li_li', |
... | ... | |
427 | 435 |
'"la \'le le\' la"', |
428 | 436 |
'\'la "le le" la\'', |
429 | 437 |
'\'la "la" la\' "le \'le\' le" li_"li"_li', |
430 |
'\'\' \'L\' "" "A"' |
|
431 |
] |
|
438 |
'\'\' \'L\' "" "A"'] |
|
432 | 439 |
|
433 | 440 |
for i, example in enumerate(examples): |
434 | 441 |
print('%s. Split this: (%s)' % (i + 1, example)) |
b/kamaki/clients/__init__.py | ||
---|---|---|
111 | 111 |
self.base_url = base_url |
112 | 112 |
self.token = token |
113 | 113 |
self.headers = {} |
114 |
self.DATE_FORMATS = ["%a %b %d %H:%M:%S %Y", |
|
115 |
"%A, %d-%b-%y %H:%M:%S GMT", |
|
116 |
"%a, %d %b %Y %H:%M:%S GMT"] |
|
114 |
self.DATE_FORMATS = [ |
|
115 |
'%a %b %d %H:%M:%S %Y', |
|
116 |
'%A, %d-%b-%y %H:%M:%S GMT', |
|
117 |
'%a, %d %b %Y %H:%M:%S GMT'] |
|
117 | 118 |
self.http_client = http_client |
118 | 119 |
|
119 | 120 |
def _init_thread_limit(self, limit=1): |
... | ... | |
123 | 124 |
|
124 | 125 |
def _watch_thread_limit(self, threadlist): |
125 | 126 |
recvlog.debug('# running threads: %s' % len(threadlist)) |
126 |
if self._elapsed_old > self._elapsed_new\ |
|
127 |
and self._thread_limit < self.POOL_SIZE: |
|
127 |
if ( |
|
128 |
self._elapsed_old > self._elapsed_new) and ( |
|
129 |
self._thread_limit < self.POOL_SIZE): |
|
128 | 130 |
self._thread_limit += 1 |
129 | 131 |
elif self._elapsed_old < self._elapsed_new and self._thread_limit > 1: |
130 | 132 |
self._thread_limit -= 1 |
... | ... | |
161 | 163 |
def set_default_header(self, name, value): |
162 | 164 |
self.http_client.headers.setdefault(name, value) |
163 | 165 |
|
164 |
def request(self, |
|
166 |
def request( |
|
167 |
self, |
|
165 | 168 |
method, |
166 | 169 |
path, |
167 | 170 |
async_headers={}, |
... | ... | |
193 | 196 |
|
194 | 197 |
self.http_client.url = self.base_url |
195 | 198 |
self.http_client.path = path |
196 |
r = self.http_client.perform_request(method, |
|
199 |
r = self.http_client.perform_request( |
|
200 |
method, |
|
197 | 201 |
data, |
198 | 202 |
async_headers, |
199 | 203 |
async_params) |
... | ... | |
223 | 227 |
errstr = '%s' % err |
224 | 228 |
if not errstr: |
225 | 229 |
errstr = ('%s' % type(err))[7:-2] |
226 |
raise ClientError('%s\n' % errstr,
|
|
227 |
status=getattr(err, 'status', 0) or getattr(err, 'errno', 0))
|
|
230 |
status = getattr(err, 'status', getattr(err, 'errno', 0))
|
|
231 |
raise ClientError('%s\n' % errstr, status=status)
|
|
228 | 232 |
|
229 | 233 |
self.http_client.reset_headers() |
230 | 234 |
self.http_client.reset_params() |
b/kamaki/clients/compute.py | ||
---|---|---|
98 | 98 |
r = self.servers_post(json_data=req) |
99 | 99 |
except ClientError as err: |
100 | 100 |
try: |
101 |
tmp_err = err.details if isinstance(err.details, list)\ |
|
102 |
else unicode(err.details).split(',') |
|
101 |
if isinstance(err.details, list): |
|
102 |
tmp_err = err.details |
|
103 |
else: |
|
104 |
tmp_err = unicode(err.details).split(',') |
|
103 | 105 |
tmp_err = tmp_err[0].split(':') |
104 | 106 |
tmp_err = tmp_err[2].split('"') |
105 | 107 |
err.message = tmp_err[1] |
... | ... | |
161 | 163 |
:returns: dict of updated key:val metadata |
162 | 164 |
""" |
163 | 165 |
req = {'meta': {key: val}} |
164 |
r = self.servers_put(server_id, |
|
166 |
r = self.servers_put( |
|
167 |
server_id, |
|
165 | 168 |
'meta/' + key, |
166 | 169 |
json_data=req, |
167 | 170 |
success=201) |
... | ... | |
229 | 232 |
try: |
230 | 233 |
return r.json['image'] |
231 | 234 |
except KeyError: |
232 |
raise ClientError('Image not available', 404, |
|
233 |
details='Image %d not found or not accessible')
|
|
235 |
raise ClientError('Image not available', 404, details=[
|
|
236 |
'Image %d not found or not accessible'])
|
|
234 | 237 |
|
235 | 238 |
def delete_image(self, image_id): |
236 | 239 |
""" |
b/kamaki/clients/compute_rest_api.py | ||
---|---|---|
70 | 70 |
path = path4url('servers', server_id, command) |
71 | 71 |
return self.delete(path, success=success, **kwargs) |
72 | 72 |
|
73 |
def servers_post(self, |
|
74 |
server_id='', command='', json_data=None, success=202, **kwargs): |
|
73 |
def servers_post( |
|
74 |
self, |
|
75 |
server_id='', |
|
76 |
command='', |
|
77 |
json_data=None, |
|
78 |
success=202, |
|
79 |
**kwargs): |
|
75 | 80 |
"""POST base_url/servers[/server_id]/[command] request |
76 | 81 |
|
77 | 82 |
:param server_id: integer (as int or str) |
... | ... | |
95 | 100 |
path = path4url('servers', server_id, command) |
96 | 101 |
return self.post(path, data=data, success=success, **kwargs) |
97 | 102 |
|
98 |
def servers_put(self, |
|
99 |
server_id='', command='', json_data=None, success=204, **kwargs): |
|
103 |
def servers_put( |
|
104 |
self, |
|
105 |
server_id='', |
|
106 |
command='', |
|
107 |
json_data=None, |
|
108 |
success=204, |
|
109 |
**kwargs): |
|
100 | 110 |
"""PUT base_url/servers[/server_id]/[command] request |
101 | 111 |
|
102 | 112 |
:param server_id: integer (as int or str) |
... | ... | |
168 | 178 |
path = path4url('images', image_id, command) |
169 | 179 |
return self.delete(path, success=success, **kwargs) |
170 | 180 |
|
171 |
def images_post(self, |
|
172 |
image_id='', command='', json_data=None, success=201, **kwargs): |
|
181 |
def images_post( |
|
182 |
self, |
|
183 |
image_id='', |
|
184 |
command='', |
|
185 |
json_data=None, |
|
186 |
success=201, |
|
187 |
**kwargs): |
|
173 | 188 |
"""POST base_url/images[/image_id]/[command] request |
174 | 189 |
|
175 | 190 |
:param image_id: string |
... | ... | |
193 | 208 |
path = path4url('images', image_id, command) |
194 | 209 |
return self.post(path, data=data, success=success, **kwargs) |
195 | 210 |
|
196 |
def images_put(self, |
|
197 |
image_id='', command='', json_data=None, success=201, **kwargs): |
|
211 |
def images_put( |
|
212 |
self, |
|
213 |
image_id='', |
|
214 |
command='', |
|
215 |
json_data=None, |
|
216 |
success=201, |
|
217 |
**kwargs): |
|
198 | 218 |
"""PUT base_url/images[/image_id]/[command] request |
199 | 219 |
|
200 | 220 |
:param image_id: string |
Also available in: Unified diff