summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/api_samples/os-coverage/coverage-report-post-req.json5
-rw-r--r--doc/api_samples/os-coverage/coverage-report-post-req.xml4
-rw-r--r--doc/api_samples/os-coverage/coverage-report-post-resp.json3
-rw-r--r--doc/api_samples/os-coverage/coverage-report-post-resp.xml2
-rw-r--r--doc/api_samples/os-coverage/coverage-start-combine-post-req.json5
-rw-r--r--doc/api_samples/os-coverage/coverage-start-combine-post-req.xml4
-rw-r--r--doc/api_samples/os-coverage/coverage-start-post-req.json4
-rw-r--r--doc/api_samples/os-coverage/coverage-start-post-req.xml2
-rw-r--r--doc/api_samples/os-coverage/coverage-stop-post-req.json4
-rw-r--r--doc/api_samples/os-coverage/coverage-stop-post-req.xml2
-rw-r--r--doc/api_samples/os-coverage/coverage-xml-report-post-req.json6
-rw-r--r--doc/api_samples/os-coverage/coverage-xml-report-post-req.xml5
-rw-r--r--doc/api_samples/os-coverage/coverage-xml-report-post-resp.json3
-rw-r--r--doc/api_samples/os-coverage/coverage-xml-report-post-resp.xml2
-rw-r--r--nova/locale/nova.pot108
-rw-r--r--nova/tests/api/openstack/compute/test_servers.py13
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.json.tpl5
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.xml.tpl4
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.json.tpl3
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.xml.tpl2
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.json.tpl5
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.xml.tpl4
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.json.tpl4
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.xml.tpl2
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.json.tpl4
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.xml.tpl2
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.json.tpl6
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.xml.tpl5
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.json.tpl3
-rw-r--r--nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.xml.tpl2
-rw-r--r--nova/tests/integrated/test_api_samples.py71
-rw-r--r--nova/tests/test_libvirt.py4
-rw-r--r--nova/tests/test_virt.py10
-rw-r--r--nova/tests/test_virt_disk.py22
-rw-r--r--nova/virt/disk/api.py11
-rw-r--r--nova/virt/libvirt/driver.py46
36 files changed, 298 insertions, 89 deletions
diff --git a/doc/api_samples/os-coverage/coverage-report-post-req.json b/doc/api_samples/os-coverage/coverage-report-post-req.json
new file mode 100644
index 000000000..cb16cfc85
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-report-post-req.json
@@ -0,0 +1,5 @@
+{
+ "report" : {
+ "file" : "report"
+ }
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-report-post-req.xml b/doc/api_samples/os-coverage/coverage-report-post-req.xml
new file mode 100644
index 000000000..1cc9b7433
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-report-post-req.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<report>
+ <file>report</file>
+</report> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-report-post-resp.json b/doc/api_samples/os-coverage/coverage-report-post-resp.json
new file mode 100644
index 000000000..e7db3076a
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-report-post-resp.json
@@ -0,0 +1,3 @@
+{
+ "path": "/tmp/tmpV0Pno7/nova-coverage_D8L8SB/report"
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-report-post-resp.xml b/doc/api_samples/os-coverage/coverage-report-post-resp.xml
new file mode 100644
index 000000000..8b7188ad0
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-report-post-resp.xml
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<path>/tmp/tmpAqRtz5/nova-coverage_Iqja9E/report</path> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-start-combine-post-req.json b/doc/api_samples/os-coverage/coverage-start-combine-post-req.json
new file mode 100644
index 000000000..6d41ba598
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-start-combine-post-req.json
@@ -0,0 +1,5 @@
+{
+ "start" : {
+ "combine": true
+ }
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-start-combine-post-req.xml b/doc/api_samples/os-coverage/coverage-start-combine-post-req.xml
new file mode 100644
index 000000000..10489b3be
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-start-combine-post-req.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<start>
+ <combine>True</combine>
+</start> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-start-post-req.json b/doc/api_samples/os-coverage/coverage-start-post-req.json
new file mode 100644
index 000000000..8e5ef033c
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-start-post-req.json
@@ -0,0 +1,4 @@
+{
+ "start" : {
+ }
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-start-post-req.xml b/doc/api_samples/os-coverage/coverage-start-post-req.xml
new file mode 100644
index 000000000..398971d54
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-start-post-req.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<start></start> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-stop-post-req.json b/doc/api_samples/os-coverage/coverage-stop-post-req.json
new file mode 100644
index 000000000..57de88191
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-stop-post-req.json
@@ -0,0 +1,4 @@
+{
+ "stop" : {
+ }
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-stop-post-req.xml b/doc/api_samples/os-coverage/coverage-stop-post-req.xml
new file mode 100644
index 000000000..7092c81e2
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-stop-post-req.xml
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<stop></stop> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-xml-report-post-req.json b/doc/api_samples/os-coverage/coverage-xml-report-post-req.json
new file mode 100644
index 000000000..bcbe0c4a0
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-xml-report-post-req.json
@@ -0,0 +1,6 @@
+{
+ "report": {
+ "xml": true,
+ "file": "report"
+ }
+}
diff --git a/doc/api_samples/os-coverage/coverage-xml-report-post-req.xml b/doc/api_samples/os-coverage/coverage-xml-report-post-req.xml
new file mode 100644
index 000000000..62e5bc6f4
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-xml-report-post-req.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<report>
+ <file>report</file>
+ <xml>True</xml>
+</report> \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-xml-report-post-resp.json b/doc/api_samples/os-coverage/coverage-xml-report-post-resp.json
new file mode 100644
index 000000000..0648b2ebc
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-xml-report-post-resp.json
@@ -0,0 +1,3 @@
+{
+ "path": "/tmp/tmp6kdYaa/nova-coverage_TOTUbz/report"
+} \ No newline at end of file
diff --git a/doc/api_samples/os-coverage/coverage-xml-report-post-resp.xml b/doc/api_samples/os-coverage/coverage-xml-report-post-resp.xml
new file mode 100644
index 000000000..72f584003
--- /dev/null
+++ b/doc/api_samples/os-coverage/coverage-xml-report-post-resp.xml
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<path>/tmp/tmp4j87bp/nova-coverage_7ViTA7/report</path> \ No newline at end of file
diff --git a/nova/locale/nova.pot b/nova/locale/nova.pot
index 4aab88bdd..af5c0fc32 100644
--- a/nova/locale/nova.pot
+++ b/nova/locale/nova.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: nova 2013.1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
-"POT-Creation-Date: 2012-12-24 00:02+0000\n"
+"POT-Creation-Date: 2012-12-27 00:01+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -5930,7 +5930,7 @@ msgstr ""
msgid "The ISCSI initiator name can't be found. Choosing the default one"
msgstr ""
-#: nova/virt/hyperv/basevolumeutils.py:79 nova/virt/libvirt/driver.py:1510
+#: nova/virt/hyperv/basevolumeutils.py:79 nova/virt/libvirt/driver.py:1494
#: nova/virt/xenapi/vm_utils.py:504
#, python-format
msgid "block_device_list %s"
@@ -5979,7 +5979,7 @@ msgstr ""
msgid "get_available_resource called"
msgstr ""
-#: nova/virt/hyperv/hostops.py:163 nova/virt/libvirt/driver.py:3173
+#: nova/virt/hyperv/hostops.py:163 nova/virt/libvirt/driver.py:3179
#: nova/virt/xenapi/host.py:149
msgid "Updating host stats"
msgstr ""
@@ -6163,16 +6163,16 @@ msgstr ""
msgid "Invalid config_drive_format \"%s\""
msgstr ""
-#: nova/virt/hyperv/vmops.py:183 nova/virt/libvirt/driver.py:1443
+#: nova/virt/hyperv/vmops.py:183 nova/virt/libvirt/driver.py:1432
msgid "Using config drive"
msgstr ""
-#: nova/virt/hyperv/vmops.py:194 nova/virt/libvirt/driver.py:1453
+#: nova/virt/hyperv/vmops.py:194 nova/virt/libvirt/driver.py:1442
#, python-format
msgid "Creating config drive at %(path)s"
msgstr ""
-#: nova/virt/hyperv/vmops.py:201 nova/virt/libvirt/driver.py:1458
+#: nova/virt/hyperv/vmops.py:201 nova/virt/libvirt/driver.py:1447
#, python-format
msgid "Creating config drive failed with error: %s"
msgstr ""
@@ -6424,7 +6424,7 @@ msgstr ""
msgid "Failed to remove volume from VM %s"
msgstr ""
-#: nova/virt/hyperv/volumeops.py:228 nova/virt/libvirt/driver.py:629
+#: nova/virt/hyperv/volumeops.py:228 nova/virt/libvirt/driver.py:624
msgid "Could not determine iscsi initiator name"
msgstr ""
@@ -6594,183 +6594,183 @@ msgstr ""
msgid "Deleting instance files %(target)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:592
+#: nova/virt/libvirt/driver.py:587
#, python-format
msgid "Failed to cleanup directory %(target)s: %(e)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:752
+#: nova/virt/libvirt/driver.py:747
msgid "During detach_volume, instance disappeared."
msgstr ""
-#: nova/virt/libvirt/driver.py:762
+#: nova/virt/libvirt/driver.py:757
msgid "attaching LXC block device"
msgstr ""
-#: nova/virt/libvirt/driver.py:782
+#: nova/virt/libvirt/driver.py:777
msgid "detaching LXC block device"
msgstr ""
-#: nova/virt/libvirt/driver.py:914
+#: nova/virt/libvirt/driver.py:909
msgid "Instance soft rebooted successfully."
msgstr ""
-#: nova/virt/libvirt/driver.py:918
+#: nova/virt/libvirt/driver.py:913
msgid "Failed to soft reboot instance."
msgstr ""
-#: nova/virt/libvirt/driver.py:950
+#: nova/virt/libvirt/driver.py:945
msgid "Instance shutdown successfully."
msgstr ""
-#: nova/virt/libvirt/driver.py:986
+#: nova/virt/libvirt/driver.py:981
msgid "Instance rebooted successfully."
msgstr ""
-#: nova/virt/libvirt/driver.py:1114
+#: nova/virt/libvirt/driver.py:1109
msgid "Instance is running"
msgstr ""
-#: nova/virt/libvirt/driver.py:1121 nova/virt/powervm/operator.py:255
+#: nova/virt/libvirt/driver.py:1116 nova/virt/powervm/operator.py:255
msgid "Instance spawned successfully."
msgstr ""
-#: nova/virt/libvirt/driver.py:1137
+#: nova/virt/libvirt/driver.py:1132
#, python-format
msgid "data: %(data)r, fpath: %(fpath)r"
msgstr ""
-#: nova/virt/libvirt/driver.py:1175 nova/virt/libvirt/driver.py:1201
+#: nova/virt/libvirt/driver.py:1170 nova/virt/libvirt/driver.py:1196
#, python-format
msgid "Truncated console log returned, %d bytes ignored"
msgstr ""
-#: nova/virt/libvirt/driver.py:1190
+#: nova/virt/libvirt/driver.py:1185
msgid "Guest does not have a console available"
msgstr ""
-#: nova/virt/libvirt/driver.py:1239
+#: nova/virt/libvirt/driver.py:1234
#, python-format
msgid "Path '%(path)s' supports direct I/O"
msgstr ""
-#: nova/virt/libvirt/driver.py:1243
+#: nova/virt/libvirt/driver.py:1238
#, python-format
msgid "Path '%(path)s' does not support direct I/O: '%(ex)s'"
msgstr ""
-#: nova/virt/libvirt/driver.py:1247 nova/virt/libvirt/driver.py:1251
+#: nova/virt/libvirt/driver.py:1242 nova/virt/libvirt/driver.py:1246
#, python-format
msgid "Error on '%(path)s' while checking direct I/O: '%(ex)s'"
msgstr ""
-#: nova/virt/libvirt/driver.py:1317
+#: nova/virt/libvirt/driver.py:1312
msgid "Creating image"
msgstr ""
-#: nova/virt/libvirt/driver.py:1473
+#: nova/virt/libvirt/driver.py:1462
#, python-format
msgid "Injecting %(injection)s into image %(img_id)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:1483
+#: nova/virt/libvirt/driver.py:1472
#, python-format
msgid "Ignoring error injecting data into image %(img_id)s (%(e)s)"
msgstr ""
-#: nova/virt/libvirt/driver.py:1562
+#: nova/virt/libvirt/driver.py:1546
#, python-format
msgid ""
"Config requested an explicit CPU model, but the current libvirt "
"hypervisor '%s' does not support selecting CPU models"
msgstr ""
-#: nova/virt/libvirt/driver.py:1568
+#: nova/virt/libvirt/driver.py:1552
msgid "Config requested a custom CPU model, but no model name was provided"
msgstr ""
-#: nova/virt/libvirt/driver.py:1572
+#: nova/virt/libvirt/driver.py:1556
msgid "A CPU model name should not be set when a host CPU model is requested"
msgstr ""
-#: nova/virt/libvirt/driver.py:1576
+#: nova/virt/libvirt/driver.py:1560
#, python-format
msgid "CPU mode '%(mode)s' model '%(model)s' was chosen"
msgstr ""
-#: nova/virt/libvirt/driver.py:1592
+#: nova/virt/libvirt/driver.py:1576
msgid ""
"Passthrough of the host CPU was requested but this libvirt version does "
"not support this feature"
msgstr ""
-#: nova/virt/libvirt/driver.py:1909
+#: nova/virt/libvirt/driver.py:1893
msgid "Starting toXML method"
msgstr ""
-#: nova/virt/libvirt/driver.py:1913
+#: nova/virt/libvirt/driver.py:1897
msgid "Finished toXML method"
msgstr ""
-#: nova/virt/libvirt/driver.py:1930
+#: nova/virt/libvirt/driver.py:1914
#, python-format
msgid ""
"Error from libvirt while looking up %(instance_name)s: [Error Code "
"%(error_code)s] %(ex)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2062
+#: nova/virt/libvirt/driver.py:2068
msgid ""
"Cannot get the number of cpu, because this function is not implemented "
"for this platform. "
msgstr ""
-#: nova/virt/libvirt/driver.py:2179
+#: nova/virt/libvirt/driver.py:2185
msgid "libvirt version is too old (does not support getVersion)"
msgstr ""
-#: nova/virt/libvirt/driver.py:2262
+#: nova/virt/libvirt/driver.py:2268
#, python-format
msgid "Trying to get stats for the volume %s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2286
+#: nova/virt/libvirt/driver.py:2292
#, python-format
msgid ""
"Getting block stats failed, device might have been detached. "
"Code=%(errcode)s Error=%(e)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2290
+#: nova/virt/libvirt/driver.py:2296
#, python-format
msgid ""
"Could not find domain in libvirt for instance %s. Cannot get block stats "
"for device"
msgstr ""
-#: nova/virt/libvirt/driver.py:2406
+#: nova/virt/libvirt/driver.py:2412
msgid "Block migration can not be used with shared storage."
msgstr ""
-#: nova/virt/libvirt/driver.py:2414
+#: nova/virt/libvirt/driver.py:2420
msgid "Live migration can not be used without shared storage."
msgstr ""
-#: nova/virt/libvirt/driver.py:2451
+#: nova/virt/libvirt/driver.py:2457
#, python-format
msgid ""
"Unable to migrate %(instance_uuid)s: Disk of instance is too "
"large(available on destination host:%(available)s < need:%(necessary)s)"
msgstr ""
-#: nova/virt/libvirt/driver.py:2476
+#: nova/virt/libvirt/driver.py:2482
#, python-format
msgid ""
"Instance launched has CPU info:\n"
"%s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2488
+#: nova/virt/libvirt/driver.py:2494
#, python-format
msgid ""
"CPU doesn't have compatibility.\n"
@@ -6780,51 +6780,51 @@ msgid ""
"Refer to %(u)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2505
+#: nova/virt/libvirt/driver.py:2511
#, python-format
msgid ""
"Creating tmpfile %s to notify to other compute nodes that they should "
"mount the same storage."
msgstr ""
-#: nova/virt/libvirt/driver.py:2553
+#: nova/virt/libvirt/driver.py:2559
#, python-format
msgid "The firewall filter for %s does not exist"
msgstr ""
-#: nova/virt/libvirt/driver.py:2625
+#: nova/virt/libvirt/driver.py:2631
#, python-format
msgid "Live Migration failure: %(e)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2715
+#: nova/virt/libvirt/driver.py:2721
#, python-format
msgid "plug_vifs() failed %(cnt)d.Retry up to %(max_retry)d for %(hostname)s."
msgstr ""
-#: nova/virt/libvirt/driver.py:2830
+#: nova/virt/libvirt/driver.py:2836
#, python-format
msgid "skipping %(path)s since it looks like volume"
msgstr ""
-#: nova/virt/libvirt/driver.py:2879
+#: nova/virt/libvirt/driver.py:2885
#, python-format
msgid "Getting disk size of %(i_name)s: %(e)s"
msgstr ""
-#: nova/virt/libvirt/driver.py:2928
+#: nova/virt/libvirt/driver.py:2934
msgid "Starting migrate_disk_and_power_off"
msgstr ""
-#: nova/virt/libvirt/driver.py:2987
+#: nova/virt/libvirt/driver.py:2993
msgid "Instance running successfully."
msgstr ""
-#: nova/virt/libvirt/driver.py:2994
+#: nova/virt/libvirt/driver.py:3000
msgid "Starting finish_migration"
msgstr ""
-#: nova/virt/libvirt/driver.py:3045
+#: nova/virt/libvirt/driver.py:3051
msgid "Starting finish_revert_migration"
msgstr ""
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index 15be74d15..d32640bf2 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -1520,9 +1520,9 @@ class ServersControllerTest(test.TestCase):
self.assertEqual(s['hostId'], host_ids[i % 2])
self.assertEqual(s['name'], 'server%d' % (i + 1))
- def test_delete_server_instance(self):
+ def _delete_server_instance(self, uuid=FAKE_UUID):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
- req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
+ req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % uuid)
req.method = 'DELETE'
self.server_delete_called = False
@@ -1534,10 +1534,17 @@ class ServersControllerTest(test.TestCase):
self.server_delete_called = True
self.stubs.Set(db, 'instance_destroy', instance_destroy_mock)
- self.controller.delete(req, FAKE_UUID)
+ self.controller.delete(req, uuid)
+ def test_delete_server_instance(self):
+ self._delete_server_instance()
self.assertEqual(self.server_delete_called, True)
+ def test_delete_server_instance_not_found(self):
+ self.assertRaises(webob.exc.HTTPNotFound,
+ self._delete_server_instance,
+ uuid='non-existent-uuid')
+
def test_delete_server_instance_while_building(self):
fakes.stub_out_instance_quota(self.stubs, 0, 10)
req = fakes.HTTPRequest.blank('/v2/fake/servers/%s' % FAKE_UUID)
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.json.tpl
new file mode 100644
index 000000000..c228b05f0
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.json.tpl
@@ -0,0 +1,5 @@
+{
+ "report" : {
+ "file" : "%(filename)s"
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.xml.tpl
new file mode 100644
index 000000000..02b8fc97c
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-req.xml.tpl
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<report>
+ <file>%(filename)s</file>
+</report>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.json.tpl
new file mode 100644
index 000000000..6cdd1f37d
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.json.tpl
@@ -0,0 +1,3 @@
+{
+ "path" : "%(path)s"
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.xml.tpl
new file mode 100644
index 000000000..51b9773d3
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-report-post-resp.xml.tpl
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<path>%(path)s</path>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.json.tpl
new file mode 100644
index 000000000..296049df9
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.json.tpl
@@ -0,0 +1,5 @@
+{
+ "start" : {
+ "combine": true
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.xml.tpl
new file mode 100644
index 000000000..11bdb44f9
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-start-combine-post-req.xml.tpl
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<start>
+ <combine>True</combine>
+</start>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.json.tpl
new file mode 100644
index 000000000..a046b9207
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.json.tpl
@@ -0,0 +1,4 @@
+{
+ "start" : {
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.xml.tpl
new file mode 100644
index 000000000..aeaff102a
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-start-post-req.xml.tpl
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<start></start>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.json.tpl
new file mode 100644
index 000000000..c46e49cca
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.json.tpl
@@ -0,0 +1,4 @@
+{
+ "stop" : {
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.xml.tpl
new file mode 100644
index 000000000..1dd5c7bc7
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-stop-post-req.xml.tpl
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<stop></stop>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.json.tpl
new file mode 100644
index 000000000..906d629ed
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.json.tpl
@@ -0,0 +1,6 @@
+{
+ "report": {
+ "xml": true,
+ "file": "%(filename)s"
+ }
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.xml.tpl
new file mode 100644
index 000000000..902e0e537
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-req.xml.tpl
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<report>
+ <file>%(filename)s</file>
+ <xml>True</xml>
+</report>
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.json.tpl
new file mode 100644
index 000000000..6cdd1f37d
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.json.tpl
@@ -0,0 +1,3 @@
+{
+ "path" : "%(path)s"
+}
diff --git a/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.xml.tpl
new file mode 100644
index 000000000..65f5e16bc
--- /dev/null
+++ b/nova/tests/integrated/api_samples/os-coverage/coverage-xml-report-post-resp.xml.tpl
@@ -0,0 +1,2 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<path>%(path)s</path>
diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py
index a33b39da4..a8099a6bb 100644
--- a/nova/tests/integrated/test_api_samples.py
+++ b/nova/tests/integrated/test_api_samples.py
@@ -21,8 +21,10 @@ import re
import urllib
import uuid as uuid_lib
+from coverage import coverage
from lxml import etree
+from nova.api.openstack.compute.contrib import coverage_ext
# Import extensions to pull in osapi_compute_extension CONF option used below.
from nova.api.openstack.compute import extensions
from nova.cloudpipe.pipelib import CloudPipe
@@ -353,7 +355,6 @@ class ApiSamplesTrap(ApiSampleTestBase):
do_not_approve_additions.append('NMN')
do_not_approve_additions.append('OS-FLV-DISABLED')
do_not_approve_additions.append('os-config-drive')
- do_not_approve_additions.append('os-coverage')
do_not_approve_additions.append('os-create-server-ext')
do_not_approve_additions.append('os-fixed-ips')
do_not_approve_additions.append('os-flavor-access')
@@ -729,6 +730,74 @@ class LimitsSampleXmlTest(LimitsSampleJsonTest):
ctype = 'xml'
+class CoverageExtJsonTests(ApiSampleTestBase):
+ extension_name = ("nova.api.openstack.compute.contrib.coverage_ext."
+ "Coverage_ext")
+
+ def setUp(self):
+ super(CoverageExtJsonTests, self).setUp()
+
+ def _fake_check_coverage(self):
+ return False
+
+ def _fake_xml_report(self, outfile=None):
+ return
+
+ self.stubs.Set(coverage_ext.CoverageController, '_check_coverage',
+ _fake_check_coverage)
+ self.stubs.Set(coverage, 'xml_report', _fake_xml_report)
+
+ def test_start_coverage(self):
+ """Start coverage data collection"""
+ subs = {}
+ response = self._do_post('os-coverage/action',
+ 'coverage-start-post-req', subs)
+ self.assertEqual(response.status, 200)
+
+ def test_start_coverage_combine(self):
+ """Start coverage data collection"""
+ subs = {}
+ response = self._do_post('os-coverage/action',
+ 'coverage-start-combine-post-req', subs)
+ self.assertEqual(response.status, 200)
+
+ def test_stop_coverage(self):
+ """Stop coverage data collection"""
+ subs = {}
+ response = self._do_post('os-coverage/action',
+ 'coverage-stop-post-req', subs)
+ self.assertEqual(response.status, 200)
+
+ def test_report_coverage(self):
+ """Generate a coverage report"""
+ subs = {
+ 'filename': 'report',
+ 'path': '/.*/report',
+ }
+ response = self._do_post('os-coverage/action',
+ 'coverage-report-post-req', subs)
+ self.assertEqual(response.status, 200)
+ subs.update(self._get_regexes())
+ return self._verify_response('coverage-report-post-resp',
+ subs, response)
+
+ def test_xml_report_coverage(self):
+ subs = {
+ 'filename': 'report',
+ 'path': '/.*/report',
+ }
+ response = self._do_post('os-coverage/action',
+ 'coverage-xml-report-post-req', subs)
+ self.assertEqual(response.status, 200)
+ subs.update(self._get_regexes())
+ return self._verify_response('coverage-xml-report-post-resp',
+ subs, response)
+
+
+class CoverageExtXmlTests(CoverageExtJsonTests):
+ ctype = "xml"
+
+
class ServersActionsJsonTest(ServersSampleBase):
def _test_server_action(self, uuid, action,
subs={}, resp_tpl=None, code=202):
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index 6dcf49803..c1016f1f4 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -4213,7 +4213,7 @@ class LibvirtDriverTestCase(test.TestCase):
block_device_info=None):
pass
- def fake_create_domain(xml):
+ def fake_create_domain(xml, inst_name=''):
return None
def fake_enable_hairpin(instance):
@@ -4259,7 +4259,7 @@ class LibvirtDriverTestCase(test.TestCase):
def fake_plug_vifs(instance, network_info):
pass
- def fake_create_domain(xml):
+ def fake_create_domain(xml, inst_name=''):
return None
def fake_enable_hairpin(instance):
diff --git a/nova/tests/test_virt.py b/nova/tests/test_virt.py
index 99d69f33f..452277c54 100644
--- a/nova/tests/test_virt.py
+++ b/nova/tests/test_virt.py
@@ -95,7 +95,7 @@ class TestVirtDisk(test.TestCase):
self.stubs.Set(utils, 'execute', fake_execute)
- def test_lxc_destroy_container(self):
+ def test_lxc_teardown_container(self):
def proc_mounts(self, mount_point):
mount_points = {
@@ -110,26 +110,26 @@ class TestVirtDisk(test.TestCase):
self.stubs.Set(disk_api._DiskImage, '_device_for_path', proc_mounts)
expected_commands = []
- disk_api.destroy_container('/mnt/loop/nopart')
+ disk_api.teardown_container('/mnt/loop/nopart')
expected_commands += [
('umount', '/dev/loop0'),
('losetup', '--detach', '/dev/loop0'),
]
- disk_api.destroy_container('/mnt/loop/part')
+ disk_api.teardown_container('/mnt/loop/part')
expected_commands += [
('umount', '/dev/mapper/loop0p1'),
('kpartx', '-d', '/dev/loop0'),
('losetup', '--detach', '/dev/loop0'),
]
- disk_api.destroy_container('/mnt/nbd/nopart')
+ disk_api.teardown_container('/mnt/nbd/nopart')
expected_commands += [
('umount', '/dev/nbd15'),
('qemu-nbd', '-d', '/dev/nbd15'),
]
- disk_api.destroy_container('/mnt/nbd/part')
+ disk_api.teardown_container('/mnt/nbd/part')
expected_commands += [
('umount', '/dev/mapper/nbd15p1'),
('kpartx', '-d', '/dev/nbd15'),
diff --git a/nova/tests/test_virt_disk.py b/nova/tests/test_virt_disk.py
index 1177aef6f..902d49704 100644
--- a/nova/tests/test_virt_disk.py
+++ b/nova/tests/test_virt_disk.py
@@ -84,6 +84,28 @@ class VirtDiskTest(test.TestCase):
vfs.teardown()
+ def test_inject_data_key_with_selinux_append_with_newline(self):
+
+ vfs = vfsguestfs.VFSGuestFS("/some/file", "qcow2")
+ vfs.setup()
+
+ vfs.replace_file("/etc/rc.d/rc.local", "#!/bin/sh\necho done")
+ vfs.make_path("etc/selinux")
+ vfs.make_path("etc/rc.d")
+ diskapi._inject_key_into_fs("mysshkey", vfs)
+
+ self.assertTrue("/etc/rc.d/rc.local" in vfs.handle.files)
+ self.assertEquals(vfs.handle.files["/etc/rc.d/rc.local"],
+ {'isdir': False,
+ 'content': "#!/bin/sh\necho done\n# Added "
+ "by Nova to ensure injected ssh keys have "
+ "the right context\nrestorecon -RF "
+ "root/.ssh 2>/dev/null || :\n",
+ 'gid': 100,
+ 'uid': 100,
+ 'mode': 0700})
+ vfs.teardown()
+
def test_inject_net(self):
vfs = vfsguestfs.VFSGuestFS("/some/file", "qcow2")
diff --git a/nova/virt/disk/api.py b/nova/virt/disk/api.py
index 9d9d672d7..758299f16 100644
--- a/nova/virt/disk/api.py
+++ b/nova/virt/disk/api.py
@@ -294,11 +294,11 @@ def setup_container(image, container_dir, use_cow=False):
raise exception.NovaException(img.errors)
-def destroy_container(container_dir):
- """Destroy the container once it terminates.
+def teardown_container(container_dir):
+ """Teardown the container rootfs mounting once it is spawned.
It will umount the container that is mounted,
- and delete any linked devices.
+ and delete any linked devices.
"""
try:
img = _DiskImage(image=None, mount_dir=container_dir)
@@ -357,11 +357,14 @@ def _setup_selinux_for_keys(fs, sshdir):
# and so to append there you'd need something like:
# utils.execute('sed', '-i', '${/^exit 0$/d}' rclocal, run_as_root=True)
restorecon = [
- '#!/bin/sh\n',
+ '\n',
'# Added by Nova to ensure injected ssh keys have the right context\n',
'restorecon -RF %s 2>/dev/null || :\n' % sshdir,
]
+ if not fs.has_file(rclocal):
+ restorecon.insert(0, '#!/bin/sh')
+
_inject_file_into_fs(fs, rclocal, ''.join(restorecon), append=True)
fs.set_permissions(rclocal, 0700)
diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py
index 3c78f58eb..cfed962d0 100644
--- a/nova/virt/libvirt/driver.py
+++ b/nova/virt/libvirt/driver.py
@@ -577,11 +577,6 @@ class LibvirtDriver(driver.ComputeDriver):
target = os.path.join(CONF.instances_path, instance['name'])
LOG.info(_('Deleting instance files %(target)s') % locals(),
instance=instance)
- if CONF.libvirt_type == 'lxc':
- container_dir = os.path.join(CONF.instances_path,
- instance['name'],
- 'rootfs')
- disk.destroy_container(container_dir=container_dir)
if os.path.exists(target):
# If we fail to get rid of the directory
# tree, this shouldn't block deletion of
@@ -877,7 +872,7 @@ class LibvirtDriver(driver.ComputeDriver):
power_state.CRASHED]:
LOG.info(_("Instance shutdown successfully."),
instance=instance)
- self._create_domain(domain=dom)
+ self._create_domain(domain=dom, inst_name=instance['name'])
timer = utils.LoopingCall(self._wait_for_running, instance)
timer.start(interval=0.5).wait()
return True
@@ -939,7 +934,7 @@ class LibvirtDriver(driver.ComputeDriver):
def power_on(self, instance):
"""Power on the specified instance"""
dom = self._lookup_by_name(instance['name'])
- self._create_domain(domain=dom)
+ self._create_domain(domain=dom, inst_name=instance['name'])
timer = utils.LoopingCall(self._wait_for_running, instance)
timer.start(interval=0.5).wait()
@@ -1245,12 +1240,6 @@ class LibvirtDriver(driver.ComputeDriver):
LOG.info(_('Creating image'), instance=instance)
libvirt_utils.write_to_file(basepath('libvirt.xml'), libvirt_xml)
- if CONF.libvirt_type == 'lxc':
- container_dir = os.path.join(CONF.instances_path,
- instance['name'],
- 'rootfs')
- fileutils.ensure_tree(container_dir)
-
# NOTE(dprince): for rescue console.log may already exist... chown it.
self._chown_console_log_for_instance(instance['name'])
@@ -1412,11 +1401,6 @@ class LibvirtDriver(driver.ComputeDriver):
'%(img_id)s (%(e)s)') % locals(),
instance=instance)
- if CONF.libvirt_type == 'lxc':
- disk.setup_container(image('disk').path,
- container_dir=container_dir,
- use_cow=CONF.use_cow_images)
-
if CONF.libvirt_type == 'uml':
libvirt_utils.chown(image('disk').path, 'root')
@@ -1875,16 +1859,37 @@ class LibvirtDriver(driver.ComputeDriver):
'num_cpu': num_cpu,
'cpu_time': cpu_time}
- def _create_domain(self, xml=None, domain=None, launch_flags=0):
+ def _create_domain(self, xml=None, domain=None,
+ inst_name='', launch_flags=0):
"""Create a domain.
Either domain or xml must be passed in. If both are passed, then
the domain definition is overwritten from the xml.
"""
+ if CONF.libvirt_type == 'lxc':
+ container_dir = os.path.join(CONF.instances_path,
+ inst_name,
+ 'rootfs')
+ fileutils.ensure_tree(container_dir)
+ image = self.image_backend.image(inst_name, 'disk')
+ disk.setup_container(image.path,
+ container_dir=container_dir,
+ use_cow=CONF.use_cow_images)
+
if xml:
domain = self._conn.defineXML(xml)
domain.createWithFlags(launch_flags)
self._enable_hairpin(domain.XMLDesc(0))
+
+ # NOTE(uni): Now the container is running with its own private mount
+ # namespace and so there is no need to keep the container rootfs
+ # mounted in the host namespace
+ if CONF.libvirt_type == 'lxc':
+ container_dir = os.path.join(CONF.instances_path,
+ inst_name,
+ 'rootfs')
+ disk.teardown_container(container_dir=container_dir)
+
return domain
def _create_domain_and_network(self, xml, instance, network_info,
@@ -1904,7 +1909,8 @@ class LibvirtDriver(driver.ComputeDriver):
self.plug_vifs(instance, network_info)
self.firewall_driver.setup_basic_filtering(instance, network_info)
self.firewall_driver.prepare_instance_filter(instance, network_info)
- domain = self._create_domain(xml)
+ domain = self._create_domain(xml, inst_name=instance['name'])
+
self.firewall_driver.apply_instance_filter(instance, network_info)
return domain