Support for Heat LoadBalancer and Stack Outputs
Change-Id: If5261fe83967d2d5fbef4f71d4fa3b250b3ce6d7
This commit is contained in:
parent
9feed1b9a5
commit
f49dbfe907
@ -22,23 +22,30 @@ import time
|
||||
import xml_code_engine
|
||||
|
||||
|
||||
def update_cf_stack(engine, context, body, template,
|
||||
mappings, arguments, **kwargs):
|
||||
def update_cf_stack(engine, context, body, template, result=None, **kwargs):
|
||||
command_dispatcher = context['/commandDispatcher']
|
||||
|
||||
callback = lambda result: engine.evaluate_content(
|
||||
body.find('success'), context)
|
||||
def callback(result_value):
|
||||
if result is not None:
|
||||
context[result] = result_value['Result']
|
||||
success_handler = body.find('success')
|
||||
if success_handler is not None:
|
||||
engine.evaluate_content(success_handler, context)
|
||||
|
||||
command_dispatcher.execute(
|
||||
name='cf', command='CreateOrUpdate', template=template,
|
||||
mappings=mappings, arguments=arguments, callback=callback)
|
||||
mappings=kwargs.get('mappings', {}),
|
||||
arguments=kwargs.get('arguments', {}),
|
||||
callback=callback)
|
||||
|
||||
|
||||
def delete_cf_stack(engine, context, body, **kwargs):
|
||||
command_dispatcher = context['/commandDispatcher']
|
||||
|
||||
callback = lambda result: engine.evaluate_content(
|
||||
body.find('success'), context)
|
||||
def callback(result_value):
|
||||
success_handler = body.find('success')
|
||||
if success_handler is not None:
|
||||
engine.evaluate_content(success_handler, context)
|
||||
|
||||
command_dispatcher.execute(
|
||||
name='cf', command='Delete', callback=callback)
|
||||
|
@ -59,8 +59,8 @@ class HeatExecutor(CommandBase):
|
||||
if command == 'CreateOrUpdate':
|
||||
return self._execute_create_update(
|
||||
kwargs['template'],
|
||||
kwargs['mappings'],
|
||||
kwargs['arguments'],
|
||||
kwargs.get('mappings', {}),
|
||||
kwargs.get('arguments', {}),
|
||||
callback)
|
||||
elif command == 'Delete':
|
||||
return self._execute_delete(callback)
|
||||
@ -116,23 +116,24 @@ class HeatExecutor(CommandBase):
|
||||
template=template)
|
||||
log.debug(
|
||||
'Waiting for the stack {0} to be update'.format(self._stack))
|
||||
self._wait_state('UPDATE_COMPLETE')
|
||||
outs = self._wait_state('UPDATE_COMPLETE')
|
||||
log.info('Stack {0} updated'.format(self._stack))
|
||||
else:
|
||||
self._heat_client.stacks.create(
|
||||
stack_name=self._stack,
|
||||
parameters=arguments,
|
||||
template=template)
|
||||
|
||||
log.debug('Waiting for the stack {0} to be create'.format(
|
||||
self._stack))
|
||||
self._wait_state('CREATE_COMPLETE')
|
||||
outs = self._wait_state('CREATE_COMPLETE')
|
||||
log.info('Stack {0} created'.format(self._stack))
|
||||
|
||||
pending_list = self._update_pending_list
|
||||
self._update_pending_list = []
|
||||
|
||||
for item in pending_list:
|
||||
item['callback'](True)
|
||||
item['callback'](outs)
|
||||
|
||||
return True
|
||||
|
||||
@ -177,9 +178,11 @@ class HeatExecutor(CommandBase):
|
||||
|
||||
while True:
|
||||
try:
|
||||
status = self._heat_client.stacks.get(
|
||||
stack_id=self._stack).stack_status
|
||||
stack_info = self._heat_client.stacks.get(
|
||||
stack_id=self._stack)
|
||||
status = stack_info.stack_status
|
||||
except heatclient.exc.HTTPNotFound:
|
||||
stack_info = None
|
||||
status = ''
|
||||
|
||||
if 'IN_PROGRESS' in status:
|
||||
@ -187,4 +190,9 @@ class HeatExecutor(CommandBase):
|
||||
continue
|
||||
if status not in states:
|
||||
raise EnvironmentError()
|
||||
return
|
||||
|
||||
try:
|
||||
return dict([(t['output_key'], t['output_value'])
|
||||
for t in stack_info.outputs])
|
||||
except Exception:
|
||||
return {}
|
||||
|
@ -27,7 +27,13 @@ def transform_json(json, mappings):
|
||||
transform_json(value, mappings)
|
||||
return result
|
||||
|
||||
if isinstance(json, types.StringTypes) and json.startswith('$'):
|
||||
elif isinstance(json, types.ListType):
|
||||
result = []
|
||||
for value in json:
|
||||
result.append(transform_json(value, mappings))
|
||||
return result
|
||||
|
||||
elif isinstance(json, types.StringTypes) and json.startswith('$'):
|
||||
value = mappings.get(json[1:])
|
||||
if value is not None:
|
||||
return value
|
||||
@ -35,19 +41,28 @@ def transform_json(json, mappings):
|
||||
return json
|
||||
|
||||
|
||||
def merge_lists(list1, list2):
|
||||
return list1 + list2
|
||||
|
||||
|
||||
def merge_dicts(dict1, dict2, max_levels=0):
|
||||
result = {}
|
||||
for key, value in dict1.items():
|
||||
result[key] = value
|
||||
if key in dict2:
|
||||
other_value = dict2[key]
|
||||
if max_levels == 1 or not isinstance(
|
||||
if type(other_value) != type(value):
|
||||
raise TypeError()
|
||||
if max_levels != 1 and isinstance(
|
||||
other_value, types.DictionaryType):
|
||||
result[key] = other_value
|
||||
else:
|
||||
result[key] = merge_dicts(
|
||||
value, other_value,
|
||||
0 if max_levels == 0 else max_levels - 1)
|
||||
elif max_levels != 1 and isinstance(
|
||||
other_value, types.ListType):
|
||||
result[key] = merge_lists(value, other_value)
|
||||
else:
|
||||
result[key] = other_value
|
||||
for key, value in dict2.items():
|
||||
if key not in result:
|
||||
result[key] = value
|
||||
|
21
data/templates/cf/LoadBalancer.template
Normal file
21
data/templates/cf/LoadBalancer.template
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"Resources" : {
|
||||
"$lbName" : {
|
||||
"Type" : "AWS::ElasticLoadBalancing::LoadBalancer",
|
||||
"Properties" : {
|
||||
"Instances" : [{"Ref": "$instanceName"}],
|
||||
"Listeners" : [ {
|
||||
"LoadBalancerPort" : "$lbPort",
|
||||
"InstancePort" : "80",
|
||||
"Protocol" : "HTTP"
|
||||
}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"Outputs": {
|
||||
"LoadBalancerIP": {
|
||||
"Value": { "Fn::GetAtt": [ "$lbName", "DNSName" ] },
|
||||
"Description": ""
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<workflow>
|
||||
<rule match="$.services.aspNetApps[?(@.domain)].units[*]">
|
||||
<rule match="$.services.webServers,aspNetApps,webServerFarms,aspNetAppFarms[?(@.domain)].units[*]">
|
||||
<set path="domain">
|
||||
<select path="::domain"/>
|
||||
</set>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.aspNetApps[*].units[?(@.state.hostname and not @.state.instanceName)]">
|
||||
<rule match="$.services.webServers,aspNetApps,webServerFarms,aspNetAppFarms[*].units[?(@.state.hostname and not @.state.instanceName)]">
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Creating instance <select path="name"/></parameter>
|
||||
@ -41,7 +41,25 @@
|
||||
</update-cf-stack>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.aspNetApps[?(@.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.state.instanceName)]">
|
||||
<rule match="$.services.webServerFarms,aspNetAppFarms[*].units[?(@.state.hostname and not @.state.registeredWithLB)]">
|
||||
<update-cf-stack template="LoadBalancer" result="outputs">
|
||||
<parameter name="mappings">
|
||||
<map>
|
||||
<mapping name="instanceName"><select path="state.hostname"/></mapping>
|
||||
<mapping name="lbPort"><select path="::loadBalancerPort"/></mapping>
|
||||
<mapping name="lbName"><select path="::name"/></mapping>
|
||||
</map>
|
||||
</parameter>
|
||||
<success>
|
||||
<set path="state.registeredWithLB"><true/></set>
|
||||
<set path="::LoadBalancerIP">
|
||||
<select source="outputs" path="LoadBalancerIP"/>
|
||||
</set>
|
||||
</success>
|
||||
</update-cf-stack>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.webServers,aspNetApps,webServerFarms,aspNetAppFarms[?(@.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.state.instanceName)]">
|
||||
<send-command template="SetPassword">
|
||||
<parameter name="unit">
|
||||
<select path="id"/>
|
||||
@ -64,7 +82,8 @@
|
||||
</send-command>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.aspNetApps[*].units[?(@.state.instanceName and not @.state.iisInstalled)]">
|
||||
|
||||
<rule match="$.services.webServers,aspNetApps,webServerFarms,aspNetAppFarms[*].units[?(@.state.instanceName and not @.state.iisInstalled)]">
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Creating IIS Web Server on unit <select path="name"/></parameter>
|
||||
@ -86,7 +105,7 @@
|
||||
</send-command>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.aspNetApps[*].units[?(@.state.iisInstalled and not @.state.webAppDeployed)]">
|
||||
<rule match="$.services.aspNetApps,aspNetAppFarms[*].units[?(@.state.iisInstalled and not @.state.webAppDeployed)]">
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Deploying Web App on unit <select path="name"/></parameter>
|
@ -1,89 +0,0 @@
|
||||
<workflow>
|
||||
<rule match="$.services.webServers[?(@.domain)].units[*]">
|
||||
<set path="domain">
|
||||
<select path="::domain"/>
|
||||
</set>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.webServers[*].units[?(@.state.hostname and not @.state.instanceName)]">
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Creating instance <select path="name"/></parameter>
|
||||
</report>
|
||||
<update-cf-stack template="Windows">
|
||||
<parameter name="mappings">
|
||||
<map>
|
||||
<mapping name="instanceName"><select path="state.hostname"/></mapping>
|
||||
<mapping name="userData">
|
||||
<prepare-user-data>
|
||||
<parameter name="hostname"><select path="state.hostname"/></parameter>
|
||||
<parameter name="unit"><select path="id"/></parameter>
|
||||
<parameter name="service"><select path="::id"/></parameter>
|
||||
</prepare-user-data>
|
||||
</mapping>
|
||||
</map>
|
||||
</parameter>
|
||||
<parameter name="arguments">
|
||||
<map>
|
||||
<argument name="KeyName">murano-keys</argument>
|
||||
<argument name="InstanceType">m1.medium</argument>
|
||||
<argument name="ImageName">ws-2012-full</argument>
|
||||
</map>
|
||||
</parameter>
|
||||
|
||||
<success>
|
||||
<set path="state.instanceName"><select path="name"/></set>
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Instance <select path="name"/> created</parameter>
|
||||
</report>
|
||||
</success>
|
||||
</update-cf-stack>
|
||||
</rule>
|
||||
|
||||
<rule match="$.services.webServers[?(@.adminPassword and @.adminPassword != @.state.adminPassword)].units[?(@.state.instanceName)]">
|
||||
<send-command template="SetPassword">
|
||||
<parameter name="unit">
|
||||
<select path="id"/>
|
||||
</parameter>
|
||||
<parameter name="service">
|
||||
<select path="::id"/>
|
||||
</parameter>
|
||||
<parameter name="mappings">
|
||||
<map>
|
||||
<mapping name="adminPassword">
|
||||
<select path="::adminPassword"/>
|
||||
</mapping>
|
||||
</map>
|
||||
</parameter>
|
||||
<success>
|
||||
<set path="::state.adminPassword">
|
||||
<select path="::adminPassword"/>
|
||||
</set>
|
||||
</success>
|
||||
</send-command>
|
||||
</rule>
|
||||
|
||||
|
||||
<rule match="$.services.webServers[*].units[?(@.state.instanceName and not @.state.iisInstalled)]">
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">Creating IIS Web Server on unit <select path="name"/></parameter>
|
||||
</report>
|
||||
<send-command template="InstallIIS">
|
||||
<parameter name="unit">
|
||||
<select path="id"/>
|
||||
</parameter>
|
||||
<parameter name="service">
|
||||
<select path="::id"/>
|
||||
</parameter>
|
||||
<success>
|
||||
<set path="state.iisInstalled"><true/></set>
|
||||
<report entity="unit">
|
||||
<parameter name="id"><select path="id"/></parameter>
|
||||
<parameter name="text">IIS <select path="name"/> has started</parameter>
|
||||
</report>
|
||||
</success>
|
||||
</send-command>
|
||||
</rule>
|
||||
</workflow>
|
@ -4,10 +4,10 @@ debug=True
|
||||
verbose=True
|
||||
|
||||
[heat]
|
||||
auth_url = http://172.18.124.101:5000/v2.0
|
||||
auth_url = http://172.18.79.71:5000/v2.0
|
||||
|
||||
[rabbitmq]
|
||||
host = 172.18.124.101
|
||||
host = localhost
|
||||
port = 5672
|
||||
virtual_host = murano
|
||||
login = murano
|
||||
|
@ -84,7 +84,7 @@ class TestHeatExecutor(unittest.TestCase):
|
||||
"testKey": "testValue"
|
||||
}
|
||||
})
|
||||
callback.assert_called_with(True)
|
||||
callback.assert_called_with({})
|
||||
|
||||
@mock.patch('heatclient.v1.client.Client')
|
||||
@mock.patch('keystoneclient.v2_0.client.Client')
|
||||
@ -139,7 +139,7 @@ class TestHeatExecutor(unittest.TestCase):
|
||||
"testKey": "testValue"
|
||||
}
|
||||
})
|
||||
callback.assert_called_with(True)
|
||||
callback.assert_called_with({})
|
||||
|
||||
@mock.patch('heatclient.v1.client.Client')
|
||||
@mock.patch('keystoneclient.v2_0.client.Client')
|
||||
|
Loading…
x
Reference in New Issue
Block a user