Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
itminedu
kamaki
Commits
18555878
Commit
18555878
authored
Jan 14, 2013
by
Stavros Sachtouris
Browse files
Merge branch 'develop' into feature-quota
Conflicts: kamaki/cli/commands/history_cli.py kamaki/cli/commands/pithos_cli.py
parents
131f4e86
16c895db
Changes
23
Expand all
Hide whitespace changes
Inline
Side-by-side
docs/man/kamaki.rst
View file @
18555878
...
...
@@ -157,7 +157,7 @@ store commands
* append Append local file to (existing) remote object
* cat Print a file to console
* copy Copy an object
* create Create a container
or a directory object
* create Create a container
* delete Delete a container [or an object]
* delgroup Delete a user group on an account
* delmeta Delete an existing metadatum of account [, container [or object]]
...
...
@@ -182,6 +182,7 @@ store commands
* setquota Set new quota (in KB) for account [or container]
* setversioning Set new versioning (auto, none) for account [or container]
* sharers List the accounts that share objects with default account
* touch Create an empty file
* truncate Truncate remote file up to a size
* unpublish Unpublish an object
* upload Upload a file
...
...
kamaki/cli/__init__.py
View file @
18555878
...
...
@@ -38,7 +38,7 @@ from inspect import getargspec
from
kamaki.cli.argument
import
ArgumentParseManager
from
kamaki.cli.history
import
History
from
kamaki.cli.utils
import
print_dict
,
print_list
,
red
,
magenta
,
yellow
from
kamaki.cli.utils
import
print_dict
,
red
,
magenta
,
yellow
from
kamaki.cli.errors
import
CLIError
_help
=
False
...
...
kamaki/cli/argument.py
View file @
18555878
...
...
@@ -35,6 +35,7 @@ from kamaki.cli.config import Config
from
kamaki.cli.errors
import
CLISyntaxError
,
raiseCLIError
from
kamaki.cli.utils
import
split_input
from
logging
import
getLogger
from
datetime
import
datetime
as
dtm
from
argparse
import
ArgumentParser
,
ArgumentError
...
...
@@ -236,6 +237,43 @@ class IntArgument(ValueArgument):
details
=
[
'Value %s not an int'
%
newvalue
]))
class
DateArgument
(
ValueArgument
):
"""
:value type: a string formated in an acceptable date format
:value returns: same date in first of DATE_FORMATS
"""
DATE_FORMATS
=
[
"%a %b %d %H:%M:%S %Y"
,
"%A, %d-%b-%y %H:%M:%S GMT"
,
"%a, %d %b %Y %H:%M:%S GMT"
]
INPUT_FORMATS
=
DATE_FORMATS
+
[
"%d-%m-%Y"
,
"%H:%M:%S %d-%m-%Y"
]
@
property
def
value
(
self
):
return
getattr
(
self
,
'_value'
,
self
.
default
)
@
value
.
setter
def
value
(
self
,
newvalue
):
if
newvalue
is
None
:
return
self
.
_value
=
self
.
format_date
(
newvalue
)
def
format_date
(
self
,
datestr
):
for
format
in
self
.
INPUT_FORMATS
:
try
:
t
=
dtm
.
strptime
(
datestr
,
format
)
except
ValueError
:
continue
self
.
_value
=
t
.
strftime
(
self
.
DATE_FORMATS
[
0
])
return
raiseCLIError
(
None
,
'Date Argument Error'
,
details
=
'%s not a valid date. correct formats:
\n\t
%s'
\
%
(
datestr
,
self
.
INPUT_FORMATS
))
class
VersionArgument
(
FlagArgument
):
"""A flag argument with that prints current version"""
...
...
kamaki/cli/command_shell.py
View file @
18555878
...
...
@@ -100,6 +100,15 @@ class Shell(Cmd):
def
set_prompt
(
self
,
new_prompt
):
self
.
prompt
=
'%s%s%s'
%
(
self
.
_prefix
,
new_prompt
,
self
.
_suffix
)
def
cmdloop
(
self
):
while
True
:
try
:
Cmd
.
cmdloop
(
self
)
except
KeyboardInterrupt
:
print
(
' - interrupted'
)
continue
break
def
do_exit
(
self
,
line
):
print
(
''
)
if
self
.
prompt
[
len
(
self
.
_prefix
):
-
len
(
self
.
_suffix
)]
\
...
...
@@ -170,7 +179,8 @@ class Shell(Cmd):
cls
=
subcmd
.
get_class
()
ldescr
=
getattr
(
cls
,
'long_description'
,
''
)
if
subcmd
.
path
==
'history_run'
:
instance
=
cls
(
dict
(
cmd_parser
.
arguments
),
instance
=
cls
(
dict
(
cmd_parser
.
arguments
),
self
.
cmd_tree
)
else
:
instance
=
cls
(
dict
(
cmd_parser
.
arguments
))
...
...
@@ -191,10 +201,12 @@ class Shell(Cmd):
arg
.
value
=
getattr
(
cmd_parser
.
parsed
,
name
,
arg
.
default
)
exec_cmd
(
instance
,
[
term
for
term
in
cmd_parser
.
unparsed
\
if
not
term
.
startswith
(
'-'
)]
,
exec_cmd
(
instance
,
cmd_parser
.
unparsed
,
cmd_parser
.
parser
.
print_help
)
#[term for term in cmd_parser.unparsed\
# if not term.startswith('-')],
except
(
ClientError
,
CLIError
)
as
err
:
print_error_message
(
err
)
elif
(
'-h'
in
cmd_args
or
'--help'
in
cmd_args
)
\
...
...
@@ -281,6 +293,7 @@ class Shell(Cmd):
try
:
self
.
cmdloop
()
except
Exception
:
except
Exception
as
e
:
print
(
'(%s)'
%
e
)
from
traceback
import
print_stack
print_stack
()
kamaki/cli/commands/__init__.py
View file @
18555878
...
...
@@ -39,11 +39,54 @@ recvlog = logging.getLogger('clients.recv')
class
_command_init
(
object
):
def
__init__
(
self
,
arguments
=
{}):
self
.
arguments
=
arguments
if
hasattr
(
self
,
'arguments'
):
arguments
.
update
(
self
.
arguments
)
self
.
arguments
=
dict
(
arguments
)
try
:
self
.
config
=
self
.
get_argument
(
'config'
)
self
.
config
=
self
[
'config'
]
#self.config = self.get_argument('config')
except
KeyError
:
pass
def
get_argument
(
self
,
argterm
):
def
__getitem__
(
self
,
argterm
):
"""
:param argterm: (str) the name/label of an argument in self.arguments
:returns: the value of the corresponding Argument (not the argument
object)
:raises KeyError: if argterm not in self.arguments of this object
"""
return
self
.
arguments
[
argterm
].
value
def
__setitem__
(
self
,
argterm
,
arg
):
"""Install an argument as argterm
If argterm points to another argument, the other argument is lost
:param argterm: (str)
:param arg: (Argument)
"""
if
not
hasattr
(
self
,
'arguments'
):
self
.
arguments
=
{}
self
.
arguments
[
argterm
]
=
arg
def
get_argument_object
(
self
,
argterm
):
"""
:param argterm: (str) the name/label of an argument in self.arguments
:returns: the arument object
:raises KeyError: if argterm not in self.arguments of this object
"""
return
self
.
arguments
[
argterm
]
def
get_argument
(
self
,
argterm
):
"""
:param argterm: (str) the name/label of an argument in self.arguments
:returns: the value of the arument object
:raises KeyError: if argterm not in self.arguments of this object
"""
return
self
[
argterm
]
kamaki/cli/commands/astakos_cli.py
View file @
18555878
...
...
@@ -74,6 +74,7 @@ class astakos_authenticate(_astakos_init):
'If not, set a token:'
,
' 1.(permanent): /config set token <token>'
,
' 2.(temporary): rerun with <token> parameter'
])
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
print_dict
(
reply
)
kamaki/cli/commands/config_cli.py
View file @
18555878
...
...
@@ -39,26 +39,39 @@ from kamaki.cli.command_tree import CommandTree
config_cmds
=
CommandTree
(
'config'
,
'Configuration commands'
)
_commands
=
[
config_cmds
]
about_options
=
'
\n
About options:
\
\n
. syntax: [group.]option
\
\n
. example: store.account
\
\n
. special case: <option> is equivalent to global.<option>
\
\n
. configuration file syntax:
\
\n
. [group]
\
\n
. option=value
\
\n
. (more options can be set per group)'
@
command
(
config_cmds
)
class
config_list
(
_command_init
):
"""List configuration options"""
def
__init__
(
self
,
arguments
=
{}):
super
(
config_list
,
self
).
__init__
(
arguments
)
self
.
arguments
[
'all'
]
=
FlagArgument
(
'include default values'
,
'-a'
)
"""List all configuration options
FAQ:
Q: I haven't set any options!
A: Defaults are used (override with /config set )
Q: There are more options than I have set
A: Default options remain if not explicitly replaced or deleted
"""
def
main
(
self
):
include_defaults
=
self
.
get_argument
(
'all'
)
for
section
in
sorted
(
self
.
config
.
sections
()):
items
=
self
.
config
.
items
(
section
,
include_defaults
)
items
=
self
.
config
.
items
(
section
)
for
key
,
val
in
sorted
(
items
):
print
(
'%s.%s = %s'
%
(
section
,
key
,
val
))
@
command
(
config_cmds
)
class
config_get
(
_command_init
):
"""Show a configuration option"""
"""Show a configuration option
"""
__doc__
+=
about_options
def
main
(
self
,
option
):
section
,
sep
,
key
=
option
.
rpartition
(
'.'
)
...
...
@@ -72,6 +85,8 @@ class config_get(_command_init):
class
config_set
(
_command_init
):
"""Set a configuration option"""
__doc__
+=
about_options
def
main
(
self
,
option
,
value
):
section
,
sep
,
key
=
option
.
rpartition
(
'.'
)
section
=
section
or
'global'
...
...
@@ -82,11 +97,20 @@ class config_set(_command_init):
@
command
(
config_cmds
)
class
config_delete
(
_command_init
):
"""Delete a configuration option (and use the default value)"""
"""Delete a configuration option
Default values are not removed by default. To alter this behavior in a
session, use --default.
"""
arguments
=
dict
(
default
=
FlagArgument
(
'Remove default value as well (persists until end of sesion)'
,
'--default'
)
)
def
main
(
self
,
option
):
section
,
sep
,
key
=
option
.
rpartition
(
'.'
)
section
=
section
or
'global'
self
.
config
.
remove_option
(
section
,
key
)
self
.
config
.
remove_option
(
section
,
key
,
self
[
'default'
]
)
self
.
config
.
write
()
self
.
config
.
reload
()
kamaki/cli/commands/cyclades_cli.py
View file @
18555878
This diff is collapsed.
Click to expand it.
kamaki/cli/commands/history_cli.py
View file @
18555878
...
...
@@ -80,8 +80,8 @@ class _init_history(_command_init):
class
history_show
(
_init_history
):
"""Show intersession command history
---
*
With no parameters : pick all commands in history records
*
With:
-
With no parameters : pick all commands in history records
-
With:
. 1. <order-id> : pick the <order-id>th command
. 2. <order-id-1>-<order-id-2> : pick all commands ordered in the range
. [<order-id-1> - <order-id-2>]
...
...
@@ -93,17 +93,14 @@ class history_show(_init_history):
. -5--2 means : the last 5 commands except the last 2
"""
def
__init__
(
self
,
arguments
=
{}):
super
(
self
.
__class__
,
self
).
__init__
(
arguments
)
self
.
arguments
[
'limit'
]
=
\
IntArgument
(
'number of lines to show'
,
'-n'
,
default
=
0
)
self
.
arguments
[
'match'
]
=
\
ValueArgument
(
'show lines that match all given terms'
,
'--match'
)
arguments
=
dict
(
limit
=
IntArgument
(
'number of lines to show'
,
'-n'
,
default
=
0
),
match
=
ValueArgument
(
'show lines that match given terms'
,
'--match'
)
)
def
main
(
self
,
*
cmd_ids
):
super
(
self
.
__class__
,
self
).
main
()
ret
=
self
.
history
.
get
(
match_terms
=
self
.
get_argument
(
'match'
),
limit
=
self
.
get_argument
(
'limit'
))
ret
=
self
.
history
.
get
(
match_terms
=
self
[
'match'
],
limit
=
self
[
'limit'
])
if
not
cmd_ids
:
print
(
''
.
join
(
ret
))
...
...
kamaki/cli/commands/image_cli.py
View file @
18555878
...
...
@@ -34,19 +34,24 @@
from
kamaki.cli
import
command
from
kamaki.cli.command_tree
import
CommandTree
from
kamaki.cli.errors
import
raiseCLIError
from
kamaki.cli.utils
import
print_dict
,
print_items
,
bold
from
kamaki.cli.utils
import
print_dict
,
print_items
from
kamaki.clients.image
import
ImageClient
,
ClientError
from
kamaki.cli.argument
import
\
FlagArgument
,
ValueArgument
,
KeyValueArgument
,
IntArgument
from
kamaki.cli.argument
import
FlagArgument
,
ValueArgument
,
KeyValueArgument
from
kamaki.cli.argument
import
IntArgument
from
kamaki.cli.commands.cyclades_cli
import
_init_cyclades
from
kamaki.cli.commands.cyclades_cli
import
raise_if_connection_error
from
kamaki.cli.commands
import
_command_init
image_cmds
=
CommandTree
(
'image'
,
image_cmds
=
CommandTree
(
'image'
,
'Compute/Cyclades or Glance API image commands'
)
_commands
=
[
image_cmds
]
about_image_id
=
[
'To see a list of available image ids: /image list'
]
class
_init_image
(
_command_init
):
def
main
(
self
):
try
:
...
...
@@ -65,84 +70,108 @@ class _init_image(_command_init):
class
image_public
(
_init_image
):
"""List public images"""
def
__init__
(
self
,
arguments
=
{}):
super
(
image_public
,
self
).
__init__
(
arguments
)
self
.
arguments
[
'detail'
]
=
FlagArgument
(
'show detailed output'
,
'-l'
)
self
.
arguments
[
'container_format'
]
=
\
ValueArgument
(
'filter by container format'
,
'--container-format'
)
self
.
arguments
[
'disk_format'
]
=
\
ValueArgument
(
'filter by disk format'
,
'--disk-format'
)
self
.
arguments
[
'name'
]
=
ValueArgument
(
'filter by name'
,
'--name'
)
self
.
arguments
[
'size_min'
]
=
\
IntArgument
(
'filter by minimum size'
,
'--size-min'
)
self
.
arguments
[
'size_max'
]
=
\
IntArgument
(
'filter by maximum size'
,
'--size-max'
)
self
.
arguments
[
'status'
]
=
\
ValueArgument
(
'filter by status'
,
'--status'
)
self
.
arguments
[
'order'
]
=
\
ValueArgument
(
'order by FIELD (use a - prefix to reverse order)'
,
'--order'
,
default
=
''
)
arguments
=
dict
(
detail
=
FlagArgument
(
'show detailed output'
,
'-l'
),
container_format
=
ValueArgument
(
'filter by container format'
,
'--container-format'
),
disk_format
=
ValueArgument
(
'filter by disk format'
,
'--disk-format'
),
name
=
ValueArgument
(
'filter by name'
,
'--name'
),
size_min
=
IntArgument
(
'filter by minimum size'
,
'--size-min'
),
size_max
=
IntArgument
(
'filter by maximum size'
,
'--size-max'
),
status
=
ValueArgument
(
'filter by status'
,
'--status'
),
order
=
ValueArgument
(
'order by FIELD ( - to reverse order)'
,
'--order'
,
default
=
''
),
limit
=
IntArgument
(
'limit the number of images in list'
,
'-n'
),
more
=
FlagArgument
(
'output results in pages (-n to set items per page, default 10)'
,
'--more'
)
)
def
main
(
self
):
super
(
self
.
__class__
,
self
).
main
()
filters
=
{}
for
arg
in
(
'container_format'
,
'disk_format'
,
'name'
,
'size_min'
,
'size_max'
,
'status'
):
val
=
self
.
get_argument
(
arg
)
if
val
is
not
None
:
filters
[
arg
]
=
val
order
=
self
.
get_argument
(
'order'
)
detail
=
self
.
get_argument
(
'detail'
)
for
arg
in
set
(
[
'container_format'
,
'disk_format'
,
'name'
,
'size_min'
,
'size_max'
,
'status'
]).
intersection
(
self
.
arguments
):
filters
[
arg
]
=
self
[
arg
]
order
=
self
[
'order'
]
detail
=
self
[
'detail'
]
try
:
images
=
self
.
client
.
list_public
(
detail
,
filters
,
order
)
except
ClientError
as
ce
:
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
print_items
(
images
,
title
=
(
'name'
,),
with_enumeration
=
True
)
if
self
[
'more'
]:
print_items
(
images
,
title
=
(
'name'
,),
with_enumeration
=
True
,
page_size
=
self
[
'limit'
]
if
self
[
'limit'
]
else
10
)
elif
self
[
'limit'
]:
print_items
(
images
[:
self
[
'limit'
]],
title
=
(
'name'
,),
with_enumeration
=
True
)
else
:
print_items
(
images
,
title
=
(
'name'
,),
with_enumeration
=
True
)
@
command
(
image_cmds
)
class
image_meta
(
_init_image
):
"""Get image metadata"""
"""Get image metadata
Image metadata include:
- image file information (location, size, etc.)
- image information (id, name, etc.)
- image os properties (os, fs, etc.)
"""
def
main
(
self
,
image_id
):
super
(
self
.
__class__
,
self
).
main
()
try
:
image
=
self
.
client
.
get_meta
(
image_id
)
except
ClientError
as
err
:
except
ClientError
as
ce
:
if
ce
.
status
==
404
:
raiseCLIError
(
ce
,
'No image with id %s found'
%
image_id
,
details
=
about_image_id
)
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
print_dict
(
image
)
@
command
(
image_cmds
)
class
image_register
(
_init_image
):
"""(Re)Register an image
call with --update to update image properties
"""
def
__init__
(
self
,
arguments
=
{}):
super
(
image_register
,
self
).
__init__
(
arguments
)
self
.
arguments
[
'checksum'
]
=
\
ValueArgument
(
'set image checksum'
,
'--checksum'
)
self
.
arguments
[
'container_format'
]
=
\
ValueArgument
(
'set container format'
,
'--container-format'
)
self
.
arguments
[
'disk_format'
]
=
\
ValueArgument
(
'set disk format'
,
'--disk-format'
)
self
.
arguments
[
'id'
]
=
ValueArgument
(
'set image ID'
,
'--id'
)
self
.
arguments
[
'owner'
]
=
\
ValueArgument
(
'set image owner (admin only)'
,
'--owner'
)
self
.
arguments
[
'properties'
]
=
\
KeyValueArgument
(
parsed_name
=
'--property'
,
help
=
'add property in key=value form (can be repeated)'
)
self
.
arguments
[
'is_public'
]
=
\
FlagArgument
(
'mark image as public'
,
'--public'
)
self
.
arguments
[
'size'
]
=
IntArgument
(
'set image size'
,
'--size'
)
self
.
arguments
[
'update'
]
=
FlagArgument
(
'update an existing image properties'
,
'--update'
)
"""(Re)Register an image"""
arguments
=
dict
(
checksum
=
ValueArgument
(
'set image checksum'
,
'--checksum'
),
container_format
=
ValueArgument
(
'set container format'
,
'--container-format'
),
disk_format
=
ValueArgument
(
'set disk format'
,
'--disk-format'
),
id
=
ValueArgument
(
'set image ID'
,
'--id'
),
owner
=
ValueArgument
(
'set image owner (admin only)'
,
'--owner'
),
properties
=
KeyValueArgument
(
'add property in key=value form (can be repeated)'
,
'--property'
),
is_public
=
FlagArgument
(
'mark image as public'
,
'--public'
),
size
=
IntArgument
(
'set image size'
,
'--size'
),
update
=
FlagArgument
(
'update existing image properties'
,
'--update'
)
)
def
main
(
self
,
name
,
location
):
super
(
self
.
__class__
,
self
).
main
()
...
...
@@ -159,24 +188,27 @@ class image_register(_init_image):
location
=
'pithos://%s/%s/%s'
%
(
account
,
container
,
location
)
params
=
{}
for
key
in
(
'checksum'
,
'container_format'
,
'disk_format'
,
'id'
,
'owner'
,
'size'
,
'is_public'
):
val
=
self
.
get_argument
(
key
)
if
val
is
not
None
:
params
[
key
]
=
val
update
=
self
.
get_argument
(
'update'
)
properties
=
self
.
get_argument
(
'properties'
)
for
key
in
set
(
[
'checksum'
,
'container_format'
,
'disk_format'
,
'id'
,
'owner'
,
'size'
,
'is_public'
]).
intersection
(
self
.
arguments
):
params
[
key
]
=
self
[
key
]
try
:
if
update
:
properties
=
self
[
'properties'
]
if
self
[
'update'
]:
self
.
client
.
reregister
(
location
,
name
,
params
,
properties
)
else
:
self
.
client
.
register
(
name
,
location
,
params
,
properties
)
except
ClientError
as
ce
:
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
...
...
@@ -189,24 +221,28 @@ class image_members(_init_image):
super
(
self
.
__class__
,
self
).
main
()
try
:
members
=
self
.
client
.
list_members
(
image_id
)
except
ClientError
as
ce
:
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
for
member
in
members
:
print
(
member
[
'member_id'
])
print_items
(
members
)
@
command
(
image_cmds
)
class
image_shared
(
_init_image
):
"""List
shared images
"""
"""List
images shared by a member
"""
def
main
(
self
,
member
):
super
(
self
.
__class__
,
self
).
main
()
try
:
images
=
self
.
client
.
list_shared
(
member
)
except
ClientError
as
ce
:
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
for
image
in
images
:
print
(
image
[
'image_id'
])
print_items
(
images
)
@
command
(
image_cmds
)
...
...
@@ -217,6 +253,13 @@ class image_addmember(_init_image):
super
(
self
.
__class__
,
self
).
main
()
try
:
self
.
client
.
add_member
(
image_id
,
member
)
except
ClientError
as
ce
:
if
ce
.
status
==
404
:
raiseCLIError
(
ce
,
'No image with id %s found'
%
image_id
,
details
=
about_image_id
)
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
...
...
@@ -229,6 +272,13 @@ class image_delmember(_init_image):
super
(
self
.
__class__
,
self
).
main
()
try
:
self
.
client
.
remove_member
(
image_id
,
member
)
except
ClientError
as
ce
:
if
ce
.
status
==
404
:
raiseCLIError
(
ce
,
'No image with id %s found'
%
image_id
,
details
=
about_image_id
)
raise_if_connection_error
(
ce
,
base_url
=
'image.url'
)
raiseCLIError
(
ce
)
except
Exception
as
err
:
raiseCLIError
(
err
)
...
...
@@ -241,6 +291,13 @@ class image_setmembers(_init_image):
super
(
self
.
__class__
,
self
).
main
()
try
:
self
.
client
.
set_members
(
image_id
,
member
)
except
ClientError
as
ce
: