Add Container Volume Model into Mesos Heat Templates

Previously,the mesos bay type did not support the Magnum Container
Volume Model. This patch adds support for volume through the following:

1. Add username, tenant_name, preempt, region_name, domain_name to
mesos bay type.
2. Add get_parameter to mesos.
3. Update mesos unit tests to support container volume.
4. Update mesos heat templates for container volume model

Change-Id: Icf7cb9fc38c7facb2d49904b6e52bbce974948f7
Partially-Implements: blueprint magnum-integrate-with-cinder
This commit is contained in:
wangqun 2016-02-20 03:04:48 +00:00
parent def0cce268
commit c932d5fab9
8 changed files with 251 additions and 5 deletions

View File

@ -203,6 +203,7 @@ function create_magnum_conf {
iniset $MAGNUM_CONF trust trustee_domain_id $trustee_domain_id iniset $MAGNUM_CONF trust trustee_domain_id $trustee_domain_id
iniset $MAGNUM_CONF trust trustee_domain_admin_id $trustee_domain_admin_id iniset $MAGNUM_CONF trust trustee_domain_admin_id $trustee_domain_admin_id
iniset $MAGNUM_CONF trust trustee_domain_admin_password $MAGNUM_TRUSTEE_DOMAIN_ADMIN_PASSWORD iniset $MAGNUM_CONF trust trustee_domain_admin_password $MAGNUM_TRUSTEE_DOMAIN_ADMIN_PASSWORD
iniset $MAGNUM_CONF cinder_client region_name $REGION_NAME
} }
function update_heat_policy { function update_heat_policy {

View File

@ -634,6 +634,8 @@ class UbuntuMesosTemplateDefinition(BaseTemplateDefinition):
baymodel_attr='flavor_id') baymodel_attr='flavor_id')
self.add_parameter('cluster_name', self.add_parameter('cluster_name',
bay_attr='name') bay_attr='name')
self.add_parameter('volume_driver',
baymodel_attr='volume_driver')
self.add_output('api_address', self.add_output('api_address',
bay_attr='api_address') bay_attr='api_address')
@ -646,6 +648,28 @@ class UbuntuMesosTemplateDefinition(BaseTemplateDefinition):
self.add_output('mesos_slaves', self.add_output('mesos_slaves',
bay_attr='node_addresses') bay_attr='node_addresses')
def get_params(self, context, baymodel, bay, **kwargs):
extra_params = kwargs.pop('extra_params', {})
# HACK(apmelton) - This uses the user's bearer token, ideally
# it should be replaced with an actual trust token with only
# access to do what the template needs it to do.
osc = clients.OpenStackClients(context)
extra_params['auth_url'] = context.auth_url
extra_params['username'] = context.user_name
extra_params['tenant_name'] = context.tenant
extra_params['domain_name'] = context.domain_name
extra_params['region_name'] = osc.cinder_region_name()
label_list = ['rexray_preempt']
for label in label_list:
extra_params[label] = baymodel.labels.get(label)
return super(UbuntuMesosTemplateDefinition,
self).get_params(context, baymodel, bay,
extra_params=extra_params,
**kwargs)
@property @property
def template_path(self): def template_path(self):
return cfg.CONF.bay.mesos_ubuntu_template_path return cfg.CONF.bay.mesos_ubuntu_template_path

View File

@ -0,0 +1,39 @@
#!/bin/sh
. /etc/sysconfig/heat-params
# Judge whether to install the rexray driver
if [ "$VOLUME_DRIVER" != "rexray" ]; then
exit 0
fi
curl -sSL https://dl.bintray.com/emccode/rexray/install | sh -
CLOUD_CONFIG=/etc/rexray/config.yml
CLOUD=/etc/rexray
if [ ! -d ${CLOUD_CONFIG} -o ! -d ${CLOUD} ]; then
mkdir -p $CLOUD
fi
if [ ${AUTH_URL##*/}=="v3" ]; then
extra_configs="domainName: $DOMAIN_NAME"
fi
cat > $CLOUD_CONFIG <<EOF
rexray:
storageDrivers:
- openstack
volume:
mount:
preempt: $REXRAY_PREEMPT
openstack:
authUrl: $AUTH_URL
username: $USERNAME
password: $PASSWORD
tenantName: $TENANT_NAME
regionName: $REGION_NAME
availabilityZoneName: nova
$extra_configs
EOF
service rexray start

View File

@ -10,3 +10,11 @@ write_files:
HTTP_PROXY="$HTTP_PROXY" HTTP_PROXY="$HTTP_PROXY"
HTTPS_PROXY="$HTTPS_PROXY" HTTPS_PROXY="$HTTPS_PROXY"
NO_PROXY="$NO_PROXY" NO_PROXY="$NO_PROXY"
AUTH_URL="$AUTH_URL"
USERNAME="$USERNAME"
PASSWORD="$PASSWORD"
TENANT_NAME="$TENANT_NAME"
VOLUME_DRIVER="$VOLUME_DRIVER"
REGION_NAME="$REGION_NAME"
DOMAIN_NAME="$DOMAIN_NAME"
REXRAY_PREEMPT="$REXRAY_PREEMPT"

View File

@ -111,6 +111,51 @@ parameters:
default: "" default: ""
hidden: true hidden: true
region_name:
type: string
description: A logically separate section of the cluster
auth_url:
type: string
description: >
url for mesos to authenticate before sending request
username:
type: string
description: user name
password:
type: string
description: >
user password, not set in current implementation, only used to
fill in for Mesos config file
default:
password
hidden: true
tenant_name:
type: string
description: >
tenant_name is used to isolate access to Compute resources
volume_driver:
type: string
description: volume driver to use for container storage
default: ""
domain_name:
type: string
description: >
domain is to define the administrative boundaries for management
of Keystone entities
rexray_preempt:
type: string
description: >
enables any host to take control of a volume irrespective of whether
other hosts are using the volume
default: "false"
resources: resources:
###################################################################### ######################################################################
@ -336,6 +381,14 @@ resources:
http_proxy: {get_param: http_proxy} http_proxy: {get_param: http_proxy}
https_proxy: {get_param: https_proxy} https_proxy: {get_param: https_proxy}
no_proxy: {get_param: no_proxy} no_proxy: {get_param: no_proxy}
auth_url: {get_param: auth_url}
username: {get_param: username}
password: {get_param: password}
tenant_name: {get_param: tenant_name}
volume_driver: {get_param: volume_driver}
region_name: {get_param: region_name}
domain_name: {get_param: domain_name}
rexray_preempt: {get_param: rexray_preempt}
outputs: outputs:

View File

@ -54,6 +54,51 @@ parameters:
description: no proxies for docker description: no proxies for docker
default: "" default: ""
auth_url:
type: string
description: >
url for mesos to authenticate before sending request
username:
type: string
description: user name
password:
type: string
description: >
user password, not set in current implementation, only used to
fill in for Kubernetes config file
default:
password
hidden: true
tenant_name:
type: string
description: >
tenant_name is used to isolate access to Compute resources
volume_driver:
type: string
description: volume driver to use for container storage
default: ""
region_name:
type: string
description: A logically separate section of the cluster
domain_name:
type: string
description: >
domain is to define the administrative boundaries for management
of Keystone entities
rexray_preempt:
type: string
description: >
enables any host to take control of a volume irrespective of whether
other hosts are using the volume
default: "false"
# The following are all generated in the parent template. # The following are all generated in the parent template.
mesos_masters_ips: mesos_masters_ips:
type: string type: string
@ -107,6 +152,14 @@ resources:
"$HTTP_PROXY": {get_param: http_proxy} "$HTTP_PROXY": {get_param: http_proxy}
"$HTTPS_PROXY": {get_param: https_proxy} "$HTTPS_PROXY": {get_param: https_proxy}
"$NO_PROXY": {get_param: no_proxy} "$NO_PROXY": {get_param: no_proxy}
"$AUTH_URL": {get_param: auth_url}
"$USERNAME": {get_param: username}
"$PASSWORD": {get_param: password}
"$TENANT_NAME": {get_param: tenant_name}
"$VOLUME_DRIVER": {get_param: volume_driver}
"$REGION_NAME": {get_param: region_name}
"$DOMAIN_NAME": {get_param: domain_name}
"$REXRAY_PREEMPT": {get_param: rexray_preempt}
configure_mesos_slave: configure_mesos_slave:
type: OS::Heat::SoftwareConfig type: OS::Heat::SoftwareConfig
@ -131,13 +184,19 @@ resources:
wc_notify --data-binary '{"status": "SUCCESS"}' wc_notify --data-binary '{"status": "SUCCESS"}'
params: params:
wc_notify: {get_attr: [slave_wait_handle, curl_cli]} wc_notify: {get_attr: [slave_wait_handle, curl_cli]}
add_proxy: add_proxy:
type: OS::Heat::SoftwareConfig type: OS::Heat::SoftwareConfig
properties: properties:
group: ungrouped group: ungrouped
config: {get_file: fragments/add-proxy.sh} config: {get_file: fragments/add-proxy.sh}
volume_service:
type: OS::Heat::SoftwareConfig
properties:
group: ungrouped
config: {get_file: fragments/volume-service.sh}
mesos_slave_init: mesos_slave_init:
type: OS::Heat::MultipartMime type: OS::Heat::MultipartMime
properties: properties:
@ -145,6 +204,7 @@ resources:
- config: {get_resource: write_heat_params} - config: {get_resource: write_heat_params}
- config: {get_resource: configure_mesos_slave} - config: {get_resource: configure_mesos_slave}
- config: {get_resource: add_proxy} - config: {get_resource: add_proxy}
- config: {get_resource: volume_service}
- config: {get_resource: start_services} - config: {get_resource: start_services}
- config: {get_resource: slave_wc_notify} - config: {get_resource: slave_wc_notify}

View File

@ -38,7 +38,9 @@ class TestBayConductorWithMesos(base.TestCase):
'http_proxy': 'http_proxy', 'http_proxy': 'http_proxy',
'https_proxy': 'https_proxy', 'https_proxy': 'https_proxy',
'no_proxy': 'no_proxy', 'no_proxy': 'no_proxy',
'server_type': 'vm' 'server_type': 'vm',
'volume_driver': 'volume_driver',
'labels': {'rexray_preempt': 'False'}
} }
self.bay_dict = { self.bay_dict = {
'id': 1, 'id': 1,
@ -58,6 +60,16 @@ class TestBayConductorWithMesos(base.TestCase):
cfg.CONF.set_override('trustee_domain_id', cfg.CONF.set_override('trustee_domain_id',
'3527620c-b220-4f37-9ebc-6e63a81a9b2f', '3527620c-b220-4f37-9ebc-6e63a81a9b2f',
group='trust') group='trust')
self.context.auth_url = 'http://192.168.10.10:5000/v3'
self.context.user_name = 'mesos_user'
self.context.tenant = 'admin'
self.context.domain_name = 'domainname'
osc_patcher = mock.patch('magnum.common.clients.OpenStackClients')
self.mock_osc_class = osc_patcher.start()
self.addCleanup(osc_patcher.stop)
self.mock_osc = mock.MagicMock()
self.mock_osc.cinder_region_name.return_value = 'RegionOne'
self.mock_osc_class.return_value = self.mock_osc
@patch('magnum.objects.BayModel.get_by_uuid') @patch('magnum.objects.BayModel.get_by_uuid')
def test_extract_template_definition_all_values( def test_extract_template_definition_all_values(
@ -88,7 +100,14 @@ class TestBayConductorWithMesos(base.TestCase):
'trustee_username': 'fake_trustee', 'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password', 'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de' 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'volume_driver': 'volume_driver',
'auth_url': 'http://192.168.10.10:5000/v3',
'region_name': self.mock_osc.cinder_region_name.return_value,
'username': 'mesos_user',
'tenant_name': 'admin',
'domain_name': 'domainname',
'rexray_preempt': 'False'
} }
self.assertEqual(expected, definition) self.assertEqual(expected, definition)
@ -98,7 +117,7 @@ class TestBayConductorWithMesos(base.TestCase):
mock_objects_baymodel_get_by_uuid): mock_objects_baymodel_get_by_uuid):
not_required = ['image_id', 'master_flavor_id', 'flavor_id', not_required = ['image_id', 'master_flavor_id', 'flavor_id',
'dns_nameserver', 'fixed_network', 'http_proxy', 'dns_nameserver', 'fixed_network', 'http_proxy',
'https_proxy', 'no_proxy'] 'https_proxy', 'no_proxy', 'volume_driver']
for key in not_required: for key in not_required:
self.baymodel_dict[key] = None self.baymodel_dict[key] = None
@ -120,7 +139,13 @@ class TestBayConductorWithMesos(base.TestCase):
'trustee_username': 'fake_trustee', 'trustee_username': 'fake_trustee',
'trustee_password': 'fake_trustee_password', 'trustee_password': 'fake_trustee_password',
'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656', 'trustee_user_id': '7b489f04-b458-4541-8179-6a48a553e656',
'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de' 'trust_id': 'bd11efc5-d4e2-4dac-bbce-25e348ddf7de',
'auth_url': 'http://192.168.10.10:5000/v3',
'region_name': self.mock_osc.cinder_region_name.return_value,
'username': 'mesos_user',
'tenant_name': 'admin',
'domain_name': 'domainname',
'rexray_preempt': 'False'
} }
self.assertEqual(expected, definition) self.assertEqual(expected, definition)

View File

@ -510,6 +510,42 @@ class AtomicSwarmTemplateDefinitionTestCase(base.TestCase):
class UbuntuMesosTemplateDefinitionTestCase(base.TestCase): class UbuntuMesosTemplateDefinitionTestCase(base.TestCase):
@mock.patch('magnum.common.clients.OpenStackClients')
@mock.patch('magnum.conductor.template_definition.BaseTemplateDefinition'
'.get_params')
@mock.patch('magnum.conductor.template_definition.TemplateDefinition'
'.get_output')
def test_mesos_get_params(self, mock_get_output, mock_get_params,
mock_osc_class):
mock_context = mock.MagicMock()
mock_context.auth_url = 'http://192.168.10.10:5000/v3'
mock_context.user_name = 'mesos_user'
mock_context.tenant = 'admin'
mock_context.domain_name = 'domainname'
mock_baymodel = mock.MagicMock()
mock_baymodel.tls_disabled = False
rexray_preempt = mock_baymodel.labels.get('rexray_preempt')
mock_bay = mock.MagicMock()
mock_bay.uuid = 'bay-xx-xx-xx-xx'
del mock_bay.stack_id
mock_osc = mock.MagicMock()
mock_osc.cinder_region_name.return_value = 'RegionOne'
mock_osc_class.return_value = mock_osc
mesos_def = tdef.UbuntuMesosTemplateDefinition()
mesos_def.get_params(mock_context, mock_baymodel, mock_bay)
expected_kwargs = {'extra_params': {
'region_name': mock_osc.cinder_region_name.return_value,
'auth_url': 'http://192.168.10.10:5000/v3',
'username': 'mesos_user',
'tenant_name': 'admin',
'domain_name': 'domainname',
'rexray_preempt': rexray_preempt}}
mock_get_params.assert_called_once_with(mock_context, mock_baymodel,
mock_bay, **expected_kwargs)
def test_mesos_get_heat_param(self): def test_mesos_get_heat_param(self):
mesos_def = tdef.UbuntuMesosTemplateDefinition() mesos_def = tdef.UbuntuMesosTemplateDefinition()