Commit 7f8136c4 authored by Stavros Sachtouris's avatar Stavros Sachtouris
Browse files

Merge branch 'feature-astakosclient-docs' into hotfix-0.12.1

Conflicts:
	README.Upgrade
	kamaki/clients/compute/__init__.py
parents f2051b93 9d84caa4
......@@ -65,9 +65,23 @@ project (Astakos)
modify Modify a project
terminate Terminate a project (special privileges needed)
application Application management commands
membership Project membership management commands
reinstate Reinstate a terminated project (special privileges needed)
membership (Astakos)
--------------------
.. code-block:: text
info Details on a membership
enroll Enroll somebody to a project you manage
join Join a project
list List all memberships
accept Accept a membership for a project you manage
leave Leave a project you have membership to
remove Remove a membership for a project you manage
reject Reject a membership for a project you manage
cancel Cancel your (probably pending) membership to a project
quota (Account/Astakos)
-----------------------
......
......@@ -12,3 +12,4 @@ Examples
examplesdir/imageregister
examplesdir/server
examplesdir/network
examplesdir/astakos
Astakos
=======
`Astakos <http://www.synnefo.org/docs/synnefo/latest/astakos-api-guide.html>`_
is the synnefo implementation of a variant of OpenStack Keystone with custom
extentions. Kamaki offer tools for managing Astakos information.
.. node:: The underlying library that calls the API is part of the synnefo
and it is called 'astakosclient'
User
----
The *authenticate* command will send a token to the server, for authentication.
Be default, the token provided in the cloud configuration (config file) will be
used:
.. code-block:: console
$ kamaki user authenticate
...
endpoints:
SNF:uiURL: https://example.com/ui/
versionId:
region: default
publicURL: https://example.com/admin
endpoints_links:
type: admin
name: cyclades_admin
user:
roles_links:
id: s0m3-u53r-1d
roles:
id: 1
name: default
name: Example User
To authenticate other users, provide their token, as shown bellow:
.. code-block:: console
$ kamaki user add z01db3rgs-u53r-t0k3n
...
endpoints:
SNF:uiURL: https://example.com/ui/
versionId:
region: default
publicURL: https://example.com/admin
endpoints_links:
type: admin
name: cyclades_admin
user:
roles_links:
id: z01db3rgs-u53r-1d
roles:
id: 1
name: default
name: Dr. Harold Zoidberg
$ kamaki user list
s0m5-u53r-1d Example User
z01db3rgs-u53r-1d Dr. Harold Zoidberg
At any time, get the current user's information, or provide a user id for
information on any existing user. In the following example, "Example User" is
the current user, meaning that all kamaki commands will run for him/her.
.. code-block:: console
$ kamaki user info
roles_links:
id: s0m3-u53r-1d
roles:
id: 1
name: default
name: Example User
$ kamaki user info --uuid=z01db3rgs-u53r-1d
roles_links:
id: z01db3rgs-u53r-1d
roles:
id: 1
name: default
name: EDr. Harold Zoidberg
You can switch between authenticated users
.. code-block:: console
$ kamaki user select z01db3rgs-u53r-1d
Are you sure? [y/N]: y
Use the *uuid2name* and *name2uuid* commands to map uuids to usernames and vice
versa.
.. code-block:: console
$ kamaki user uuid2name z01db3rgs-u53r-1d s0m3-u53r-1d
z01db3rgs-u53r-1d: zoidberg@planetexpress.com
s0m3-u53r-1d: someuser@example.com
Quotas and resources
--------------------
Each user is assigned a set of limits on various resources:
.. code-block:: console
$ kamaki quota list
system:
cyclades.disk:
usage: 0B
limit: 100GiB
pending: 0B
cyclades.vm:
usage: 0
limit: 2
pending: 0
pithos.diskspace:
usage: 5.11GiB
limit: 50GiB
pending: 0B
cyclades.ram:
usage: 0B
limit: 8GiB
pending: 0B
cyclades.cpu:
usage: 0
limit: 8
pending: 0
cyclades.network.private:
usage: 0
limit: 5
pending: 0
If the information above is not clear, use *resource list* for descriptions
fetched fresh from the server:
.. code-block:: console
$ kamaki resource list
cyclades.disk:
service: cyclades_compute
description: Virtual machine disk size
unit: bytes
allow_in_projects: True
cyclades.vm:
service: cyclades_compute
description: Number of virtual machines
unit: None
allow_in_projects: True
pithos.diskspace:
service: pithos_object-store
description: Pithos account diskspace
unit: bytes
allow_in_projects: True
cyclades.ram:
service: cyclades_compute
description: Virtual machine memory size
unit: bytes
allow_in_projects: True
cyclades.cpu:
service: cyclades_compute
description: Number of virtual machine processors
unit: None
allow_in_projects: True
cyclades.network.private:
service: cyclades_compute
description: Number of private networks
unit: None
allow_in_projects: True
Projects
--------
If the standard policy of a synnefo deployment does not meet the needs of an
organization, they should make a request for a *synnefo project*.
First, create a file with the project specification. The specification should
be in json format, as described at the
`project API <http://www.synnefo.org/docs/synnefo/latest/project-api-guide.html#create-a-project>`_
(see "Example request").
Let's request a project of 48 CPUs, with an 8 CPU limit per member. Also 200GB
storage space per user, without a project limit.
.. code-block:: console
$ cat > my_project.txt
{
"name": "My example project",
"homepage": "http://www.exampleorganization.org",
"description": "An example testing project",
"comments": "We need more CPUs and more disk space",
"end_date": "2031-02-13",
"resources": {
"cyclades.vm": {
"project_capacity": 48,
"member_capacity": 8
},
"pithos.diskspace": {
"project_capacity": None,
"member_capacity": 53687091200
}
}
}
$ cat my_project.txt | kamaki project create
List all the projects to see if our project is listed
.. code-block:: console
$ kamaki project list
1 newtitle.film.example.com
end_date: 2014-03-31T00:00:00+00:00
description: Our new film project
join_policy: auto
max_members: None
applicant: s0m3-4pp1ic4n7
leave_policy: auto
creation_date: 2013-01-31T09:36:04.061130+00:00
application: 4
state: active
start_date: 2013-01-31T00:00:00+00:00
owner: s0m3-4pp1ic4n7
homepage: http://example.com/film
resources:
29 many.quotas
end_date: 2013-12-12T00:00:00+00:00
description: I need more quotas
join_policy: moderated
max_members: 10
applicant: s0m3-u53r-1d
leave_policy: auto
creation_date: 2013-02-14T09:26:23.034177+00:00
application: 108
state: active
start_date: 2013-02-14T00:00:00+00:00
owner: s0m3-u53r-1d
homepage: http://example.com
resources:
cyclades.disk:
member_capacity: 109951162777600
project_capacity: None
cyclades.vm:
member_capacity: 1000
project_capacity: None
cyclades.cpu:
member_capacity: 2000
project_capacity: None
cyclades.ram:
member_capacity: 4398046511104
project_capacity: None
pithos.diskspace:
member_capacity: 107374182400
project_capacity: None
cyclades.floating_ip:
member_capacity: 1000
project_capacity: None
No, our project is not in the list yet, probably because we wait for (manual)
authorization.
To get information on a project:
.. code-block:: console
$ kamaki project info 29
name: many.quotas
id: 29
end_date: 2013-12-12T00:00:00+00:00
description: I need more quotas
join_policy: moderated
max_members: 10
applicant: s0m3-u53r-1d
leave_policy: auto
creation_date: 2013-02-14T09:26:23.034177+00:00
application: 108
state: active
start_date: 2013-02-14T00:00:00+00:00
owner: s0m3-u53r-1d
homepage: http://example.com
resources:
cyclades.disk:
member_capacity: 109951162777600
project_capacity: None
cyclades.vm:
member_capacity: 1000
project_capacity: None
cyclades.cpu:
member_capacity: 2000
project_capacity: None
cyclades.ram:
member_capacity: 4398046511104
project_capacity: None
pithos.diskspace:
member_capacity: 107374182400
project_capacity: None
cyclades.floating_ip:
member_capacity: 1000
project_capacity: None
Project membership
------------------
Assuming that our project has been approved and assigned the id 42, we can now
see its details and assign users to benefit from it.
.. code-block:: console
$ kamaki project info 42
name: My example project
id: 42
end_date: 2031-02-13T00:00:00+00:00
description: An example testing project
commends: We need more CPUs and more disk space
join_policy: moderated
applicant: s0m3-u53r-1d
leave_policy: auto
creation_date: <NOW>
application: 109
state: active
start_date: <NOW>
owner: s0m3-u53r-1d
homepage: http://example.com
resources:
cyclades.disk:
member_capacity: 107374182400
project_capacity: None
cyclades.vm:
member_capacity: 2
project_capacity: None
cyclades.cpu:
member_capacity: 8
project_capacity: 48
cyclades.ram:
member_capacity: 6442450944
project_capacity: None
pithos.diskspace:
member_capacity: 53687091200
project_capacity: None
cyclades.floating_ip:
member_capacity: 2
project_capacity: None
Great! Now, we should allow some users to benefit from this project:
.. code-block:: console
$ kamaki membership enroll 42 my_favorite@user.example.com
Membership id: 128345
$ kamaki membership enroll 42 that_guy@user.example.com
Membership id: 128346
$ kamaki membership list --with-project-id=42
128345
42 my_favorite@user.example.com OK
238346
42 that_guy@user.example.com OK
We changed our minds: we don't want the last user to be part of the project:
.. code-block:: console
$ kamaki membership remove 238346 "Our cooperation was not productive"
Later, the removed user attempts to apply for our project:
.. code-block:: console
that_guy$ kamaki membership join 42
We may reject his application:
.. code-block:: console
$ kamaki memebrship list
128345
42 my_favorite@user.example.com OK
238347
42 that_guy@user.example.com PENDING
$ kamaki membership reject 238347 "Not in need of a new partner"
or accept:
.. code-block:: console
$ kamaki membership accept 238347
In the later case, the user decided to leave the project:
.. code-block:: console
that_guy$ kamaki membership leave 42
......@@ -38,6 +38,9 @@ user
project
Astakos project API commands
membership
Astakos project membership API commands
quota
Astakos/Account API commands for quotas
......@@ -146,6 +149,19 @@ project
* membership Project membership management commands
* reinstate Reinstate a terminated project (special privileges needed)
membership
**********
* info Details on a membership
* enroll Enroll somebody to a project you manage
* join Join a project
* list List all memberships
* accept Accept a membership for a project you manage
* leave Leave a project you have membership to
* remove Remove a membership for a project you manage
* reject Reject a membership for a project you manage
* cancel Cancel your (probably pending) membership to a project
quota
*****
......
......@@ -41,7 +41,7 @@ from kamaki.cli.history import History
from kamaki.cli.utils import print_dict, red, magenta, yellow
from kamaki.cli.errors import CLIError, CLICmdSpecError
from kamaki.cli import logger
from kamaki.clients.astakos import AstakosClient as AuthCachedClient
from kamaki.clients.astakos import CachedAstakosClient
from kamaki.clients import ClientError
_help = False
......@@ -308,7 +308,7 @@ def init_cached_authenticator(config_argument, cloud, logger):
if auth_base:
auth_base.authenticate(token)
else:
tmp_base = AuthCachedClient(url, token)
tmp_base = CachedAstakosClient(url, token)
from kamaki.cli.commands import _command_init
fake_cmd = _command_init(dict(config=config_argument))
fake_cmd.client = auth_base
......@@ -496,7 +496,7 @@ def is_non_API(parser):
return False
def main(foo):
def main(func):
def wrap():
try:
exe = basename(argv[0])
......@@ -517,7 +517,7 @@ def main(foo):
global _colors
exclude = ['ansicolors'] if not _colors == 'on' else []
suggest_missing(exclude=exclude)
foo(exe, parser)
func(exe, parser)
except CLIError as err:
print_error_message(err)
if _debug:
......
......@@ -42,19 +42,19 @@ from sys import stdin, stdout, stderr
log = get_logger(__name__)
def DontRaiseKeyError(foo):
def DontRaiseKeyError(func):
def wrap(*args, **kwargs):
try:
return foo(*args, **kwargs)
return func(*args, **kwargs)
except KeyError:
return None
return wrap
def addLogSettings(foo):
def addLogSettings(func):
def wrap(self, *args, **kwargs):
try:
return foo(self, *args, **kwargs)
return func(self, *args, **kwargs)
finally:
self._set_log_params()
return wrap
......
......@@ -52,6 +52,8 @@ quota_commands = CommandTree(
resource_commands = CommandTree(
'resource', 'Astakos/Account API commands for resources')
project_commands = CommandTree('project', 'Astakos project API commands')
membership_commands = CommandTree(
'membership', 'Astakos project membership API commands')
# Optional
......@@ -64,20 +66,21 @@ commission_commands = CommandTree(
_commands = [
user_commands, quota_commands, resource_commands, project_commands,
service_commands, commission_commands, endpoint_commands]
service_commands, commission_commands, endpoint_commands,
membership_commands]
def with_temp_token(foo):
""" Set token to self.client.token, run foo, recover old token """
def with_temp_token(func):
""" Set token to self.client.token, run func, recover old token """
def wrap(self, *args, **kwargs):
try:
token = kwargs.pop('token')
except KeyError:
raise CLISyntaxError('A token is needed for %s' % foo)
raise CLISyntaxError('A token is needed for %s' % func)
token_bu = self.client.token
try:
self.client.token = token or token_bu
return foo(self, *args, **kwargs)
return func(self, *args, **kwargs)
finally:
self.client.token = token_bu
return wrap
......@@ -604,9 +607,9 @@ _project_specs = """{
"""
def apply_notification(foo):
def apply_notification(func):
def wrap(self, *args, **kwargs):
r = foo(self, *args, **kwargs)
r = func(self, *args, **kwargs)
self.writeln('Application is submitted successfully')
return r
return wrap
......@@ -821,13 +824,13 @@ class project_application_cancel(_application_action):
action = 'cancel'
@command(project_commands)
class project_membership(_init_synnefo_astakosclient):
@command(membership_commands)
class membership(_init_synnefo_astakosclient):
"""Project membership management commands"""
@command(project_commands)
class project_membership_list(_init_synnefo_astakosclient, _optional_json):
@command(membership_commands)
class membership_list(_init_synnefo_astakosclient, _optional_json):
"""List all memberships"""
arguments = dict(
......@@ -844,8 +847,8 @@ class project_membership_list(_init_synnefo_astakosclient, _optional_json):
self._run()
@command(project_commands)
class project_membership_info(_init_synnefo_astakosclient, _optional_json):
@command(membership_commands)
class membership_info(_init_synnefo_astakosclient, _optional_json):
"""Details on a membership"""
@errors.generic.all
......@@ -874,38 +877,38 @@ class _membership_action(_init_synnefo_astakosclient, _optional_json):
self._run(membership_id, quote_a_reason)
@command(project_commands)
class project_membership_leave(_membership_action):
@command(membership_commands)
class membership_leave(_membership_action):
"""Leave a project you have membership to"""
action = 'leave'
@command(project_commands)
class project_membership_cancel(_membership_action):
@command(membership_commands)
class membership_cancel(_membership_action):
"""Cancel your (probably pending) membership to a project"""
action = 'cancel'
@command(project_commands)
class project_membership_accept(_membership_action):
@command(membership_commands)
class membership_accept(_membership_action):
"""Accept a membership for a project you manage"""
action = 'accept'
@command(project_commands)
class project_membership_reject(_membership_action):
@command(membership_commands)
class membership_reject(_membership_action):
"""Reject a membership for a project you manage"""
action = 'reject'
@command(project_commands)
class project_membership_remove(_membership_action):
@command(membership_commands)
class membership_remove(_membership_action):
"""Remove a membership for a project you manage"""
action = 'remove'
@command(project_commands)
class project_membership_join(_init_synnefo_astakosclient):
@command(membership_commands)
class membership_join(_init_synnefo_astakosclient):
"""Join a project"""
@errors.generic.all
......@@ -914,12 +917,12 @@ class project_membership_join(_init_synnefo_astakosclient):
self.writeln(self.client.join_project(project_id))
def main(self, project_id):
super(project_membership_join, self)._run()
super(membership_join, self)._run()
self._run(project_id)