Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Boot VM from volume via python

Hi, I try to start a VM from a volume with a self-defined size via python. It works with the openstack cli in two steps:

  1. Create volume from image with a defined size: openstack volume create --image IMAGE_ID --size 40 test_volume
  2. Start VM from created Volume: openstack server create --flavor computev1-1 --volume VOLUME_ID --network NETWORK_ID test-vm

However, I can't start a VM via python. I didn't find an option to create a VM from volume instead of an image. I tried to create a VM with a mapped device from a volume. It didn't work with device_mapping or device_mapping_v2. The code and the results are posted below. How can I create a VM from volume?

  1. Create a volume image with a defined size
  2. Start a VM with an mapped volume

#!/usr/bin/env python3
import os
from keystoneauth1 import loading
from keystoneauth1 import session

import novaclient.client
import glanceclient.client
import neutronclient.v2_0.client
import cinderclient.client

def get_image(glance, name="Standard_CentOS_7.3_latest"):
    for image in glance.images.list():
        if image["name"] == name:
            return image
    return None

def get_network(neutron, name="SNAT"):
    return (networks['networks'][0]['id'])

def create_disk(cinder, size=100, image_id='27298832-7a55-42e4-ae15-60ed87a79236'):
    return cinder.volumes.create(size=size, imageRef=image_id)

loader = loading.get_plugin_loader('password')
auth = loader.load_from_options(auth_url=os.getenv('OS_AUTH_URL'),

sess = session.Session(auth=auth)

nova = novaclient.client.Client(VERSION, session=sess)
glance = glanceclient.client.Client(VERSION, session=sess)
neutron = neutronclient.v2_0.client.Client(session=sess)
cinder = cinderclient.client.Client(VERSION,session=sess)

image_id = '27298832-7a55-42e4-ae15-60ed87a79236'
network_id = 'b3e518bd-718b-4aa8-b1de-d8cd9bdefb3d'
fl = nova.flavors.find(name="c1.medium")
disk_size = 40

print("create volume")
volume_id = cinder.volumes.create(size=disk_size, imageRef=image_id).id
print("volume created: %s" % volume_id)
block_dev_mapping = {'vda':volume_id+":::0"}
block_dev_mapping_v2= [{ "boot_index": 0, "volume_id" :volume_id, "destination_type": "volume", "source_type": "volume"}]
print("create vm")
#nova.servers.create("test-vm", flavor=fl, image=image_id, volume=volume_id, nics=[{"net-id":network_id}])
# does not attach volume

#nova.servers.create("test-vm", flavor=fl, image=image_id, volume=volume_id, nics=[{"net-id":network_id}], block_device_mapping=block_dev_mapping)
# novaclient.exceptions.BadRequest: Using different block_device_mapping syntaxes is not allowed in the same request. (HTTP 400)

nova.servers.create("test-vm", flavor=fl, image=image_id, volume=volume_id, nics=[{"net-id":network_id}], block_device_mapping_v2=block_dev_mapping_v2)
# with source_type image: novaclient.exceptions.BadRequest: Block Device Mapping is Invalid: Mapping image to local is not supported. (HTTP 400)
# with source_type volume: novaclient.exceptions.NotFound: Volume null could not be found. (HTTP 404)