sync images across deployments
diff --git a/planetstack/core/models/image.py b/planetstack/core/models/image.py
index b4803e2..db01e1b 100644
--- a/planetstack/core/models/image.py
+++ b/planetstack/core/models/image.py
@@ -1,13 +1,23 @@
import os
from django.db import models
from core.models import PlCoreBase
+from core.models import Deployment
# Create your models here.
class Image(PlCoreBase):
- image_id = models.CharField(max_length=256, unique=True)
name = models.CharField(max_length=256, unique=True)
disk_format = models.CharField(max_length=256)
container_format = models.CharField(max_length=256)
+ path = models.CharField(max_length=256, null=True, blank=True, help_text="Path to image on local disk")
def __unicode__(self): return u'%s' % (self.name)
+
+class ImageDeployments(PlCoreBase):
+ image = models.ForeignKey(Image)
+ deployment = models.ForeignKey(Deployment)
+ glance_image_id = models.CharField(null=True, blank=True, max_length=200, help_text="Glance image id")
+
+ def __unicode__(self): return u'%s %s' % (self.image, self.deployment)
+
+
diff --git a/planetstack/observer/steps/__init__.py b/planetstack/observer/steps/__init__.py
index eabf46c..2ef6922 100644
--- a/planetstack/observer/steps/__init__.py
+++ b/planetstack/observer/steps/__init__.py
@@ -12,4 +12,5 @@
from .sync_roles import SyncRoles
from .sync_nodes import SyncNodes
from .sync_images import SyncImages
+from .sync_image_deployments import SyncImageDeployments
from .garbage_collector import GarbageCollector
diff --git a/planetstack/observer/steps/sync_image_deployments.py b/planetstack/observer/steps/sync_image_deployments.py
new file mode 100644
index 0000000..e611044
--- /dev/null
+++ b/planetstack/observer/steps/sync_image_deployments.py
@@ -0,0 +1,44 @@
+import os
+import base64
+from collections import defaultdict
+from django.db.models import F, Q
+from planetstack.config import Config
+from observer.openstacksyncstep import OpenStackSyncStep
+from core.models.deployment import Deployment
+from core.models.image import Image, ImageDeployments
+
+class SyncImageDeployments(OpenStackSyncStep):
+ provides=[ImageDeployments]
+ requested_interval=0
+
+ def fetch_pending(self):
+ # ensure images are available across all deployments
+ image_deployments = ImageDeployments.objects.all()
+ image_deploy_lookup = defaultdict(list)
+ for image_deployment in image_deployments:
+ image_deploy_lookup[image_deployment.image].append(image_deployment.deployment)
+
+ all_deployments = Deployment.objects.all()
+ for image in Image.objects.all():
+ expected_deployments = all_deployments
+ for expected_deployment in expected_deployments:
+ if image not in image_deploy_lookup or \
+ expected_deployment not in image_deploy_lookup[image]:
+ id = ImageDeployments(image=image, deployment=expected_deployment)
+ id.save()
+
+ # now we return all images that need to be enacted
+ return ImageDeployments.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
+
+ def sync_record(self, image_deployment):
+ driver = self.driver.admin_driver(deployment=image_deployment.deployment.name)
+ image = {
+ 'name': image_deployment.image.name,
+ 'is_public': True,
+ 'disk_format': 'raw',
+ 'container_format': 'bare',
+ 'file': image_deployment.image.path,
+ }
+ glance_image = driver.shell.glance.add_image(image)
+ image_deployment.glance_image_id = glance_image['id']
+ image_deployment.save()
diff --git a/planetstack/observer/steps/sync_images.py b/planetstack/observer/steps/sync_images.py
index 2dbd74d..6ee53fe 100644
--- a/planetstack/observer/steps/sync_images.py
+++ b/planetstack/observer/steps/sync_images.py
@@ -10,20 +10,28 @@
requested_interval=0
def fetch_pending(self):
+ # get list of images on disk
+ images_path = Config().observer_images_directory
+ available_images = {}
+ for f in os.listdir(images_path):
+ if os.path.isfile(os.path.join(images_path ,f)):
+ available_images[f] = os.path.join(images_path ,f)
+
images = Image.objects.all()
image_names = [image.name for image in images]
+
+ for image_name in available_images:
+ #remove file extension
+ clean_name = ".".join(image_name.split('.')[:-1])
+ if image_name not in image_names:
+ image = Image(name=clean_name,
+ disk_format='raw',
+ container_format='bare',
+ path = available_images[image_name])
+ image.save()
- new_images = []
- glance_images = self.driver.shell.glance.get_images()
- for glance_image in glance_images:
- if glance_image['name'] not in image_names:
- image = Image(image_id=glance_image['id'],
- name=glance_image['name'],
- disk_format=glance_image['disk_format'],
- container_format=glance_image['container_format'])
- new_images.append(image)
-
- return new_images
+
+ return Image.objects.filter(Q(enacted__lt=F('updated')) | Q(enacted=None))
def sync_record(self, image):
image.save()