Commit 364f4fc1 authored by Alain Takoudjou's avatar Alain Takoudjou

add request clone recipe for clone instance

This new recipe allow to request an instance with a first software type, which is
called clone instance. Then as soon the instance is ready (connection parameter is
published) then request method will now request the instance normally.

It's used to install clone stack in a partition, the clone stack will sync data
then when all done publish a paramter to say that the instance can be requested
with the real software type.
parent e2bd5191
...@@ -166,6 +166,7 @@ setup(name=name, ...@@ -166,6 +166,7 @@ setup(name=name,
'readline = slapos.recipe.readline:Recipe', 'readline = slapos.recipe.readline:Recipe',
'redis.server = slapos.recipe.redis:Recipe', 'redis.server = slapos.recipe.redis:Recipe',
'request = slapos.recipe.request:Recipe', 'request = slapos.recipe.request:Recipe',
'request.clone = slapos.recipe.request:RequestClone',
'request.serialised = slapos.recipe.request:Serialised', 'request.serialised = slapos.recipe.request:Serialised',
'request.edge = slapos.recipe.request:RequestEdge', 'request.edge = slapos.recipe.request:RequestEdge',
'requestoptional = slapos.recipe.request:RequestOptional', 'requestoptional = slapos.recipe.request:RequestOptional',
......
...@@ -32,6 +32,7 @@ from slapos import slap as slapmodule ...@@ -32,6 +32,7 @@ from slapos import slap as slapmodule
from slapos.slap import SoftwareProductCollection from slapos.slap import SoftwareProductCollection
import slapos.recipe.librecipe.generic as librecipe import slapos.recipe.librecipe.generic as librecipe
import traceback import traceback
import os
SOFTWARE_PRODUCT_NAMESPACE = "product." SOFTWARE_PRODUCT_NAMESPACE = "product."
DEFAULT_SOFTWARE_TYPE = 'RootSoftwareInstance' DEFAULT_SOFTWARE_TYPE = 'RootSoftwareInstance'
...@@ -294,3 +295,77 @@ class RequestEdge(Recipe): ...@@ -294,3 +295,77 @@ class RequestEdge(Recipe):
update = install update = install
class RequestClone(Recipe):
"""
Request one instance, then change software type as soon a return parameter exists.
"""
def __init__(self, buildout, name, options):
self.path = os.path.join(buildout['buildout']['directory'],
'.%s-request-clone-%s' % (options['partition-id'],
options['name']))
# A way to save force clone request and not apply force at every run of buildout
self.reclone_check_path = os.path.join(buildout['buildout']['directory'],
'.%s-force-clone-%s' % (options['partition-id'],
options['name']))
# say if clone instance event if instance already exists
check_force = options.get('clone-force-deploy', 'false').lower() \
in librecipe.GenericBaseRecipe.TRUE_VALUES
if not check_force and os.path.exists(self.reclone_check_path):
os.remove(self.reclone_check_path)
if check_force and not os.path.exists(self.reclone_check_path):
with open(self.reclone_check_path, 'w') as f:
f.write('Clone on existing instance')
if os.path.exists(self.path):
os.remove(self.path)
if os.path.exists(self.path):
super(RequestClone, self).__init__(buildout, name, options)
else:
# Request clone instance untill clone-return parameters are OK
software_type = options['software-type']
options['software-type'] = options['clone-software-type']
for param in options.get('return', '').split():
options['connection-%s' % param] = ''
options['return'] = options['clone-return']
super(RequestClone, self).__init__(buildout, name, options)
retun_key = 'connection-%s' % options['clone-return']
if self.failed is None and options.has_key(retun_key) and \
options[retun_key]:
with open(self.path, 'w') as f:
f.write('Clone %s is ready.' % options['name'])
# Raise, next run should be OK
raise Exception("Instance clone %s is ready and should be requested "\
"with software type '%s'" % (options['name'], software_type))
def install(self):
if os.path.exists(self.path):
return super(RequestClone, self).install()
else:
if self._raise_request_exception_formatted:
self.logger.warning('Clone request failed.')
if not isinstance(self._raise_request_exception, slapmodule.NotFoundError):
# full traceback for optional 'not found' is too verbose and confusing
self.logger.debug(self._raise_request_exception_formatted)
elif self.failed is not None:
# Check instance status to know if instance has been deployed
try:
if self.instance._computer_id is not None:
status = self.instance.getState()
else:
status = 'not ready yet'
except (slapmodule.NotFoundError, slapmodule.ServerError, slapmodule.ResourceNotReady):
status = 'not ready yet'
except AttributeError:
status = 'unknown'
error_message = 'Connection parameter %s not found. '\
'Requested instance is currently %s. If this error persists, '\
'check status of this instance.' % (self.failed, status)
self.logger.warning(error_message)
return []
update = install
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