This is an automated email from the ASF dual-hosted git repository.

tomaz pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/libcloud.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 114f09f  openstack driver can create node from bootable vol
     new 9e3296d  Merge pull request #1362 from 
vdloo/openstack-driver-can-create-node-from-bootable-vol
114f09f is described below

commit 114f09f11abeb353ee1d19bd8e203f4daf1bdfec
Author: Rick van de Loo <[email protected]>
AuthorDate: Wed Oct 30 12:46:22 2019 +0100

    openstack driver can create node from bootable vol
    
    Currently it is not possible to use the create_node method without
    specifying an image. This is because in the OpenStack_1_1_NodeDriver
    create_node converts the server_params like:
    
    ```
    server_params = self._create_args_to_params(None, **kwargs)
    ```
    
    but in case when there is no image to boot from like when you are
    booting from an already existing bootable volume (which could have been
    created from an image earlier), then _create_args_to_params will try to
    access node.extra in order to get the imageRef, and node is None:
    
    ```
            if 'image' in kwargs:
                server_params['imageRef'] = kwargs.get('image').id
            else:
                server_params['imageRef'] = node.extra.get('imageId')
    ```
    
    Booting an instance from a previously existing bootable volume like this
    would fail:
    
    ```
    In [36]: conn.create_node(ex_availability_zone='R123', 
port='8487d948-0840-4205-8b31-7f705a19e7f4', name='r123apitestnode', ex_keyname
        ...: ='rick', size='e55a2688-ef74-44cf-b302-9a6f960c3d74', 
ex_blockdevicemappings=[{'boot_index': 0, 'uuid': 'be7ee330-b454-4414-8
        ...: e9f-c70c558dd3af', 'source_type': 'volume', 'destination_type': 
'volume', 'delete_on_termination': False}])
    ```
    
    with:
    ```
    
/usr/local/venv/hypernode-control/src/apache-libcloud/libcloud/compute/drivers/openstack.pyc
 in _create_args_to_params(self, node, **kwargs)
       1495             server_params['imageRef'] = kwargs.get('image').id
       1496         else:
    -> 1497             server_params['imageRef'] = node.extra.get('imageId')
       1498
       1499         if 'size' in kwargs:
    
    AttributeError: 'NoneType' object has no attribute 'extra'
    ```
    
    This could be circumvented by specifying `image=''`:
    ```
    In [39]: conn.create_node(ex_availability_zone='R123', 
port='8487d948-0840-4205-8b31-7f705a19e7f4', image='', name='r123apitestnode',
        ...: ex_keyname='rick', size='e55a2688-ef74-44cf-b302-9a6f960c3d74', 
ex_blockdevicemappings=[{'boot_index': 0, 'uuid': 'be7ee330-b
        ...: 454-4414-8e9f-c70c558dd3af', 'source_type': 'volume', 
'destination_type': 'volume', 'delete_on_termination': False}])
    ```
    
    This PR also changes the default imageRef to empty string '' instead of 
None to prevent the API from responding with an error like this when the .get 
would default to None so that `image=''` will now no longer have to be 
specified.
    ```
    BaseHTTPError: 400 Bad Request Invalid input for field/attribute imageRef. 
Value: None. u'None' is not valid under any of the given schemas
    ```
---
 libcloud/compute/drivers/openstack.py   |  4 +++-
 libcloud/test/compute/test_openstack.py | 20 ++++++++++++++++++++
 2 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/libcloud/compute/drivers/openstack.py 
b/libcloud/compute/drivers/openstack.py
index 6be9157..2b1039d 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -1515,7 +1515,9 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
         if 'image' in kwargs:
             server_params['imageRef'] = kwargs.get('image').id
         else:
-            server_params['imageRef'] = node.extra.get('imageId')
+            server_params['imageRef'] = node.extra.get(
+                'imageId', ''
+            ) if node else ''
 
         if 'size' in kwargs:
             server_params['flavorRef'] = kwargs.get('size').id
diff --git a/libcloud/test/compute/test_openstack.py 
b/libcloud/test/compute/test_openstack.py
index e3604e9..d172771 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -981,6 +981,26 @@ class OpenStack_1_1_Tests(unittest.TestCase, 
TestCaseMixin):
         self.assertEqual(node.name, 'racktest')
         self.assertTrue(node.extra['config_drive'])
 
+    def test_create_node_from_bootable_volume(self):
+        size = NodeSize(
+            1, '256 slice', None, None, None, None, driver=self.driver)
+
+        node = self.driver.create_node(
+            name='racktest', size=size,
+            ex_blockdevicemappings=[
+                {
+                    'boot_index': 0,
+                    'uuid': 'ee7ee330-b454-4414-8e9f-c70c558dd3af',
+                    'source_type': 'volume',
+                    'destination_type': 'volume',
+                    'delete_on_termination': False
+                }])
+
+        self.assertEqual(node.id, '26f7fbee-8ce1-4c28-887a-bfe8e4bb10fe')
+        self.assertEqual(node.name, 'racktest')
+        self.assertEqual(node.extra['password'], 'racktestvJq7d3')
+        self.assertEqual(node.extra['metadata']['My Server Name'], 'Apache1')
+
     def test_destroy_node(self):
         self.assertTrue(self.node.destroy())
 

Reply via email to