Commit 4e0e6580 authored by Dionysis Grigoropoulos's avatar Dionysis Grigoropoulos Committed by Christos Stavrakakis
Browse files

cyclades: Bug fixes in volume related commands

* Add a check to both name length and disk template length in
snf-manage volume-type-create.
* Add a check for the metadata length of snapshots.
* Add a generic try/except clause to handle Pithos responses.
* Add --user/--public options in snapshot-show/image-show.
* Add a boolean "snapshot" field in image-list.
* Remove unused user agrument from backend.get_snapshot().
* Remove --wait option from snapshot-create.
* Various typo fixes.
parent ddc98573
......@@ -37,8 +37,10 @@ log = logging.getLogger(__name__)
class VolumeType(models.Model):
NAME_LENGTH = 255
DISK_TEMPLATE_LENGTH = 32
name = models.CharField("Name", max_length=NAME_LENGTH)
disk_template = models.CharField('Disk Template', max_length=32)
disk_template = models.CharField('Disk Template',
max_length=DISK_TEMPLATE_LENGTH)
deleted = models.BooleanField('Deleted', default=False)
def __str__(self):
......
......@@ -48,7 +48,7 @@ class Command(SynnefoCommand):
port = common.get_resource("port", args[0])
display_mails = options['displaymails']
pprint.pprint_port(port, display_mails=display_mail,
pprint.pprint_port(port, display_mails=display_mails,
stdout=self.stdout)
self.stdout.write('\n\n')
......
......@@ -58,7 +58,7 @@ class Command(SynnefoCommand):
" --port id:<port_id>"
" --port floatingip:<floatingip_id>."),
make_option("--volume", dest="volumes", action="append",
help="--volume size=<size>, --volume id=<volume_id"
help="--volume size=<size>, --volume id=<volume_id>"
", --volume size=<size>,image=<image_id>"
", --volume size=<size>,snapshot=<snapshot_id>",
default=[]),
......
......@@ -49,6 +49,7 @@ from django.utils.encoding import smart_unicode, smart_str
from pithos.backends.base import NotAllowedError, VersionNotExists, QuotaError
from pithos.backends.util import PithosBackendPool
from snf_django.lib.api import faults
from snf_django.management.utils import parse_bool
Location = namedtuple("ObjectLocation", ["account", "container", "path"])
......@@ -199,26 +200,30 @@ class PlanktonBackend(object):
return self._get_image(uuid)
def _update_metadata(self, uuid, location, metadata, replace=False):
prefixed = self._prefix_and_validate_metadata(metadata)
account, container, path = location
self.backend.update_object_meta(self.user, account, container, path,
PLANKTON_DOMAIN, prefixed, replace)
logger.debug("User '%s' updated image '%s', metadata: '%s'", self.user,
uuid, prefixed)
def _prefix_and_validate_metadata(self, metadata):
_prefixed_metadata = self._prefix_metadata(metadata)
prefixed = {}
for k, v in _prefixed_metadata.items():
# Encode to UTF-8
k, v = smart_unicode(k), smart_unicode(v)
# Check the length of key/value
if len(k) > 128:
if len(k) > MAX_META_KEY_LENGTH:
raise faults.BadRequest('Metadata keys should be less than %s'
' characters' % MAX_META_KEY_LENGTH)
if len(v) > 256:
if len(v) > MAX_META_VALUE_LENGTH:
raise faults.BadRequest('Metadata values should be less than'
' %scharacters.'
' %s characters.'
% MAX_META_VALUE_LENGTH)
prefixed[k] = v
account, container, path = location
self.backend.update_object_meta(self.user, account, container, path,
PLANKTON_DOMAIN, prefixed, replace)
logger.debug("User '%s' updated image '%s', metadata: '%s'", self.user,
uuid, prefixed)
return prefixed
def _get_raw_metadata(self, uuid, version=None, check_image=True):
"""Get info and metadata in Plankton doamin for the Pithos object.
......@@ -448,6 +453,7 @@ class PlanktonBackend(object):
# Snapshots
@handle_pithos_backend
def register_snapshot(self, name, mapfile, size, metadata):
metadata = self._prefix_and_validate_metadata(metadata)
snapshot_id = self.backend.register_object_map(
user=self.user,
account=self.user,
......@@ -467,7 +473,7 @@ class PlanktonBackend(object):
return [s for s in _snapshots if s["is_snapshot"]]
@handle_pithos_backend
def get_snapshot(self, user, snapshot_uuid):
def get_snapshot(self, snapshot_uuid):
snap = self._get_image(snapshot_uuid)
if snap.get("is_snapshot", False) is False:
raise faults.ItemNotFound("Snapshots '%s' does not exist" %
......@@ -520,7 +526,8 @@ def image_to_dict(location, metadata, permissions):
image["size"] = metadata["bytes"]
image['owner'] = account
image["store"] = u"pithos"
image["is_snapshot"] = metadata.pop(PLANKTON_PREFIX + "is_snapshot", False)
image["is_snapshot"] = parse_bool(metadata.pop(PLANKTON_PREFIX +
"is_snapshot", False))
image["version"] = metadata["version"]
# Permissions
......
......@@ -39,10 +39,10 @@ class Command(SynnefoCommand):
images = backend._list_images(user)
images.sort(key=lambda x: x['created_at'], reverse=True)
headers = ("id", "name", "user.uuid", "public")
headers = ("id", "name", "user.uuid", "public", "snapshot")
table = []
for img in images:
fields = (img["id"], img["name"], img["owner"],
str(img["is_public"]))
str(img["is_public"]), str(img["is_snapshot"]))
table.append(fields)
pprint_table(self.stdout, table, headers)
......@@ -33,6 +33,12 @@ class Command(SynnefoCommand):
default=None,
help="The UUID of the owner of the image. Required"
" if image is not public"),
make_option(
'--public',
dest='public',
default=False,
action="store_true",
help="Use this option if the image is public"),
)
@common.convert_api_faults
......@@ -41,9 +47,18 @@ class Command(SynnefoCommand):
if len(args) != 1:
raise CommandError("Please provide an image ID")
image_id = args[0]
#user_id = options["userid"]
user_id = options["userid"]
public = options["public"]
if (user_id is None) and (public is False):
raise CommandError("'user' option or 'public' option is required")
try:
with PlanktonBackend(user_id) as backend:
image = backend.get_image(image_id)
except:
raise CommandError("An error occurred, verify that image or "
"user ID are valid")
with PlanktonBackend(None) as backend:
image = backend.get_image(image_id)
utils.pprint_table(out=self.stdout, table=[image.values()],
headers=image.keys(), vertical=True)
......@@ -26,13 +26,6 @@ class Command(SynnefoCommand):
help = "Create a snapshot from the specified volume"
option_list = SynnefoCommand.option_list + (
make_option(
'--wait',
dest='wait',
default="True",
choices=["True", "False"],
metavar="True|False",
help="Wait for Ganeti job to complete."),
make_option(
"--name",
dest="name",
......@@ -58,7 +51,7 @@ class Command(SynnefoCommand):
description = options.get("description")
if description is None:
description = "Snapshot of Volume '%s" % volume.id
description = "Snapshot of Volume '%s'" % volume.id
snapshot = snapshots.create(volume.userid,
volume,
......
......@@ -32,6 +32,12 @@ class Command(SynnefoCommand):
default=None,
help="The UUID of the owner of the snapshot. Required"
"if snapshot is not public"),
make_option(
'--public',
dest='public',
default=False,
action="store_true",
help="Use this option if the snapshot is public"),
)
@common.convert_api_faults
......@@ -42,8 +48,17 @@ class Command(SynnefoCommand):
snapshot_id = args[0]
userid = options["userid"]
public = options["public"]
if (userid is None) and (public is False):
raise CommandError("'user' option or 'public' option is required")
try:
with PlanktonBackend(userid) as backend:
snapshot = backend.get_snapshot(snapshot_id)
except:
raise CommandError("An error occurred, verify that snapshot and "
"user ID are valid")
with PlanktonBackend(userid) as backend:
snapshot = backend.get_snapshot(userid, snapshot_id)
utils.pprint_table(out=self.stdout, table=[snapshot.values()],
headers=snapshot.keys(), vertical=True)
......@@ -53,7 +53,13 @@ class Command(SynnefoCommand):
if disk_template is None:
raise CommandError("Please specify the disk template of the volume"
" type.")
if len(name) > VolumeType.NAME_LENGTH:
raise CommandError("Name of the volume type can't be more than %s"
" characters." % VolumeType.NAME_LENGTH)
if len(disk_template) > VolumeType.DISK_TEMPLATE_LENGTH:
raise CommandError("Disk template of the volume type can't be more"
" than %s characters." %
VolumeType.DISK_TEMPLATE_LENGTH)
try:
vtype = VolumeType.objects.create(name=name,
disk_template=disk_template)
......
......@@ -22,8 +22,6 @@ from synnefo.volume import util
log = logging.getLogger(__name__)
PLANKTON_PREFIX = "plankton:"
PROPERTY_PREFIX = "property:"
SNAPSHOTS_MAPFILE_PREFIX = "archip:"
......@@ -65,14 +63,14 @@ def create(user_id, volume, name, description, metadata, force=False):
transaction.commit()
snapshot_metadata = {
PLANKTON_PREFIX + "name": name,
PLANKTON_PREFIX + "status": "CREATING",
PLANKTON_PREFIX + "disk_format": "diskdump",
PLANKTON_PREFIX + "container_format": "bare",
PLANKTON_PREFIX + "is_snapshot": True,
"name": name,
"status": "CREATING",
"disk_format": "diskdump",
"container_format": "bare",
"is_snapshot": True,
# Snapshot specific
PLANKTON_PREFIX + "description": description,
PLANKTON_PREFIX + "volume_id": volume.id,
"description": description,
"volume_id": volume.id,
}
# Snapshots are used as images. We set the most important properties
......@@ -86,8 +84,8 @@ def create(user_id, volume, name, description, metadata, force=False):
.values_list("meta_key", "meta_value"))
metadata.update(vm_metadata)
for key, val in metadata.items():
snapshot_metadata[PLANKTON_PREFIX + PROPERTY_PREFIX + key] = val
snapshot_properties = PlanktonBackend._prefix_properties(metadata)
snapshot_metadata.update(snapshot_properties)
# Generate a name for the Pithos file. Also, generate a name for the
# Archipelago mapfile.
......
......@@ -62,7 +62,7 @@ def get_volume_type(volume_type_id, for_update=False, include_deleted=False,
def get_snapshot(user_id, snapshot_id, exception=faults.ItemNotFound):
try:
with backend.PlanktonBackend(user_id) as b:
return b.get_snapshot(user_id, snapshot_id)
return b.get_snapshot(snapshot_id)
except faults.ItemNotFound:
raise exception("Snapshot %s not found" % snapshot_id)
......
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