diff --git a/doc/source/dev/dev-quickstart.rst b/doc/source/dev/dev-quickstart.rst index 2b99bbd703..5eff0bce23 100644 --- a/doc/source/dev/dev-quickstart.rst +++ b/doc/source/dev/dev-quickstart.rst @@ -438,6 +438,75 @@ Now that we're done with the container we can delete it:: magnum container-delete test-container +Building and Using a Mesos Bay +============================== + +Provisioning a mesos bay requires a Ubuntu-based image with some packages +pre-installed. To build and upload such image, please refer to +``_ + +Then, create a baymodel by using 'mesos' as the coe, with the rest of arguments +similar to the Kubernetes baymodel:: + + NIC_ID=$(neutron net-show public | awk '/ id /{print $4}') + magnum baymodel-create --name mesosbaymodel --image-id ubuntu-mesos \ + --keypair-id testkey \ + --external-network-id $NIC_ID \ + --dns-nameserver 8.8.8.8 --flavor-id m1.small \ + --coe mesos + +Finally, create the bay. Use the baymodel 'mesosbaymodel' as a template for +bay creation. This bay will result in one mesos master node and two mesos +slave nodes:: + + magnum bay-create --name mesosbay --baymodel mesosbaymodel --node-count 2 + +Now that we have a mesos bay we can start interacting with it. First we need +to make sure the bay's status is 'CREATE_COMPLETE':: + + $ magnum bay-show mesosbay + +----------------+--------------------------------------+ + | Property | Value | + +----------------+--------------------------------------+ + | status | CREATE_COMPLETE | + | uuid | ff727f0d-72ca-4e2b-9fef-5ec853d74fdf | + | created_at | 2015-06-09T20:21:43+00:00 | + | updated_at | 2015-06-09T20:28:18+00:00 | + | api_address | 172.24.4.115 | + | baymodel_id | 92dbda62-32d4-4435-88fc-8f42d514b347 | + | node_count | 2 | + | node_addresses | [u'172.24.4.116', u'172.24.4.117'] | + | status_reason | Stack CREATE completed successfully | + | discovery_url | None | + | name | mesosbay | + +----------------+--------------------------------------+ + +Next we will create a container in this bay by using the REST API of Marathon. +This container will ping the address 8.8.8.8:: + + $ cat > mesos.json << END + { + "container": { + "type": "DOCKER", + "docker": { + "image": "cirros" + } + }, + "id": "ubuntu", + "instances": 1, + "cpus": 0.5, + "mem": 512, + "uris": [], + "cmd": "ping 8.8.8.8" + } + END + $ MASTER_IP=$(magnum bay-show mesosbay | awk '/ api_address /{print $4}') + $ curl -X POST -H "Content-Type: application/json" \ + http://${MASTER_IP}:8080/v2/apps -d@mesos.json + +Using the Marathon web console (at http://:8080/), you will see the +application you created. + Building Developer Documentation ================================ diff --git a/etc/magnum/magnum.conf.sample b/etc/magnum/magnum.conf.sample index 014578f575..d488cd4a70 100644 --- a/etc/magnum/magnum.conf.sample +++ b/etc/magnum/magnum.conf.sample @@ -259,8 +259,12 @@ # Url for swarm public discovery endpoint. (string value) #public_swarm_discovery_url = https://discovery-stage.hub.docker.com/v1/clusters +# Location of template to build a mesos cluster on ubuntu. (string +# value) +#mesos_ubuntu_template_path = $pybasedir/templates/heat-mesos/mesoscluster.yaml + # Enabled bay definition entry points. (list value) -#enabled_definitions = magnum_vm_atomic_k8s,magnum_vm_coreos_k8s,magnum_vm_atomic_swarm +#enabled_definitions = magnum_vm_atomic_k8s,magnum_vm_coreos_k8s,magnum_vm_atomic_swarm,magnum_vm_ubuntu_mesos [bay_heat] diff --git a/magnum/conductor/template_definition.py b/magnum/conductor/template_definition.py index 6f10919304..bb0000abc1 100644 --- a/magnum/conductor/template_definition.py +++ b/magnum/conductor/template_definition.py @@ -64,9 +64,14 @@ template_def_opts = [ cfg.StrOpt('public_swarm_discovery_url', default='https://discovery-stage.hub.docker.com/v1/clusters', help=_('Url for swarm public discovery endpoint.')), + cfg.StrOpt('mesos_ubuntu_template_path', + default=paths.basedir_def('templates/heat-mesos/' + 'mesoscluster.yaml'), + help=_('Location of template to build a mesos cluster ' + 'on ubuntu. ')), cfg.ListOpt('enabled_definitions', default=['magnum_vm_atomic_k8s', 'magnum_vm_coreos_k8s', - 'magnum_vm_atomic_swarm'], + 'magnum_vm_atomic_swarm', 'magnum_vm_ubuntu_mesos'], help=_('Enabled bay definition entry points. ')), ] @@ -304,7 +309,6 @@ class BaseTemplateDefinition(TemplateDefinition): self.add_parameter('ssh_key_name', baymodel_attr='keypair_id', required=True) - self.add_parameter('server_image', baymodel_attr='image_id') self.add_parameter('dns_nameserver', @@ -452,3 +456,31 @@ class AtomicSwarmTemplateDefinition(BaseTemplateDefinition): @property def template_path(self): return cfg.CONF.bay.swarm_atomic_template_path + + +class UbuntuMesosTemplateDefinition(BaseTemplateDefinition): + provides = [ + {'platform': 'vm', 'os': 'ubuntu', 'coe': 'mesos'}, + ] + + def __init__(self): + super(UbuntuMesosTemplateDefinition, self).__init__() + self.add_parameter('external_network', + baymodel_attr='external_network_id', + required=True) + self.add_parameter('number_of_slaves', + bay_attr='node_count', + param_type=str) + self.add_parameter('master_flavor', + baymodel_attr='master_flavor_id') + self.add_parameter('slave_flavor', + baymodel_attr='flavor_id') + + self.add_output('mesos_master', + bay_attr='api_address') + self.add_output('mesos_slaves', + bay_attr='node_addresses') + + @property + def template_path(self): + return cfg.CONF.bay.mesos_ubuntu_template_path diff --git a/magnum/tests/functional/test_templates.py b/magnum/tests/functional/test_templates.py index 5c9a57fc34..cd66048811 100644 --- a/magnum/tests/functional/test_templates.py +++ b/magnum/tests/functional/test_templates.py @@ -18,7 +18,7 @@ from magnum.tests import base class TestTemplates(base.TestCase): def test_templates_list(self): entry_points = list(tdef.TemplateDefinition.load_entry_points()) - self.assertEqual(3, len(entry_points)) + self.assertEqual(4, len(entry_points)) templates = [] for entry_point, def_class in entry_points: @@ -26,5 +26,6 @@ class TestTemplates(base.TestCase): self.assertEqual(['AtomicK8sTemplateDefinition', 'AtomicSwarmTemplateDefinition', - 'CoreOSK8sTemplateDefinition'], + 'CoreOSK8sTemplateDefinition', + 'UbuntuMesosTemplateDefinition'], sorted(templates)) diff --git a/magnum/tests/unit/conductor/handlers/test_bay_conductor.py b/magnum/tests/unit/conductor/handlers/test_bay_conductor.py index d3e1e481a4..cec2030da1 100644 --- a/magnum/tests/unit/conductor/handlers/test_bay_conductor.py +++ b/magnum/tests/unit/conductor/handlers/test_bay_conductor.py @@ -745,3 +745,77 @@ class TestBayConductorWithSwarm(base.TestCase): 'discovery_url': 'test_discovery' } self.assertEqual(expected, definition) + + +class TestBayConductorWithMesos(base.TestCase): + def setUp(self): + super(TestBayConductorWithMesos, self).setUp() + self.baymodel_dict = { + 'image_id': 'image_id', + 'flavor_id': 'flavor_id', + 'master_flavor_id': 'master_flavor_id', + 'keypair_id': 'keypair_id', + 'dns_nameserver': 'dns_nameserver', + 'external_network_id': 'external_network_id', + 'fixed_network': '10.2.0.0/22', + 'cluster_distro': 'ubuntu', + 'coe': 'mesos' + } + self.bay_dict = { + 'id': 1, + 'uuid': 'some_uuid', + 'baymodel_id': 'xx-xx-xx-xx', + 'name': 'bay1', + 'stack_id': 'xx-xx-xx-xx', + 'api_address': '172.17.2.3', + 'node_addresses': ['172.17.2.4'], + 'node_count': 1, + } + + @patch('magnum.objects.BayModel.get_by_uuid') + def test_extract_template_definition_all_values( + self, + mock_objects_baymodel_get_by_uuid): + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_objects_baymodel_get_by_uuid.return_value = baymodel + bay = objects.Bay(self.context, **self.bay_dict) + + (template_path, + definition) = bay_conductor._extract_template_definition(self.context, + bay) + + expected = { + 'ssh_key_name': 'keypair_id', + 'external_network': 'external_network_id', + 'dns_nameserver': 'dns_nameserver', + 'server_image': 'image_id', + 'master_flavor': 'master_flavor_id', + 'slave_flavor': 'flavor_id', + 'number_of_slaves': '1', + 'fixed_network_cidr': '10.2.0.0/22' + } + self.assertEqual(expected, definition) + + @patch('magnum.objects.BayModel.get_by_uuid') + def test_extract_template_definition_only_required( + self, + mock_objects_baymodel_get_by_uuid): + not_required = ['image_id', 'master_flavor_id', 'flavor_id', + 'dns_nameserver', 'fixed_network'] + for key in not_required: + self.baymodel_dict[key] = None + + baymodel = objects.BayModel(self.context, **self.baymodel_dict) + mock_objects_baymodel_get_by_uuid.return_value = baymodel + bay = objects.Bay(self.context, **self.bay_dict) + + (template_path, + definition) = bay_conductor._extract_template_definition(self.context, + bay) + + expected = { + 'ssh_key_name': 'keypair_id', + 'external_network': 'external_network_id', + 'number_of_slaves': '1', + } + self.assertEqual(expected, definition) diff --git a/magnum/tests/unit/conductor/test_template_definition.py b/magnum/tests/unit/conductor/test_template_definition.py index 75924317c2..f5c1597fc8 100644 --- a/magnum/tests/unit/conductor/test_template_definition.py +++ b/magnum/tests/unit/conductor/test_template_definition.py @@ -76,6 +76,15 @@ class TemplateDefinitionTestCase(base.TestCase): self.assertIsInstance(definition, tdef.AtomicSwarmTemplateDefinition) + def test_get_vm_ubuntu_mesos_definition(self): + definition = tdef.TemplateDefinition.get_template_definition( + 'vm', + 'ubuntu', + 'mesos') + + self.assertIsInstance(definition, + tdef.UbuntuMesosTemplateDefinition) + def test_get_definition_not_supported(self): self.assertRaises(exception.BayTypeNotSupported, tdef.TemplateDefinition.get_template_definition, diff --git a/setup.cfg b/setup.cfg index c809b6108e..2d848678e4 100644 --- a/setup.cfg +++ b/setup.cfg @@ -57,6 +57,7 @@ magnum.template_definitions = magnum_vm_atomic_k8s = magnum.conductor.template_definition:AtomicK8sTemplateDefinition magnum_vm_coreos_k8s = magnum.conductor.template_definition:CoreOSK8sTemplateDefinition magnum_vm_atomic_swarm = magnum.conductor.template_definition:AtomicSwarmTemplateDefinition + magnum_vm_ubuntu_mesos = magnum.conductor.template_definition:UbuntuMesosTemplateDefinition [wheel] universal = 1