Fixed several quantum issues:

Networks and subnets are now created per environment
Added code to detect external network id and pass it to newly-created routers
DNS name servers are assigned to subnets
Minor fixes

All these relies on Patched HEat and Quantum which allows overlapping subnets

Change-Id: I7f47e71c13a0202743e3bb2cb70b0456bb4117a8
This commit is contained in:
Alexander Tivelkov
2013-10-17 19:51:05 +04:00
committed by Serg Melikyan
parent d3315d07e1
commit 17d6b3a732
10 changed files with 219 additions and 61 deletions

View File

@@ -1,26 +0,0 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Parameters" : {
"KeyName" : {
"Description" : "Key Pair name for Load Balancer",
"Type" : "String",
"Default" : "murano-lb-key"
}
},
"Resources" : {
"$instanceName": {
"Type" : "AWS::EC2::Instance",
"Properties": {
"InstanceType" : "$instanceType",
"ImageId" :"$imageName",
"AvailabilityZone" : "$availabilityZone",
"UserData": "$userData"
}
}
},
"Outputs" : {
}
}

View File

@@ -1,26 +1,42 @@
{
"AWSTemplateFormatVersion" : "2010-09-09",
"AWSTemplateFormatVersion": "2010-09-09",
"Parameters" : {
"KeyName" : {
"Description" : "Key Pair name for Load Balancer",
"Type" : "String",
"Default" : "murano-lb-key"
}
},
"Resources" : {
"$instanceName": {
"Type" : "AWS::EC2::Instance",
"Properties": {
"InstanceType" : "$instanceType",
"ImageId" :"$imageName",
"AvailabilityZone" : "$availabilityZone",
"UserData": "$userData",
"SecurityGroups" : [ { "Ref" : "MuranoDefaultSecurityGroup"}]
}
"Parameters": {
"KeyName": {
"Description": "Key Pair name for Load Balancer",
"Type": "String",
"Default": "murano-lb-key"
}
},
"MuranoDefaultSecurityGroup": {
"Resources": {
"$instanceName": {
"Type": "AWS::EC2::Instance",
"Properties": {
"InstanceType": "$instanceType",
"ImageId": "$imageName",
"AvailabilityZone": "$availabilityZone",
"UserData": "$userData",
"NetworkInterfaces": [ { "Ref": "$instancePort" } ]
}
},
"$instancePort": {
"Type": "OS::Quantum::Port",
"Properties": {
"network_id": {
"Ref": "network"
},
"security_groups" : [ { "Ref" : "MuranoDefaultSecurityGroup"}],
"fixed_ips": [
{
"subnet_id": {
"Ref": "subnet"
}
}
]
}
},
"MuranoDefaultSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
@@ -45,9 +61,55 @@
],
"GroupDescription": "Default security group for Linux Murano Environments"
}
},
"network": {
"Type": "OS::Quantum::Net",
"Properties": {
"name": "$networkName"
}
},
"subnet": {
"Type": "OS::Quantum::Subnet",
"Properties": {
"network_id": {
"Ref": "network"
},
"ip_version": 4,
"cidr": "10.0.0.0/24",
"dns_nameservers": ["8.8.8.8"],
"allocation_pools": [
{
"start": "10.0.0.20",
"end": "10.0.0.250"
}
]
}
},
"router": {
"Type": "OS::Quantum::Router"
},
"router_interface": {
"Type": "OS::Quantum::RouterInterface",
"Properties": {
"router_id": {
"Ref": "router"
},
"subnet_id": {
"Ref": "subnet"
}
}
},
"router_gateway": {
"Type": "OS::Quantum::RouterGateway",
"Properties": {
"router_id": {
"Ref": "router"
},
"network_id": "$externalNetworkId"
}
}
},
},
"Outputs" : {
}
"Outputs": {
}
}

View File

@@ -2,7 +2,7 @@
"Resources": {
"$instancePort": {
"Properties": {
"SecurityGroups" : [ {"Ref" : "MsSqlSecurityGroup"} ]
"security_groups" : [ {"Ref" : "MsSqlSecurityGroup"} ]
}
},
"MsSqlSecurityGroup": {

View File

@@ -17,7 +17,23 @@
"ImageId": "$imageName",
"AvailabilityZone": "$availabilityZone",
"UserData": "$userData",
"SecurityGroups" : [ { "Ref" : "MuranoDefaultSecurityGroup"}]
"NetworkInterfaces": [ { "Ref": "$instancePort" } ]
}
},
"$instancePort": {
"Type": "OS::Quantum::Port",
"Properties": {
"network_id": {
"Ref": "network"
},
"security_groups" : [ { "Ref" : "MuranoDefaultSecurityGroup"}],
"fixed_ips": [
{
"subnet_id": {
"Ref": "subnet"
}
}
]
}
},
"MuranoDefaultSecurityGroup": {
@@ -45,6 +61,52 @@
],
"GroupDescription": "Default security group for Murano Environments"
}
},
"network": {
"Type": "OS::Quantum::Net",
"Properties": {
"name": "$networkName"
}
},
"subnet": {
"Type": "OS::Quantum::Subnet",
"Properties": {
"network_id": {
"Ref": "network"
},
"ip_version": 4,
"cidr": "10.0.0.0/24",
"dns_nameservers": ["8.8.8.8"],
"allocation_pools": [
{
"start": "10.0.0.20",
"end": "10.0.0.250"
}
]
}
},
"router": {
"Type": "OS::Quantum::Router"
},
"router_interface": {
"Type": "OS::Quantum::RouterInterface",
"Properties": {
"router_id": {
"Ref": "router"
},
"subnet_id": {
"Ref": "subnet"
}
}
},
"router_gateway": {
"Type": "OS::Quantum::RouterGateway",
"Properties": {
"router_id": {
"Ref": "router"
},
"network_id": "$externalNetworkId"
}
}
},

View File

@@ -9,10 +9,12 @@
<parameter name="id"><select path="id"/></parameter>
<parameter name="text">Creating instance <select path="state.hostname"/> (<select path="name"/>)</parameter>
</report>
<update-cf-stack template="Demo" error="exception">
<update-cf-stack template="Linux" error="exception">
<parameter name="mappings">
<map>
<mapping name="instanceName"><select path="state.hostname"/></mapping>
<mapping name="instancePort">port-<select path="state.hostname"/></mapping>
<mapping name="networkName">network-<select path="/id"/></mapping>
<mapping name="userData">
<prepare-user-data template="Demo" initFile="demo_init.sh">
<parameter name="hostname"><select path="state.hostname"/></parameter>

View File

@@ -42,6 +42,19 @@ insecure = False
# Valid endpoint types: publicURL (default), internalURL, adminURL
endpoint_type = publicURL
[quantum]
# quantum SSL parameters
# Optional CA cert file to use in SSL connections
ca_file =
# Optional PEM-formatted certificate chain file
cert_file =
# Optional PEM-formatted file that contains the private key
key_file =
# If set then the server's certificate will not be verified
insecure = False
# Valid endpoint types: publicURL (default), internalURL, adminURL
endpoint_type = publicURL
[rabbitmq]
# Connection parameters to RabbitMQ service

View File

@@ -21,9 +21,10 @@ from muranoconductor.openstack.common import log as logging
import muranoconductor.helpers
from command import CommandBase
import muranoconductor.config
from heatclient.client import Client
import heatclient.exc
from keystoneclient.v2_0 import client as ksclient
from heatclient import client as heat_client
from quantumclient.v2_0 import client as quantum_client
log = logging.getLogger(__name__)
@@ -37,6 +38,7 @@ class HeatExecutor(CommandBase):
keystone_settings = muranoconductor.config.CONF.keystone
heat_settings = muranoconductor.config.CONF.heat
quantum_settings = muranoconductor.config.CONF.quantum
client = ksclient.Client(
endpoint=keystone_settings.auth_url,
@@ -55,7 +57,15 @@ class HeatExecutor(CommandBase):
service_type='orchestration',
endpoint_type=heat_settings.endpoint_type)
self._heat_client = Client(
quantum_url = client.service_catalog.url_for(
service_type='network',
endpoint_type=quantum_settings.endpoint_type)
self._quantum_client = quantum_client.Client(
endpoint_url=quantum_url,
token=token)
self._heat_client = heat_client.Client(
'1',
heat_url,
token_only=True,
@@ -82,7 +92,8 @@ class HeatExecutor(CommandBase):
def _execute_create_update(self, template, mappings, arguments, callback):
with open('data/templates/cf/%s.template' % template) as template_file:
template_data = template_file.read()
if not "externalNetworkId" in mappings:
mappings["externalNetworkId"] = self._get_external_network_id()
template_data = muranoconductor.helpers.transform_json(
anyjson.loads(template_data), mappings)
@@ -97,6 +108,21 @@ class HeatExecutor(CommandBase):
'callback': callback
})
def _get_external_network_id(self):
log.info('Fetching the list of external networks...')
ext_nets = self._quantum_client.list_networks(
**{"router:external": True}).get('networks')
log.debug(ext_nets)
if ext_nets and len(ext_nets) > 0:
if len(ext_nets) > 1:
log.warning(
"Multiple external networks found, will use the first one")
net = ext_nets[0]
return net.get('id')
else:
log.error("No external networks found!")
return None
def has_pending_commands(self):
return len(self._update_pending_list) + len(
self._delete_pending_list) > 0

View File

@@ -52,6 +52,14 @@ heat_opts = [
cfg.StrOpt('endpoint_type', default='publicURL')
]
quantum_opts = [
cfg.BoolOpt('insecure', default=False),
cfg.StrOpt('ca_file'),
cfg.StrOpt('cert_file'),
cfg.StrOpt('key_file'),
cfg.StrOpt('endpoint_type', default='publicURL')
]
keystone_opts = [
cfg.StrOpt('auth_url'),
cfg.BoolOpt('insecure', default=False),
@@ -64,6 +72,7 @@ CONF = cfg.CONF
CONF.register_opts(paste_deploy_opts, group='paste_deploy')
CONF.register_opts(rabbit_opts, group='rabbitmq')
CONF.register_opts(heat_opts, group='heat')
CONF.register_opts(quantum_opts, group='quantum')
CONF.register_opts(keystone_opts, group='keystone')
CONF.register_opt(cfg.StrOpt('file_server'))
CONF.register_cli_opt(cfg.StrOpt('data_dir', default='./'))

View File

@@ -6,6 +6,7 @@ Paste
PasteDeploy>=1.5.0
iso8601>=0.1.4
python-heatclient>=0.2.4
python-quantumclient
jsonschema>=1.3.0,!=1.4.0
netaddr

View File

@@ -42,15 +42,22 @@ class TestHeatExecutor(unittest.TestCase):
auth_data = ksclient_mock().tokens.authenticate()
auth_data.id = '123456'
auth_data.serviceCatalog = [{
'name': 'heat',
'endpoints': [{'publicURL': 'http://invalid.heat.url'}]
}]
auth_data.serviceCatalog = [
{
'name': 'heat',
'endpoints': [{'publicURL': 'http://invalid.heat.url'}]
}, {
'name': 'quantum',
'endpoints': [{'publicURL': 'http://invalid.quantum.url'}]
}
]
@mock.patch('quantumclient.v2_0.client.Client')
@mock.patch('heatclient.v1.client.Client')
@mock.patch('keystoneclient.v2_0.client.Client')
@mock.patch('muranoconductor.config.CONF')
def test_create_stack(self, config_mock, ksclient_mock, heat_mock):
def test_create_stack(self, config_mock, ksclient_mock, heat_mock,
quantum_mock):
self._init(config_mock, ksclient_mock)
reporter = mock.MagicMock()
executor = HeatExecutor('stack', 'token', 'tenant_id', reporter)
@@ -88,10 +95,12 @@ class TestHeatExecutor(unittest.TestCase):
disable_rollback=False)
callback.assert_called_with({})
@mock.patch('quantumclient.v2_0.client.Client')
@mock.patch('heatclient.v1.client.Client')
@mock.patch('keystoneclient.v2_0.client.Client')
@mock.patch('muranoconductor.config.CONF')
def test_update_stack(self, config_mock, ksclient_mock, heat_mock):
def test_update_stack(self, config_mock, ksclient_mock, heat_mock,
quantum_mock):
self._init(config_mock, ksclient_mock)
reporter = mock.MagicMock()
executor = HeatExecutor('stack', 'token', 'tenant_id', reporter)