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:
parent
def0cce268
commit
c932d5fab9
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
|
@ -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"
|
||||||
|
|
|
@ -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:
|
||||||
|
|
||||||
|
|
|
@ -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}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue