Skip to content

Root disk size reverts to its template size after reinstall #7139

Closed

Description

@soreana

This issue is almost the same as the #3957

ISSUE TYPE
  • Bug Report
COMPONENT NAME
Instance reinstallation
CLOUDSTACK VERSION
main,
4.17, 
but not in 4.14
SUMMARY

Reinstall action acts surprisingly. When users reinstall a vm, they expect the VM configurations stay the same (like: service offering, volume sizes, IP) and a brand new operating system installs on the VM. But it is not always true. For example:

First Scenario:
  1. Deploy an instance. Don't override the root disk
  2. Resize the root volume
  3. Reinstall the VM
Expected Result Actual Result
Root volume size stays the same Root volume size resets to original value
First Scenario:
  1. Deploy an instance. Override the root disk
  2. Resize the root volume
  3. Reinstall the VM
Expected Result Actual Result
Root volume size stays the same Root volume size stays the same
Findings

In our debugging we noticed that when user overrides the root disk size an entry in user_vm_details is created. When user don't override root disk size, the entry is not created in database. In that case, CloudStack uses the template's disk size rather than the old root volume size in reinstallation process.

mysql> select * from user_vm_details where name = 'rootdisksize' ;
+----+-------+--------------+-------+---------+
| id | vm_id | name         | value | display |
+----+-------+--------------+-------+---------+
| 21 |     5 | rootdisksize | 15    |       1 |
+----+-------+--------------+-------+---------+
1 row in set (0.00 sec)

if (userVmDetailsDao.findDetail(vm.getId(), VmDetailConstants.ROOT_DISK_SIZE) == null && !newVol.getSize().equals(template.getSize())) {
VolumeVO resizedVolume = (VolumeVO) newVol;
if (template.getSize() != null) {
resizedVolume.setSize(template.getSize());
_volsDao.update(resizedVolume.getId(), resizedVolume);
}
}

Activity

  1. moved this to 👀 Review in ACS Backlogon Jan 30, 2023
  2. added this to the 4.18.0.0 milestone on Feb 1, 2023
  3. DaanHoogland commented on Feb 1, 2023

    @DaanHoogland
    Contributor

    fixed by #7145

  4. moved this from 👀 Review to Wei's List in ACS Backlogon Feb 2, 2023
  5. soreana commented on Feb 10, 2023

    @soreana
    MemberAuthor

    @weizhouapache

    Although the #7145 PR fixed the issue for new VMs, we have to update CloudStack's database manually and add an entry in user_vm_details for old VMs. I thought it would be nice to share the scrips here just in case someone has the same issue. :-)

    1. Get the affected VMs with the following sql query. Save it to a file called missing.txt
    2. Then use the python code to generate appropriate insert SQLs. python3 parser.py missing
    3. The python programm will generate the missing.sql file.
    4. Update the database using the missing.sql
    MariaDB [cloud]> SELECT distinct(view.id) as vm_id, view.uuid as vm_uuid, view.volume_id, vol.uuid as volume_uuid, \
        vol.volume_type , details.value as rootdisksize, CAST(vol.size/1024/1024/1024 AS SIGNED INTEGER) as expected \ 
        FROM cloud.user_vm_view AS view LEFT JOIN cloud.user_vm_details AS details ON view.id=details.vm_id AND \
        details.name='rootdisksize' LEFT JOIN cloud.volumes AS vol ON vol.id=view.volume_id WHERE view.state != 'Destroyed' \
        AND (CAST(vol.size/1024/1024/1024 AS SIGNED INTEGER) != details.value OR details.value IS NULL) \
        and vol.volume_type = 'ROOT' and details.value is NULL ORDER BY vm_id ;
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    | vm_id | vm_uuid                              | volume_id | volume_uuid                          | volume_type | rootdisksize | expected |
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    |   1   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff0 |       1   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff0 | ROOT        | NULL         |       12 |
    |   2   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff1 |       2   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff1 | ROOT        | NULL         |       15 |
    |   3   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff2 |       3   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff2 | ROOT        | NULL         |       25 |
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    3 rows in set (0.005 sec)
    import sys
    
    input_file_name = '{}.txt'.format( sys.argv[1] )
    output_file_name = '{}.sql'.format( sys.argv[1] )
    
    with open( input_file_name , "r") as f_in:
        with open( output_file_name , "w") as f_out:
            for li in f_in.readlines():
                if '-+-' not in li and "vm_id" not in li and "SELECT" not in li and 'rows' not in li:
                    print(li, end = '')
                    tmp = li.split('|')
                    print(tmp)
                    out_line = 'insert into user_vm_details (vm_id, name, value, display) values ( {}, \'rootdisksize\', {}, 1);\n'.format( tmp[1], tmp[-2] )
                    print(out_line, end = '')
    
                    if 'NULL' in tmp[-3]:
                        f_out.write(out_line)
  6. weizhouapache commented on Feb 11, 2023

    @weizhouapache
    Member

    @weizhouapache

    Although the #7145 PR fixed the issue for new VMs, we have to update CloudStack's database manually and add an entry in user_vm_details for old VMs. I thought it would be nice to share the scrips here just in case someone has the same issue. :-)

    1. Get the affected VMs with the following sql query. Save it to a file called missing.txt
    2. Then use the python code to generate appropriate insert SQLs. python3 parser.py missing
    3. The python programm will generate the missing.sql file.
    4. Update the database using the missing.sql
    MariaDB [cloud]> SELECT distinct(view.id) as vm_id, view.uuid as vm_uuid, view.volume_id, vol.uuid as volume_uuid, \
        vol.volume_type , details.value as rootdisksize, CAST(vol.size/1024/1024/1024 AS SIGNED INTEGER) as expected \ 
        FROM cloud.user_vm_view AS view LEFT JOIN cloud.user_vm_details AS details ON view.id=details.vm_id AND \
        details.name='rootdisksize' LEFT JOIN cloud.volumes AS vol ON vol.id=view.volume_id WHERE view.state != 'Destroyed' \
        AND (CAST(vol.size/1024/1024/1024 AS SIGNED INTEGER) != details.value OR details.value IS NULL) \
        and vol.volume_type = 'ROOT' and details.value is NULL ORDER BY vm_id ;
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    | vm_id | vm_uuid                              | volume_id | volume_uuid                          | volume_type | rootdisksize | expected |
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    |   1   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff0 |       1   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff0 | ROOT        | NULL         |       12 |
    |   2   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff1 |       2   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff1 | ROOT        | NULL         |       15 |
    |   3   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff2 |       3   | aaaaaaaa-bbbb-cccc-dddd-fffffffffff2 | ROOT        | NULL         |       25 |
    +-------+--------------------------------------+-----------+--------------------------------------+-------------+--------------+----------+
    3 rows in set (0.005 sec)
    import sys
    
    input_file_name = '{}.txt'.format( sys.argv[1] )
    output_file_name = '{}.sql'.format( sys.argv[1] )
    
    with open( input_file_name , "r") as f_in:
        with open( output_file_name , "w") as f_out:
            for li in f_in.readlines():
                if '-+-' not in li and "vm_id" not in li and "SELECT" not in li and 'rows' not in li:
                    print(li, end = '')
                    tmp = li.split('|')
                    print(tmp)
                    out_line = 'insert into user_vm_details (vm_id, name, value, display) values ( {}, \'rootdisksize\', {}, 1);\n'.format( tmp[1], tmp[-2] )
                    print(out_line, end = '')
    
                    if 'NULL' in tmp[-3]:
                        f_out.write(out_line)

    thanks @soreana for sharing
    would it be good do it via mysql procedure?

  7. soreana commented on Feb 16, 2023

    @soreana
    MemberAuthor

    @weizhouapache We had a lot of edge cases, we prefer to get the list first and manually update those. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions