fedimg: Add the initial files for the hotfix, fix copied amis
Signed-off-by: Sayan Chowdhury <sayan.chowdhury2012@gmail.com>
This commit is contained in:
parent
9f74f46187
commit
6752f195d9
2 changed files with 307 additions and 0 deletions
300
files/hotfix/fedimg/ec2imgpublisher.py
Normal file
300
files/hotfix/fedimg/ec2imgpublisher.py
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
# This file is part of fedimg.
|
||||||
|
# Copyright (C) 2014-2017 Red Hat, Inc.
|
||||||
|
#
|
||||||
|
# fedimg is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# fedimg is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public
|
||||||
|
# License along with fedimg; if not, see http://www.gnu.org/licenses,
|
||||||
|
# or write to the Free Software Foundation, Inc.,
|
||||||
|
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
#
|
||||||
|
# Authors: Sayan Chowdhury <sayanchowdhury@fedoraproject.org>
|
||||||
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
|
_log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
import fedimg.messenger
|
||||||
|
|
||||||
|
from fedimg.utils import external_run_command, get_item_from_regex
|
||||||
|
from fedimg.utils import get_image_name_from_ami_name
|
||||||
|
from fedimg.utils import get_image_name_from_ami_name_for_fedmsg
|
||||||
|
from fedimg.services.ec2.ec2base import EC2Base
|
||||||
|
|
||||||
|
|
||||||
|
class EC2ImagePublisher(EC2Base):
|
||||||
|
""" Comment goes here """
|
||||||
|
|
||||||
|
def __init__(self, **kwargs):
|
||||||
|
defaults = {
|
||||||
|
'access_key': None,
|
||||||
|
'compose_id': None,
|
||||||
|
'image_id': None,
|
||||||
|
'image_name': 'Fedora-AMI',
|
||||||
|
'image_url': None,
|
||||||
|
'image_description': 'Fedora AMI Description',
|
||||||
|
'service': 'EC2',
|
||||||
|
'region': None,
|
||||||
|
'secret_key': None,
|
||||||
|
'visibility': 'all',
|
||||||
|
'push_notifications': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
for (prop, default) in defaults.iteritems():
|
||||||
|
setattr(self, prop, kwargs.get(prop, default))
|
||||||
|
|
||||||
|
def _retry_till_image_is_public(self, image):
|
||||||
|
""" Comment goes here """
|
||||||
|
|
||||||
|
driver = self._connect()
|
||||||
|
|
||||||
|
is_image_public = False
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
is_image_public = driver.ex_modify_image_attribute(
|
||||||
|
image,
|
||||||
|
{'LaunchPermission.Add.1.Group': 'all'})
|
||||||
|
except Exception as e:
|
||||||
|
if 'InvalidAMIID.Unavailable' in str(e):
|
||||||
|
# The copy isn't completed yet, so wait for 20 seconds
|
||||||
|
# more.
|
||||||
|
sleep(20)
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
|
||||||
|
return is_image_public
|
||||||
|
|
||||||
|
def _retry_till_snapshot_is_public(self, snapshot):
|
||||||
|
|
||||||
|
driver = self._connect()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
is_snapshot_public = driver.ex_modify_snapshot_attribute(
|
||||||
|
snapshot,
|
||||||
|
{'CreateVolumePermission.Add.1.Group': 'all'})
|
||||||
|
|
||||||
|
if is_snapshot_public:
|
||||||
|
break
|
||||||
|
|
||||||
|
return is_snapshot_public
|
||||||
|
|
||||||
|
|
||||||
|
def _retry_till_snapshot_is_available(self, image):
|
||||||
|
|
||||||
|
driver = self._connect()
|
||||||
|
while True:
|
||||||
|
image = driver.get_image(image.id)
|
||||||
|
snapshot_id = image.extra['block_device_mapping'][0]['ebs']['snapshot_id']
|
||||||
|
|
||||||
|
if snapshot_id:
|
||||||
|
break
|
||||||
|
|
||||||
|
return snapshot_id
|
||||||
|
|
||||||
|
def _generate_dummy_snapshot_object(self, snapshot_id):
|
||||||
|
|
||||||
|
driver = self._connect()
|
||||||
|
|
||||||
|
snapshot_obj = type('', (), {})()
|
||||||
|
snapshot_obj.id = snapshot_id
|
||||||
|
snapshot = driver.list_snapshots(snapshot=snapshot_obj)
|
||||||
|
|
||||||
|
return snapshot
|
||||||
|
|
||||||
|
def _retry_till_blk_mapping_is_available(self, image):
|
||||||
|
|
||||||
|
while True:
|
||||||
|
image = self._connect().get_image(image_id=image.id)
|
||||||
|
blk_mapping = image.extra['block_device_mapping']
|
||||||
|
|
||||||
|
if blk_mapping:
|
||||||
|
return blk_mapping
|
||||||
|
|
||||||
|
def get_snapshot_from_image(self, image):
|
||||||
|
""" Comment goes here """
|
||||||
|
if isinstance(image, str):
|
||||||
|
image_id = image
|
||||||
|
image = self._connect().get_image(image_id)
|
||||||
|
|
||||||
|
blk_mapping = image.extra['block_device_mapping']
|
||||||
|
if not blk_mapping:
|
||||||
|
blk_mapping = self._retry_till_blk_mapping_is_available(image)
|
||||||
|
|
||||||
|
snapshot_id = blk_mapping[0]['ebs']['snapshot_id']
|
||||||
|
if snapshot_id is None:
|
||||||
|
snapshot_id = self._retry_till_snapshot_is_available(image)
|
||||||
|
|
||||||
|
snapshot = self._generate_dummy_snapshot_object(snapshot_id)[0]
|
||||||
|
|
||||||
|
return snapshot
|
||||||
|
|
||||||
|
def get_volume_type_from_image(self, image):
|
||||||
|
if isinstance(image, str):
|
||||||
|
image_id = image
|
||||||
|
image = self._connect().get_image(image_id)
|
||||||
|
|
||||||
|
blk_mapping = image.extra['block_device_mapping']
|
||||||
|
if not blk_mapping:
|
||||||
|
blk_mapping = self._retry_till_blk_mapping_is_available(image)
|
||||||
|
|
||||||
|
return blk_mapping[0]['ebs']['volume_type']
|
||||||
|
|
||||||
|
def get_virt_type_from_image(self, image):
|
||||||
|
return 'hvm'
|
||||||
|
|
||||||
|
def publish_images(self, region_image_mapping=None):
|
||||||
|
""" Comment goes here """
|
||||||
|
|
||||||
|
published_images = []
|
||||||
|
if region_image_mapping is None:
|
||||||
|
return published_images
|
||||||
|
|
||||||
|
for region, image_id in region_image_mapping:
|
||||||
|
self.set_region(region)
|
||||||
|
|
||||||
|
_log.info('Publish image (%s) in %s started' % (image_id, region))
|
||||||
|
image = self._connect().get_image(image_id=image_id)
|
||||||
|
is_image_public = self._retry_till_image_is_public(image)
|
||||||
|
_log.info('Publish image (%s) in %s completed' % (image_id, region))
|
||||||
|
|
||||||
|
_log.info('Publish snaphsot for image (%s) in %s started' % (image_id, region))
|
||||||
|
snapshot = self.get_snapshot_from_image(image)
|
||||||
|
_log.info('Fetched snapshot for image (%s): %s' % (image_id, snapshot.id))
|
||||||
|
is_snapshot_public = self._retry_till_snapshot_is_public(snapshot)
|
||||||
|
_log.info('Publish snaphsot for image (%s) in %s completed' % (image_id, region))
|
||||||
|
|
||||||
|
volume_type = self.get_volume_type_from_image(image)
|
||||||
|
virt_type = self.get_virt_type_from_image(image)
|
||||||
|
|
||||||
|
if self.push_notifications:
|
||||||
|
fedimg.messenger.notify(
|
||||||
|
topic='image.publish',
|
||||||
|
msg=dict(
|
||||||
|
image_name=get_image_name_from_ami_name_for_fedmsg(image.name),
|
||||||
|
image_url=self.image_url,
|
||||||
|
destination=self.region,
|
||||||
|
service=self.service,
|
||||||
|
compose=self.compose_id,
|
||||||
|
extra=dict(
|
||||||
|
id=image.id,
|
||||||
|
virt_type=virt_type,
|
||||||
|
vol_type=volume_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fedimg.messenger.notify(
|
||||||
|
topic='image.upload',
|
||||||
|
msg=dict(
|
||||||
|
image_name=get_image_name_from_ami_name_for_fedmsg(image.name),
|
||||||
|
image_url=self.image_url,
|
||||||
|
destination=self.region,
|
||||||
|
service=self.service,
|
||||||
|
status='completed',
|
||||||
|
compose=self.compose_id,
|
||||||
|
extra=dict(
|
||||||
|
id=image.id,
|
||||||
|
virt_type=virt_type,
|
||||||
|
vol_type=volume_type
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
published_images.append({
|
||||||
|
'image_id': image.id,
|
||||||
|
'is_image_public': is_image_public,
|
||||||
|
'snapshot_id': snapshot.id,
|
||||||
|
'is_snapshot_public': is_snapshot_public,
|
||||||
|
'regions': self.region
|
||||||
|
})
|
||||||
|
|
||||||
|
return published_images
|
||||||
|
|
||||||
|
def copy_images_to_regions(self, image_id=None, base_region=None, regions=None):
|
||||||
|
""" Comment goes here """
|
||||||
|
|
||||||
|
if (image_id is None) or (regions is None) or (base_region is None):
|
||||||
|
return
|
||||||
|
|
||||||
|
counter = 0
|
||||||
|
copied_images = []
|
||||||
|
|
||||||
|
self.set_region(base_region)
|
||||||
|
image = self._connect().get_image(image_id=image_id)
|
||||||
|
if not image:
|
||||||
|
return []
|
||||||
|
|
||||||
|
for region in regions:
|
||||||
|
_log.info('Copy %s to %s started' % (image_id, region))
|
||||||
|
self.set_region(region)
|
||||||
|
self.image_name = get_image_name_from_ami_name(image.name, region)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if counter > 0:
|
||||||
|
self.image_name = re.sub(
|
||||||
|
'\d(?!\d)',
|
||||||
|
lambda x: str(int(x.group(0))+1),
|
||||||
|
self.image_name
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
copied_image = self._connect().copy_image(
|
||||||
|
source_region=base_region,
|
||||||
|
image=image,
|
||||||
|
name=self.image_name,
|
||||||
|
description=self.image_description)
|
||||||
|
|
||||||
|
virt_type = image.extra['virtualization_type']
|
||||||
|
volume_type = image.extra['block_device_mapping'][0]['ebs']['volume_type']
|
||||||
|
|
||||||
|
if self.push_notifications:
|
||||||
|
fedimg.messenger.notify(
|
||||||
|
topic='image.copy',
|
||||||
|
msg=dict(
|
||||||
|
image_name=get_image_name_from_ami_name_for_fedmsg(copied_image.name),
|
||||||
|
destination=self.region,
|
||||||
|
service=self.service,
|
||||||
|
compose_id=self.compose_id,
|
||||||
|
extra=dict(
|
||||||
|
id=copied_image.id,
|
||||||
|
virt_type=virt_type,
|
||||||
|
vol_type=volume_type,
|
||||||
|
source_image_id=image.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
_log.info('Copy %s to %s is completed.' % (image_id, region))
|
||||||
|
copied_images.append({
|
||||||
|
'region': region,
|
||||||
|
'copied_image_id': copied_image.id
|
||||||
|
})
|
||||||
|
break
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
_log.info('Could not register '
|
||||||
|
'with name: %r' % self.image_name)
|
||||||
|
if 'InvalidAMIName.Duplicate' in str(e):
|
||||||
|
counter = counter + 1
|
||||||
|
else:
|
||||||
|
_log.info('Failed')
|
||||||
|
break
|
||||||
|
|
||||||
|
return copied_images
|
||||||
|
|
||||||
|
def deprecate_images(self, image_ids=None, snapshot_perm='all'):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def delete_images(self, image_ids=None, snapshot_perm='all'):
|
||||||
|
raise NotImplementedError
|
|
@ -123,3 +123,10 @@
|
||||||
- fedimg
|
- fedimg
|
||||||
- hotfix
|
- hotfix
|
||||||
|
|
||||||
|
- name: hotfix - copy the ec2imgpublisher.py over to the site-packages
|
||||||
|
copy: src="{{ files }}/hotfix/fedimg/ec2imgpublisher.py" dest=/usr/lib/python2.7/site-packages/fedimg/services/ec2/ec2imgpublisher.py
|
||||||
|
notify:
|
||||||
|
- restart fedmsg-hub
|
||||||
|
tags:
|
||||||
|
- fedimg
|
||||||
|
- hotfix
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue