Commit 913a33a2 authored by Christos Stavrakakis's avatar Christos Stavrakakis

Merge branch 'master' into ilias_doc

Conflicts:
	docs/quick-install-admin-guide.rst
parents ea35f1aa 3ec42fe6
......@@ -161,6 +161,32 @@ Then, add those terms-of-use with the snf-manage command:
Your terms have been successfully added and you will see the corresponding link
appearing in the Astakos web pages' footer.
Enabling reCAPTCHA
~~~~~~~~~~~~~~~~~~
Astakos supports the `reCAPTCHA <http://www.google.com/recaptcha>`_ feature.
If enabled, it protects the Astakos forms from bots. To enable the feature, go
to https://www.google.com/recaptcha/admin/create and create your own reCAPTCHA
key pair. Then edit ``/etc/synnefo/20-snf-astakos-app-settings.conf`` and set
the corresponding variables to reflect your newly created key pair. Finally, set
the ``ASTAKOS_RECAPTCHA_ENABLED`` variable to ``True``:
.. code-block:: console
ASTAKOS_RECAPTCHA_PUBLIC_KEY = 'example_recaptcha_public_key!@#$%^&*('
ASTAKOS_RECAPTCHA_PRIVATE_KEY = 'example_recaptcha_private_key!@#$%^&*('
ASTAKOS_RECAPTCHA_ENABLED = True
Restart the service on the Astakos node(s) and you are ready:
.. code-block:: console
# /etc/init.d/gunicorn restart
Checkout your new Sign up page. If you see the reCAPTCHA box, you have setup
everything correctly.
File Storage Service (Pithos)
......
......@@ -102,7 +102,7 @@ You can install apache2 and progresql by running:
.. code-block:: console
# apt-get install apache2 postgresql rabbitmq-server
# apt-get install apache2 postgresql
Make sure to install gunicorn >= v0.12.2. You can do this by installing from
the official debian backports:
......
......@@ -40,6 +40,8 @@ from django.http import HttpResponse
from django.template.loader import render_to_string
from django.utils import simplejson as json
from contextlib import contextmanager
from synnefo.api import util
from synnefo.api.common import method_not_allowed
from synnefo.api.faults import BadRequest, ItemNotFound, ServiceUnavailable
......@@ -104,6 +106,14 @@ def image_to_dict(image, detail=True):
return d
@contextmanager
def image_backend(userid):
backend = ImageBackend(userid)
try:
yield backend
finally:
backend.close()
@api_method('GET')
def list_images(request, detail=False):
# Normal Response Codes: 200, 203
......@@ -114,19 +124,18 @@ def list_images(request, detail=False):
# overLimit (413)
log.debug('list_images detail=%s', detail)
backend = ImageBackend(request.user_uniq)
since = isoparse(request.GET.get('changes-since'))
if since:
images = []
for image in backend.iter():
updated = dateutil.parser.parse(image['updated_at'])
if updated >= since:
images.append(image)
if not images:
return HttpResponse(status=304)
else:
images = backend.list()
with image_backend(request.user_uniq) as backend:
since = isoparse(request.GET.get('changes-since'))
if since:
images = []
for image in backend.iter():
updated = dateutil.parser.parse(image['updated_at'])
if updated >= since:
images.append(image)
if not images:
return HttpResponse(status=304)
else:
images = backend.list()
images = sorted(images, key=lambda x: x['id'])
reply = [image_to_dict(image, detail) for image in images]
......@@ -190,9 +199,8 @@ def delete_image(request, image_id):
# overLimit (413)
log.info('delete_image %s', image_id)
backend = ImageBackend(request.user_uniq)
backend.delete(image_id)
backend.close()
with image_backend(request.user_uniq) as backend:
backend.delete(image_id)
log.info('User %s deleted image %s', request.user_uniq, image_id)
return HttpResponse(status=204)
......@@ -235,9 +243,8 @@ def update_metadata(request, image_id):
properties = image['properties']
properties.update(metadata)
backend = ImageBackend(request.user_uniq)
backend.update(image_id, dict(properties=properties))
backend.close()
with image_backend(request.user_uniq) as backend:
backend.update(image_id, dict(properties=properties))
return util.render_metadata(request, properties, status=201)
......@@ -287,9 +294,8 @@ def create_metadata_item(request, image_id, key):
properties = image['properties']
properties[key] = val
backend = ImageBackend(request.user_uniq)
backend.update(image_id, dict(properties=properties))
backend.close()
with image_backend(request.user_uniq) as backend:
backend.update(image_id, dict(properties=properties))
return util.render_meta(request, {key: val}, status=201)
......@@ -311,8 +317,7 @@ def delete_metadata_item(request, image_id, key):
properties = image['properties']
properties.pop(key, None)
backend = ImageBackend(request.user_uniq)
backend.update(image_id, dict(properties=properties))
backend.close()
with image_backend(request.user_uniq) as backend:
backend.update(image_id, dict(properties=properties))
return HttpResponse(status=204)
......@@ -449,11 +449,15 @@ def delete_server(request, server_id):
return HttpResponse(status=204)
# additional server actions
ARBITRARY_ACTIONS = ['console', 'firewallProfile']
@util.api_method('POST')
def server_action(request, server_id):
req = util.get_request_dict(request)
log.debug('server_action %s %s', server_id, req)
if len(req) != 1:
raise faults.BadRequest("Malformed request")
......@@ -463,7 +467,7 @@ def server_action(request, server_id):
try:
key = req.keys()[0]
if key != 'console':
if key not in ARBITRARY_ACTIONS:
start_action(vm, key_to_action(key))
val = req[key]
assert isinstance(val, dict)
......@@ -480,7 +484,7 @@ def key_to_action(key):
return "STOP"
if key == "delete":
return "DESTROY"
if key == "console":
if key in ARBITRARY_ACTIONS:
return None
else:
return key.upper()
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment