Add network parameters to Heat template creation.
In order to allow the allocation of a floating IP in the heat template, we need to give network paremeters as input. This patch : - updates the heat template to associate a floating IP to the created server - Use python-neutronclient to find the needed network id to pass to the heat template Fixes bug 1301324 Change-Id: If6182d1bf6196022b77bfaf26d2563a483f1a460
This commit is contained in:
@@ -25,7 +25,7 @@ At present it is a Stackforge project, and its repository is available on Github
|
||||
$ cd Solum
|
||||
$ git clone https://github.com/stackforge/solum
|
||||
|
||||
In addition to Solum, your environment will also need Devstack to configure and run the requisite Openstack components, including Keystone, Glance, Nova, and Heat.
|
||||
In addition to Solum, your environment will also need Devstack to configure and run the requisite Openstack components, including Keystone, Glance, Nova, Neutron, and Heat.
|
||||
|
||||
Vagrant (Optional)
|
||||
------------------
|
||||
@@ -56,6 +56,10 @@ Using Vagrant is not a requirement for deploying Solum.
|
||||
You may instead opt to install Solum and Devstack yourself.
|
||||
The details of integrating Solum with Devstack can be found in :code:`contrib/devstack/README.rst`.
|
||||
|
||||
Some additional configuration will be needed for Neutron, see `Neutron's Wiki page for Devstack`__
|
||||
|
||||
__ https://wiki.openstack.org/wiki/NeutronDevstack
|
||||
|
||||
Create your app
|
||||
---------------
|
||||
|
||||
|
||||
@@ -21,6 +21,15 @@ parameters:
|
||||
type: string
|
||||
default: "5000"
|
||||
description: Port Number
|
||||
private_net:
|
||||
type: string
|
||||
description: Id of the private network for the compute server
|
||||
private_subnet:
|
||||
type: string
|
||||
description: Id of the private sub network for the compute server
|
||||
public_net:
|
||||
type: string
|
||||
description: Id of the public network for the compute server
|
||||
|
||||
resources:
|
||||
external_access:
|
||||
@@ -35,6 +44,21 @@ resources:
|
||||
{IpProtocol: icmp, FromPort: "-1", ToPort: "-1",
|
||||
CidrIp: "0.0.0.0/0"}]
|
||||
|
||||
public_port:
|
||||
type: OS::Neutron::Port
|
||||
properties:
|
||||
network_id: { get_param: private_net }
|
||||
fixed_ips:
|
||||
- subnet_id: { get_param: private_subnet }
|
||||
security_groups:
|
||||
- {get_resource: external_access}
|
||||
|
||||
floating_ip:
|
||||
type: OS::Neutron::FloatingIP
|
||||
properties:
|
||||
floating_network_id: { get_param: public_net }
|
||||
port_id: { get_resource: public_port }
|
||||
|
||||
compute:
|
||||
type: OS::Nova::Server
|
||||
properties:
|
||||
@@ -42,8 +66,8 @@ resources:
|
||||
image: {get_param: image}
|
||||
flavor: { get_param: flavor }
|
||||
key_name: { get_param: key_name }
|
||||
security_groups:
|
||||
- {get_resource: external_access}
|
||||
networks:
|
||||
- port: { get_resource: public_port }
|
||||
user_data_format: RAW
|
||||
user_data:
|
||||
str_replace:
|
||||
@@ -59,12 +83,12 @@ resources:
|
||||
outputs:
|
||||
public_ip:
|
||||
description: The public IP address of the newly configured Server.
|
||||
value: { get_attr: [compute, first_address ] }
|
||||
value: { get_attr: [ floating_ip, floating_ip_address ] }
|
||||
URL:
|
||||
description: The URL for the Server.
|
||||
value:
|
||||
str_replace:
|
||||
template: http://%host%:%port%
|
||||
params:
|
||||
"%host%": { get_attr: [ compute, first_address ] }
|
||||
"%host%": { get_attr: [ floating_ip, floating_ip_address ] }
|
||||
"%port%": { get_param: port }
|
||||
|
||||
@@ -68,6 +68,19 @@ class Handler(object):
|
||||
template = templ_file.read()
|
||||
return template
|
||||
|
||||
def _get_network_parameters(self, osc):
|
||||
#TODO(julienvey) In the long term, we should have optional parameters
|
||||
# if the user wants to override this default behaviour
|
||||
params = {}
|
||||
tenant_networks = osc.neutron().list_networks()
|
||||
for tenant_network in tenant_networks['networks']:
|
||||
if tenant_network['router:external']:
|
||||
params['public_net'] = tenant_network['id']
|
||||
else:
|
||||
params['private_net'] = tenant_network['id']
|
||||
params['private_subnet'] = tenant_network['subnets'][0]
|
||||
return params
|
||||
|
||||
def deploy(self, ctxt, assembly_id, image_id):
|
||||
# TODO(asalkeld) support template flavors (maybe an autoscaling one)
|
||||
# this could also be stored in glance.
|
||||
@@ -81,6 +94,7 @@ class Handler(object):
|
||||
|
||||
parameters = {'app_name': assem.name,
|
||||
'image': image_id}
|
||||
parameters.update(self._get_network_parameters(osc))
|
||||
created_stack = osc.heat().stacks.create(stack_name=assem.name,
|
||||
template=template,
|
||||
parameters=parameters)
|
||||
|
||||
@@ -46,14 +46,25 @@ class HandlerTest(base.BaseTestCase):
|
||||
return_value = {"stack": {"id": "fake_id",
|
||||
"links": [{"href": "http://fake.ref",
|
||||
"rel": "self"}]}}
|
||||
mock_clients.return_value.neutron.return_value.list_networks.\
|
||||
return_value = {"networks": [{"router:external": True,
|
||||
"id": "public_net_id"},
|
||||
{"router:external": False,
|
||||
"id": "private_net_id",
|
||||
"subnets": ["private_subnet_id"]}]}
|
||||
handler._update_assembly_status = mock.MagicMock()
|
||||
handler.deploy(self.ctx, 77, 'created_image_id')
|
||||
parameters = {'image': 'created_image_id',
|
||||
'app_name': 'faker'}
|
||||
'app_name': 'faker',
|
||||
'private_net': 'private_net_id',
|
||||
'public_net': 'public_net_id',
|
||||
'private_subnet': 'private_subnet_id'}
|
||||
mock_clients.return_value.heat.return_value.stacks.create.\
|
||||
assert_called_once_with(stack_name='faker',
|
||||
template=fake_template,
|
||||
parameters=parameters)
|
||||
mock_clients.return_value.neutron.return_value.list_networks.\
|
||||
assert_called_once_with()
|
||||
assign_and_create_mock = mock_registry.Component.assign_and_create
|
||||
assign_and_create_mock.assert_called_once_with(self.ctx,
|
||||
fake_assembly,
|
||||
|
||||
Reference in New Issue
Block a user