Commit c650a03e authored by Christos Stavrakakis's avatar Christos Stavrakakis

Make Cyclades work with Archipelago v2 and Pithos

Recent commits have integrated Archipelago v2 mapfiles to Pithos. This
commit updates Cyclades to go along with the recent changes in Pithos.
Specifically, this commit makes the following changes:

* Use the 'mapfile' attribute of the Pithos objects, instead of the old 'hash'
  attribute. Also, this attribute needs no custom prefixing
  ('archip:' or 'pithos:').
* Do not store 'is_snapshot' and 'status' attributes as plankton
  properties. The 'is_snapshot' attribute is now provided from Pithos.
  Also, the 'status' attribute can be derived from the 'available'
  attribute.
* Remove code from 'snf-dispatcher' that used to update the 'status'
  plankton property when the OP_INSTANCE_SNAPSHOT Ganeti job completed.
  This functionality is now covered internally from Pithos.
parent ad53b410
......@@ -160,27 +160,17 @@ def get_image_dict(image_id, user_id):
img = get_image(image_id, user_id)
image["id"] = img["id"]
image["name"] = img["name"]
image["format"] = img["disk_format"]
image["location"] = img["location"]
image["is_snapshot"] = img["is_snapshot"]
image["status"] = img["status"]
image["version"] = img["version"]
image["is_public"] = img["is_public"]
image["status"] = img["status"]
image["owner"] = img["owner"]
image["format"] = img["disk_format"]
image["version"] = img["version"]
size = image["size"] = img["size"]
mapfile = img["mapfile"]
if mapfile.startswith("archip:"):
_, unprefixed_mapfile, = mapfile.split("archip:")
mapfile = unprefixed_mapfile
else:
unprefixed_mapfile = mapfile
mapfile = "pithos:" + mapfile
image["backend_id"] = PITHOSMAP_PREFIX + "/".join([unprefixed_mapfile,
str(size)])
image["mapfile"] = mapfile
mapfile = image["mapfile"] = img["mapfile"]
image["backend_id"] = PITHOSMAP_PREFIX + "/".join([mapfile, str(size)])
properties = img.get("properties", {})
image["metadata"] = dict((key.upper(), val)
......
......@@ -26,7 +26,6 @@ from synnefo import quotas
from synnefo.api.util import release_resource
from synnefo.util.mac2eui64 import mac2eui64
from synnefo.logic import rapi
from synnefo import volume
from logging import getLogger
log = getLogger(__name__)
......@@ -575,13 +574,7 @@ def adopt_instance_disk(server, gnt_disk):
def update_snapshot(snap_id, user_id, job_id, job_status, etime):
"""Update a snapshot based on result of a Ganeti job."""
if job_status in rapi.JOB_STATUS_FINALIZED:
if (job_status == rapi.JOB_STATUS_SUCCESS):
status = "AVAILABLE"
else:
status = "ERROR"
log.debug("Updating status of snapshot '%s' to '%s'", snap_id, status)
volume.util.update_snapshot_status(snap_id, user_id, status=status)
return
@transaction.commit_on_success
......
......@@ -27,7 +27,6 @@ The Plankton attributes are the following:
- owner: the file's account
- properties: stored as user meta prefixed with PROPERTY_PREFIX
- size: the 'bytes' meta
- status: stored as a system meta
- store: is always 'pithos'
- updated_at: the 'modified' meta
"""
......@@ -49,7 +48,6 @@ 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"])
......@@ -383,9 +381,7 @@ class PlanktonBackend(object):
meta.update(self._prefix_properties(properties))
# Add extra metadata
meta["name"] = name
meta["status"] = "AVAILABLE"
meta['created_at'] = str(time())
# meta["is_snapshot"] = False
self._update_metadata(uuid, location, metadata=meta, replace=False)
logger.debug("User '%s' registered image '%s'('%s')", self.user,
......@@ -486,14 +482,6 @@ class PlanktonBackend(object):
def delete_snapshot(self, snapshot_uuid):
self.backend.delete_by_uuid(self.user, snapshot_uuid)
@handle_pithos_backend
def update_status(self, image_uuid, status):
"""Update status of snapshot"""
location, _ = self._get_raw_metadata(image_uuid)
properties = {"status": status.upper()}
self._update_metadata(image_uuid, location, properties, replace=False)
return self._get_image(image_uuid)
def create_url(account, container, name):
"""Create a Pithos URL from the object info"""
......@@ -522,16 +510,17 @@ def image_to_dict(location, metadata, permissions):
image = {}
image["id"] = metadata["uuid"]
image["mapfile"] = metadata["hash"]
image["mapfile"] = metadata["mapfile"]
image["checksum"] = metadata["hash"]
image["location"] = create_url(account, container, name)
image["size"] = metadata["bytes"]
image['owner'] = account
image["store"] = u"pithos"
image["is_snapshot"] = parse_bool(metadata.pop(PLANKTON_PREFIX +
"is_snapshot", False))
image["is_snapshot"] = metadata["is_snapshot"]
image["version"] = metadata["version"]
image["status"] = "AVAILABLE" if metadata.get("available") else "CREATING"
# Permissions
users = list(permissions.get("read", []))
image["is_public"] = "*" in users
......@@ -554,14 +543,13 @@ def image_to_dict(location, metadata, permissions):
key = key.replace(PLANKTON_PREFIX, "")
# Keep only those in plankton metadata
if key in PLANKTON_META:
if key == "status":
image["status"] = val.upper()
if key != "created_at":
# created timestamp is return in 'created_at' field
image[key] = val
elif key.startswith(PROPERTY_PREFIX):
key = key.replace(PROPERTY_PREFIX, "")
properties[key] = val
image["properties"] = properties
return image
......
......@@ -22,8 +22,6 @@ from synnefo.volume import util
log = logging.getLogger(__name__)
SNAPSHOTS_MAPFILE_PREFIX = "archip:"
@transaction.commit_on_success
def create(user_id, volume, name, description, metadata, force=False):
......@@ -64,10 +62,8 @@ def create(user_id, volume, name, description, metadata, force=False):
snapshot_metadata = {
"name": name,
"status": "CREATING",
"disk_format": "diskdump",
"container_format": "bare",
"is_snapshot": True,
# Snapshot specific
"description": description,
"volume_id": volume.id,
......@@ -87,22 +83,20 @@ def create(user_id, volume, name, description, metadata, force=False):
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.
snapshot_pithos_name = generate_snapshot_pithos_name(volume)
mapfile = SNAPSHOTS_MAPFILE_PREFIX + snapshot_pithos_name
# Generate a name for the Archipelago mapfile.
mapfile = generate_mapfile_name(volume)
# Convert size from Gbytes to bytes
size = volume.size << 30
with PlanktonBackend(user_id) as b:
snapshot_id = b.register_snapshot(name=snapshot_pithos_name,
snapshot_id = b.register_snapshot(name=name,
mapfile=mapfile,
size=size,
metadata=snapshot_metadata)
backend.snapshot_instance(volume.machine,
snapshot_name=snapshot_pithos_name,
snapshot_name=mapfile,
snapshot_id=snapshot_id)
snapshot = util.get_snapshot(user_id, snapshot_id)
......@@ -110,8 +104,8 @@ def create(user_id, volume, name, description, metadata, force=False):
return snapshot
def generate_snapshot_pithos_name(volume):
"""Helper function to generate a name for the Pithos file."""
def generate_mapfile_name(volume):
"""Helper function to generate a name for the Archipelago mapfile."""
# time = isoformat(datetime.datetime.now())
return "snf-snap-%s-%s" % (volume.id,
volume.snapshot_counter)
......
......@@ -103,8 +103,3 @@ def volume_to_links(volume_id):
def snapshot_to_links(snapshot_id):
href = join_urls(SNAPSHOTS_URL, str(snapshot_id))
return [{"rel": rel, "href": href} for rel in ("self", "bookmark")]
def update_snapshot_status(snapshot_id, user_id, status):
with backend.PlanktonBackend(user_id) as b:
return b.update_status(snapshot_id, status=status)
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