Merge lp:~nttdata/nova/850602 into lp:~hudson-openstack/nova/trunk

Proposed by Kei Masumoto
Status: Rejected
Rejected by: Brian Waldon
Proposed branch: lp:~nttdata/nova/850602
Merge into: lp:~hudson-openstack/nova/trunk
Diff against target: 145 lines (+47/-12)
2 files modified
nova/tests/test_libvirt.py (+17/-9)
nova/virt/libvirt/connection.py (+30/-3)
To merge this branch: bzr merge lp:~nttdata/nova/850602
Reviewer Review Type Date Requested Status
Jason Kölker (community) Approve
Brian Waldon (community) Approve
Review via email: mp+75480@code.launchpad.net

Description of the change

block migration needs to copy backing_file.
This branch enables existing nova handling backing_file.
Changes has been done to 2 methods in nova.virt.libvirt.connection.py.
 - pre_block_migration
 - get_instance_disk_info

Unit-test is also changed following this changes.

To post a comment you must log in.
Revision history for this message
Jason Kölker (jason-koelker) wrote :

Functionality looks good. Just a few fixes in the tests:

15 + #network_info = _fake_network_info(self.stubs, 1)
Instead of leaving the other network_info lines comented out, they should be deleted.

56 + open('/tmp/aaa', 'w+').write(str(info))
Do you mean to leave this file around?

Other than that, looks good.

review: Needs Fixing
Revision history for this message
Jason Kölker (jason-koelker) wrote :

There are also some pep8 issues that should be fixed before it hits trunk:

$ ./run_tests.sh -N -x -p
Running pep8 ...
nova/tests/test_libvirt.py:586:63: W291 trailing whitespace
        # as _fake_network_info calls utils.import_class() and
                                                              ^
    JCR: Trailing whitespace is superfluous.
    FBM: Except when it occurs as part of a blank line (i.e. the line is
         nothing but whitespace). According to Python docs[1] a line with only
         whitespace is considered a blank line, and is to be ignored. However,
         matching a blank line to its indentation level avoids mistakenly
         terminating a multi-line statement (e.g. class declaration) when
         pasting code into the standard Python interpreter.

         [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines

    The warning returned varies on whether the line itself is blank, for easier
    filtering for those who want to indent their blank lines.

    Okay: spam(1)
    W291: spam(1)\s
    W293: class Foo(object):\n \n bang = 12
nova/tests/test_libvirt.py:771:63: W291 trailing whitespace
        # as _fake_network_info calls utils.import_class() and
                                                              ^
    JCR: Trailing whitespace is superfluous.
    FBM: Except when it occurs as part of a blank line (i.e. the line is
         nothing but whitespace). According to Python docs[1] a line with only
         whitespace is considered a blank line, and is to be ignored. However,
         matching a blank line to its indentation level avoids mistakenly
         terminating a multi-line statement (e.g. class declaration) when
         pasting code into the standard Python interpreter.

         [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines

    The warning returned varies on whether the line itself is blank, for easier
    filtering for those who want to indent their blank lines.

    Okay: spam(1)
    W291: spam(1)\s
    W293: class Foo(object):\n \n bang = 12
nova/virt/libvirt/connection.py:1748:1: W293 blank line contains whitespace

^
    JCR: Trailing whitespace is superfluous.
    FBM: Except when it occurs as part of a blank line (i.e. the line is
         nothing but whitespace). According to Python docs[1] a line with only
         whitespace is considered a blank line, and is to be ignored. However,
         matching a blank line to its indentation level avoids mistakenly
         terminating a multi-line statement (e.g. class declaration) when
         pasting code into the standard Python interpreter.

         [1] http://docs.python.org/reference/lexical_analysis.html#blank-lines

    The warning returned varies on whether the line itself is blank, for easier
    filtering for those who want to indent their blank lines.

    Okay: spam(1)
    W291: spam(1)\s
    W293: class Foo(object):\n \n bang = 12

Revision history for this message
Brian Waldon (bcwaldon) wrote :

15, 85: I would prefer you just delete these lines rather than leave them commented out

115: This will definitely cause someone a headache down the road. Can you check local_gb instead of the name?

review: Needs Fixing
Revision history for this message
Kei Masumoto (masumotok) wrote :

Hello Jason and Brian,
Thanks for review this path, and sorry late reply.
I fixed based on your comment. can you check this?

Revision history for this message
Brian Waldon (bcwaldon) wrote :

Thanks, Kei. Looks good!

review: Approve
Revision history for this message
Jason Kölker (jason-koelker) wrote :

Is Bueno!

review: Approve
Revision history for this message
Rafi Khardalian (rkhardalian) wrote :

Prior to having this patch I was having my root disks corrupted with block migrations using the latest Diablo release packages. I just applied the patch to my compute nodes and re-tested and it resolved the issue.

Revision history for this message
Brian Waldon (bcwaldon) wrote :

Kei: can you migrate this MP over to review.openstack.org?

lp:~nttdata/nova/850602 updated
1575. By Kei Masumoto

delete unnecessary os.remove(disk) in pre_block_migration. block_migration fails if disk is removed.

Revision history for this message
Kei Masumoto (masumotok) wrote :

Brian, thanks for notification! I migrated this MP, but unfortunately, "approbe" is not migrated. So could you check it again?

<https://review.openstack.org/#change,716>

Kei
-----Original Message-----
From: <email address hidden> [mailto:<email address hidden>] On Behalf Of Brian Waldon
Sent: Tuesday, September 27, 2011 2:18 AM
To: <email address hidden>
Subject: Re: [Merge] lp:~nttdata/nova/850602 into lp:nova/diablo

Kei: can you migrate this MP over to review.openstack.org?
--
https://code.launchpad.net/~nttdata/nova/850602/+merge/75480
Your team NTT DATA is subscribed to branch lp:~nttdata/nova/850602.

Revision history for this message
Brian Waldon (bcwaldon) wrote :

moved to gerrit

Unmerged revisions

1575. By Kei Masumoto

delete unnecessary os.remove(disk) in pre_block_migration. block_migration fails if disk is removed.

1574. By Kei Masumoto

using instance['local_gb'] on creating backing file

1573. By Kei Masumoto

pep8 error and unnecessary debug statement fixed

1572. By Kei Masumoto

fix bugs

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'nova/tests/test_libvirt.py'
2--- nova/tests/test_libvirt.py 2011-09-19 14:22:34 +0000
3+++ nova/tests/test_libvirt.py 2011-09-28 13:07:25 +0000
4@@ -629,9 +629,12 @@
5
6 fake_timer = FakeTime()
7
8+ # _fake_network_info must be called before create_fake_libvirt_mock(),
9+ # as _fake_network_info calls utils.import_class() and
10+ # create_fake_libvirt_mock() mocks utils.import_class().
11+ network_info = _fake_network_info(self.stubs, 1)
12 self.create_fake_libvirt_mock()
13 instance_ref = db.instance_create(self.context, self.test_instance)
14- network_info = _fake_network_info(self.stubs, 1)
15
16 # Start test
17 self.mox.ReplayAll()
18@@ -684,10 +687,7 @@
19 return vdmock
20
21 self.create_fake_libvirt_mock(lookupByName=fake_lookup)
22-# self.mox.StubOutWithMock(self.compute, "recover_live_migration")
23 self.mox.StubOutWithMock(self.compute, "rollback_live_migration")
24-# self.compute.recover_live_migration(self.context, instance_ref,
25-# dest='dest')
26 self.compute.rollback_live_migration(self.context, instance_ref,
27 'dest', False)
28
29@@ -722,7 +722,8 @@
30
31 # Test data
32 instance_ref = db.instance_create(self.context, self.test_instance)
33- dummyjson = '[{"path": "%s/disk", "local_gb": "10G", "type": "raw"}]'
34+ dummyjson = ('[{"path": "%s/disk", "local_gb": "10G",'
35+ ' "type": "raw", "backing_file": ""}]')
36
37 # Preparing mocks
38 # qemu-img should be mockd since test environment might not have
39@@ -763,7 +764,10 @@
40 "</devices></domain>")
41
42 ret = ("image: /test/disk\nfile format: raw\n"
43- "virtual size: 20G (21474836480 bytes)\ndisk size: 3.1G\n")
44+ "virtual size: 20G (21474836480 bytes)\ndisk size: 3.1G\n"
45+ "disk size: 102M\n"
46+ "cluster_size: 2097152\n"
47+ "backing file: /test/dummy (actual path: /backing/file)\n")
48
49 # Preparing mocks
50 vdmock = self.mox.CreateMock(libvirt.virDomain)
51@@ -793,7 +797,9 @@
52 info[0]['path'] == '/test/disk' and
53 info[1]['path'] == '/test/disk.local' and
54 info[0]['local_gb'] == '10G' and
55- info[1]['local_gb'] == '20G')
56+ info[1]['local_gb'] == '20G' and
57+ info[0]['backing_file'] == "" and
58+ info[1]['backing_file'] == "file")
59
60 db.instance_destroy(self.context, instance_ref['id'])
61
62@@ -806,6 +812,10 @@
63 def fake_none(self, instance):
64 return
65
66+ # _fake_network_info must be called before create_fake_libvirt_mock(),
67+ # as _fake_network_info calls utils.import_class() and
68+ # create_fake_libvirt_mock() mocks utils.import_class().
69+ network_info = _fake_network_info(self.stubs, 1)
70 self.create_fake_libvirt_mock()
71 instance = db.instance_create(self.context, self.test_instance)
72
73@@ -815,8 +825,6 @@
74 conn.firewall_driver.setattr('setup_basic_filtering', fake_none)
75 conn.firewall_driver.setattr('prepare_instance_filter', fake_none)
76
77- network_info = _fake_network_info(self.stubs, 1)
78-
79 try:
80 conn.spawn(self.context, instance, network_info)
81 except Exception, e:
82
83=== modified file 'nova/virt/libvirt/connection.py'
84--- nova/virt/libvirt/connection.py 2011-09-20 10:12:01 +0000
85+++ nova/virt/libvirt/connection.py 2011-09-28 13:07:25 +0000
86@@ -1726,9 +1726,31 @@
87
88 for info in disk_info:
89 base = os.path.basename(info['path'])
90- # Get image type and create empty disk image.
91+ # Get image type and create empty disk image, and
92+ # create backing file in case of qcow2.
93 instance_disk = os.path.join(instance_dir, base)
94- utils.execute('qemu-img', 'create', '-f', info['type'],
95+ if not info['backing_file']:
96+ utils.execute('qemu-img', 'create', '-f', info['type'],
97+ instance_disk, info['local_gb'])
98+
99+ else:
100+ # Creating backing file follows same way as spawning instances.
101+ backing_file = os.path.join(FLAGS.instances_path,
102+ '_base', info['backing_file'])
103+
104+ if not os.path.exists(backing_file):
105+ self._cache_image(fn=self._fetch_image,
106+ context=ctxt,
107+ target=info['path'],
108+ fname=info['backing_file'],
109+ cow=FLAGS.use_cow_images,
110+ image_id=instance_ref['image_ref'],
111+ user_id=instance_ref['user_id'],
112+ project_id=instance_ref['project_id'],
113+ size=instance_ref['local_gb'])
114+
115+ utils.execute('qemu-img', 'create', '-f', info['type'],
116+ '-o', 'backing_file=%s' % backing_file,
117 instance_disk, info['local_gb'])
118
119 # if image has kernel and ramdisk, just download
120@@ -1819,12 +1841,17 @@
121 driver_nodes[cnt].get_properties().get_next().getContent()
122 if disk_type == 'raw':
123 size = int(os.path.getsize(path))
124+ backing_file = ""
125 else:
126 out, err = utils.execute('qemu-img', 'info', path)
127 size = [i.split('(')[1].split()[0] for i in out.split('\n')
128 if i.strip().find('virtual size') >= 0]
129 size = int(size[0])
130
131+ backing_file = [i.split('actual path:')[1].strip()[:-1]
132+ for i in out.split('\n') if 0 <= i.find('backing file')]
133+ backing_file = os.path.basename(backing_file[0])
134+
135 # block migration needs same/larger size of empty image on the
136 # destination host. since qemu-img creates bit smaller size image
137 # depending on original image size, fixed value is necessary.
138@@ -1840,7 +1867,7 @@
139 break
140
141 disk_info.append({'type': disk_type, 'path': path,
142- 'local_gb': size})
143+ 'local_gb': size, 'backing_file': backing_file})
144
145 return utils.dumps(disk_info)
146