From d523f31c57eba43ee169bf9bfbca896a532bae40 Mon Sep 17 00:00:00 2001 From: Andrey Shestakov Date: Thu, 15 Aug 2013 18:09:29 +0300 Subject: [PATCH] Add instance cloudinit support implements blueprint guestagent-through-userdata Change-Id: Ifb33f149e63d7b9b7ed676da8ff05085ceceffeb --- etc/trove/cloudinit/README | 3 + trove/common/cfg.py | 2 + trove/taskmanager/models.py | 9 ++- trove/tests/fakes/nova.py | 2 +- .../unittests/taskmanager/test_models.py | 65 +++++++++++++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 etc/trove/cloudinit/README diff --git a/etc/trove/cloudinit/README b/etc/trove/cloudinit/README new file mode 100644 index 0000000000..f9e9aa8d68 --- /dev/null +++ b/etc/trove/cloudinit/README @@ -0,0 +1,3 @@ +These cloudinit scripts will used as userdata on instance create +File names should match pattern: service_type.cloudinit +For example: mysql.cloudinit diff --git a/trove/common/cfg.py b/trove/common/cfg.py index b5276f50a2..5df831e7ac 100644 --- a/trove/common/cfg.py +++ b/trove/common/cfg.py @@ -174,6 +174,8 @@ common_opts = [ cfg.StrOpt('nova_proxy_admin_tenant_name', default='', help="Admin tenant used to connect to Nova"), cfg.StrOpt('network_label_regex', default='^private$'), + cfg.StrOpt('cloudinit_location', default='/etc/trove/cloudinit', + help="Path to folder with cloudinit scripts"), ] diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py index 00b822346e..ae5efd1513 100644 --- a/trove/taskmanager/models.py +++ b/trove/taskmanager/models.py @@ -13,7 +13,7 @@ # under the License. import traceback - +import os.path from cinderclient import exceptions as cinder_exceptions from eventlet import greenthread from novaclient import exceptions as nova_exceptions @@ -334,10 +334,17 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin): files = {"/etc/guest_info": ("[DEFAULT]\nguest_id=%s\n" "service_type=%s\n" % (self.id, service_type))} + userdata = None + cloudinit = os.path.join(CONF.get('cloudinit_location'), + "%s.cloudinit" % service_type) + if os.path.isfile(cloudinit): + with open(cloudinit, "r") as f: + userdata = f.read() name = self.hostname or self.name bdmap = block_device_mapping server = self.nova_client.servers.create(name, image_id, flavor_id, files=files, + userdata=userdata, security_groups= security_groups, block_device_mapping=bdmap) diff --git a/trove/tests/fakes/nova.py b/trove/tests/fakes/nova.py index b86a4d44b9..ac2d01d232 100644 --- a/trove/tests/fakes/nova.py +++ b/trove/tests/fakes/nova.py @@ -262,7 +262,7 @@ class FakeServers(object): return (self.context.is_admin or server.owner.tenant == self.context.tenant) - def create(self, name, image_id, flavor_ref, files=None, + def create(self, name, image_id, flavor_ref, files=None, userdata=None, block_device_mapping=None, volume=None, security_groups=None): id = "FAKE_%s" % uuid.uuid4() if volume: diff --git a/trove/tests/unittests/taskmanager/test_models.py b/trove/tests/unittests/taskmanager/test_models.py index c73919de82..74fb0a1369 100644 --- a/trove/tests/unittests/taskmanager/test_models.py +++ b/trove/tests/unittests/taskmanager/test_models.py @@ -19,6 +19,71 @@ import trove.backup.models as backup_models from trove.common.exception import TroveError from mockito import mock, when, unstub, any, verify, never from swiftclient.client import ClientException +from tempfile import NamedTemporaryFile +import os + + +class fake_Server: + def __init__(self): + self.id = None + self.name = None + self.image_id = None + self.flavor_id = None + self.files = None + self.userdata = None + self.security_groups = None + self.block_device_mapping = None + + +class fake_ServerManager: + def create(self, name, image_id, flavor_id, files, userdata, + security_groups, block_device_mapping): + server = fake_Server() + server.id = "server_id" + server.name = name + server.image_id = image_id + server.flavor_id = flavor_id + server.files = files + server.userdata = userdata + server.security_groups = security_groups + server.block_device_mapping = block_device_mapping + return server + + +class fake_nova_client: + def __init__(self): + self.servers = fake_ServerManager() + + +class FreshInstanceTasksTest(testtools.TestCase): + def setUp(self): + super(FreshInstanceTasksTest, self).setUp() + when(taskmanager_models.FreshInstanceTasks).id().thenReturn( + "instance_id") + when(taskmanager_models.FreshInstanceTasks).hostname().thenReturn( + "hostname") + taskmanager_models.FreshInstanceTasks.nova_client = fake_nova_client() + taskmanager_models.CONF = mock() + self.userdata = "hello moto" + with NamedTemporaryFile(suffix=".cloudinit", delete=False) as f: + self.cloudinit = f.name + f.write(self.userdata) + self.freshinstancetasks = taskmanager_models.FreshInstanceTasks( + None, None, None, None) + + def tearDown(self): + super(FreshInstanceTasksTest, self).tearDown() + os.remove(self.cloudinit) + unstub() + + def test_create_instance_userdata(self): + cloudinit_location = os.path.dirname(self.cloudinit) + service_type = os.path.splitext(os.path.basename(self.cloudinit))[0] + when(taskmanager_models.CONF).get("cloudinit_location").thenReturn( + cloudinit_location) + server = self.freshinstancetasks._create_server(None, None, None, + service_type, None) + self.assertEqual(server.userdata, self.userdata) class BackupTasksTest(testtools.TestCase):