Openstack volume in-use although VM doesn't exist
A user at Cloudwatt had an issue about Cinder volumes with
status in-use
, attached to VMs that didn't exist anymore. I could
find similar bugs referenced in launchpad here and there,
both with status invalid
... But I didn't succeed in reproducing the
bug (using both the Horizon dashboard and the CLIs) until I got
feedback about what our user was doing.
The issue
The issue appears when one tries to attach a volume by using the
python-cinderclient
library in some Python code. There are actually
some weird methods for both version of the API.
These methods call the Cinder POST /volumes/{volume_id}/action
API,
which is neither documented here nor there. They can be used
to "set attachment metadata", which according to my opinion has no
good reason to be performed directly by a user.
>>> import time
>>> import cinderclient.v1.client
>>> import novaclient.v1_1.client
>>>
>>> # Creating manager
...
>>> args = ["username", "password", "project_name", "auth_url"]
>>> cinder = cinderclient.v1.client.Client(*args)
>>> nova = novaclient.v1_1.client.Client(*args)
>>>
>>> # Getting an image and a flavor to launch our VM
...
>>> img = nova.images.list()[0]
>>> fla = nova.flavors.list()[0]
>>>
>>> # Creating our resources (vm and volume)
...
>>> vm = nova.servers.create("MyVm", img, fla)
>>> vol = cinder.volumes.create(1, display_name="MyVol")
>>>
>>> # Waiting for VM to be spawned
...
>>> while nova.servers.get(vm.id).status != "ACTIVE":
... time.sleep(1)
...
>>> # Try an attach the volume using the VolumeManager.attach method
...
>>> cinder.volumes.attach(vol, vm.id, "/dev/vdb")
(<Response [202]>, None)
>>> cinder.volumes.get(vol.id)._info["attachments"]
[{u'device': u'/dev/vdb', u'server_id': u'3ee03547-7b93-4c8f-9316-bc2adafbd08a', u'volume_id': u'f024883d-4b35-4894-9fbf-51498e6c3c09', u'host_name': None, u'id': u'f024883d-4b35-4894-9fbf-51498e6c3c09'}]
>>> # Well it looks like it is attached
...
>>> vm = nova.servers.get('3ee03547-7b93-4c8f-9316-bc2adafbd08a')
>>> vm._info['os-extended-volumes:volumes_attached']
[]
>>> # But actually it isn't
...
>>>
The solution
The solution is to use the appropriate method to attach a volume to an instance. This should be done by using the novaclient.v1_1.volumes.VolumeManager.create_server_volume method. It actually allows to "attach a volume to a server", which is what we want to do (And yes the method's name is not super clear).
>>> # Let's continue on the example above
... # First by clearing our volume attachment's metadata
... # to recover a consistent state
...
>>> vol.detach()
(<Response [202]>, None)
>>> cinder.volumes.get(vol.id)._info['attachments']
[]
>>> nova.servers.get(vm.id)._info['os-extended-volumes:volumes_attached']
[]
>>> # Now we can use the VolumeManager.create_server_volume method
... # to really attach our volume to our vm
...
>>> nova.volumes.create_server_volume(vm.id, vol.id, "/dev/vdb")
<Volume: f024883d-4b35-4894-9fbf-51498e6c3c09>
>>> cinder.volumes.get(vol.id)._info["attachments"]
[{u'device': u'/dev/vdb', u'server_id': u'3ee03547-7b93-4c8f-9316-bc2adafbd08a', u'volume_id': u'f024883d-4b35-4894-9fbf-51498e6c3c09', u'host_name': None, u'id': u'f024883d-4b35-4894-9fbf-51498e6c3c09'}]
>>> nova.servers.get(vm.id)._info['os-extended-volumes:volumes_attached']
[{u'id': u'f024883d-4b35-4894-9fbf-51498e6c3c09'}]
>>>
The bug
Although, we could argue that the inconsistent state is due to a bad usage of the client libraries, I do believe that Cinder API (and therefore python-cinderclient) should not allow the user to put its resources in an inconsistent state. Moreover, it isn't possible to recover from such state by using the Horizon dashboard or the CLIs. To do so, one has to either use the Python client libraries, or update entries in the database manually...
Recovering from inconsistent state
One way to recover from a "volume attached to non-existent VM" inconsistent state, is to manually update entries in the Cinder database.
$ mysql cinder
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1900
Server version: 5.5.34-0ubuntu0.12.04.1-log (Ubuntu)
Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> SELECT id,status,attach_status,mountpoint,instance_uuid from volumes;
+--------------------------------------+---------+---------------+------------+--------------------------------------+
| id | status | attach_status | mountpoint | instance_uuid |
+--------------------------------------+---------+---------------+------------+--------------------------------------+
| 0580142b-bfb5-4113-8676-4fb783ec05f2 | deleted | detached | NULL | NULL |
| 1085d96e-ae82-484b-8495-27cc2f25c9c3 | deleted | detached | NULL | NULL |
| 4fbff7ce-2c9f-4116-ad1e-12f78001da2d | deleted | detached | NULL | NULL |
| 57b32eaf-7b71-49bf-a8fd-4115567a6cda | in-use | attached | /dev/vdb | fa53d190-426b-4ce6-8d36-1af408c25225 |
| 60a7eb30-9849-4b8d-9ca1-8f554b9a4045 | deleted | detached | NULL | NULL |
| a34ca08a-2e6b-4820-b472-91aa27b47261 | deleted | detached | NULL | NULL |
| d827daa5-c8d7-427b-a53c-8be918a1a6fb | deleted | detached | NULL | NULL |
+--------------------------------------+---------+---------------+------------+--------------------------------------+
7 rows in set (0.00 sec)
mysql> UPDATE volumes SET status="available", attach_status="detached", mountpoint=NULL, instance_uuid=NULL WHERE id="57b32eaf-7b71-49bf-a8fd-4115567a6cda";
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT id,status,attach_status,mountpoint,instance_uuid from volumes;
+--------------------------------------+-----------+---------------+------------+---------------+
| id | status | attach_status | mountpoint | instance_uuid |
+--------------------------------------+-----------+---------------+------------+---------------+
| 0580142b-bfb5-4113-8676-4fb783ec05f2 | deleted | detached | NULL | NULL |
| 1085d96e-ae82-484b-8495-27cc2f25c9c3 | deleted | detached | NULL | NULL |
| 4fbff7ce-2c9f-4116-ad1e-12f78001da2d | deleted | detached | NULL | NULL |
| 57b32eaf-7b71-49bf-a8fd-4115567a6cda | available | detached | NULL | NULL |
| 60a7eb30-9849-4b8d-9ca1-8f554b9a4045 | deleted | detached | NULL | NULL |
| a34ca08a-2e6b-4820-b472-91aa27b47261 | deleted | detached | NULL | NULL |
| d827daa5-c8d7-427b-a53c-8be918a1a6fb | deleted | detached | NULL | NULL |
+--------------------------------------+-----------+---------------+------------+---------------+
7 rows in set (0.00 sec)
mysql> Bye
$ cinder list
+--------------------------------------+-----------+------+------+-------------+----------+-------------+
| ID | Status | Name | Size | Volume Type | Bootable | Attached to |
+--------------------------------------+-----------+------+------+-------------+----------+-------------+
| 57b32eaf-7b71-49bf-a8fd-4115567a6cda | available | vol1 | 1 | None | false | |
+--------------------------------------+-----------+------+------+-------------+----------+-------------+