diff options
78 files changed, 763 insertions, 427 deletions
diff --git a/bin/nova-all b/bin/nova-all index d96b71604..af947d36d 100755 --- a/bin/nova-all +++ b/bin/nova-all @@ -30,6 +30,7 @@ continue attempting to launch the rest of the services. import eventlet eventlet.monkey_patch(os=False) +import gettext import os import sys @@ -40,6 +41,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.objectstore import s3server diff --git a/bin/nova-api b/bin/nova-api index d21d955cf..171a23ea0 100755 --- a/bin/nova-api +++ b/bin/nova-api @@ -26,6 +26,7 @@ Starts both the EC2 and OpenStack APIs in separate greenthreads. import eventlet eventlet.monkey_patch(os=False) +import gettext import os import sys @@ -36,6 +37,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-api-ec2 b/bin/nova-api-ec2 index d1b3d45ea..a3e1be018 100755 --- a/bin/nova-api-ec2 +++ b/bin/nova-api-ec2 @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch(os=False) +import gettext import os import sys @@ -31,6 +32,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-api-metadata b/bin/nova-api-metadata index e7cac260d..2005d6714 100755 --- a/bin/nova-api-metadata +++ b/bin/nova-api-metadata @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch(os=False) +import gettext import os import sys @@ -31,6 +32,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-api-os-compute b/bin/nova-api-os-compute index 02f16a04a..c2aa9e57c 100755 --- a/bin/nova-api-os-compute +++ b/bin/nova-api-os-compute @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch(os=False) +import gettext import os import sys @@ -31,6 +32,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath( if os.path.exists(os.path.join(possible_topdir, "nova", "__init__.py")): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-baremetal-deploy-helper b/bin/nova-baremetal-deploy-helper index 756305776..a9d5ecfc7 100755 --- a/bin/nova-baremetal-deploy-helper +++ b/bin/nova-baremetal-deploy-helper @@ -23,6 +23,7 @@ import eventlet if __name__ == '__main__': eventlet.monkey_patch() +import gettext import os import sys import threading @@ -36,6 +37,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) + import cgi import Queue import re @@ -45,6 +48,7 @@ from wsgiref import simple_server from nova import config from nova import context as nova_context +from nova import exception from nova.openstack.common import log as logging from nova import utils from nova.virt.baremetal import baremetal_states @@ -95,18 +99,27 @@ def logout_iscsi(portal_address, portal_port, target_iqn): def make_partitions(dev, root_mb, swap_mb): """Create partitions for root and swap on a disk device.""" - commands = ['o,w', - 'n,p,1,,+%dM,t,1,83,w' % root_mb, - 'n,p,2,,+%dM,t,2,82,w' % swap_mb, - ] - for command in commands: - command = command.replace(',', '\n') - utils.execute('fdisk', dev, - process_input=command, - run_as_root=True, - check_exit_code=[0]) - # avoid "device is busy" - time.sleep(3) + stdin_command = ('0 0;\n0 0;\n0 0;\n0 0;\n') + utils.execute('sfdisk', '-D', '-uM', dev, process_input=stdin_command, + run_as_root=True, + check_exit_code=[0]) + # create new partitions + commandp1 = '- %d 83;\n;\n;\n;' % root_mb + p1outraw, err = utils.execute('sfdisk', '-D', '-uM', '-N1', dev, + process_input=commandp1, + run_as_root=True, + check_exit_code=[0]) + # get end location of 1st partition + p1re = re.compile('^%s-part1.*$' % dev, re.U + re.M) + p1balist = p1re.findall(p1outraw) + p1endraw = p1balist[1] + p1end = int(p1endraw.split()[2]) + commandp2 = ('%d %d 82\n;\n;' % (p1end + 1, swap_mb)) + utils.execute('sfdisk', '-D', '-uM', '-N2', dev, process_input=commandp2, + run_as_root=True, + check_exit_code=[0]) + # avoid "device is busy" + time.sleep(3) def is_block_device(dev): @@ -215,6 +228,11 @@ def deploy(address, port, iqn, lun, image_path, pxe_config_path, login_iscsi(address, port, iqn) try: root_uuid = work_on_disk(dev, root_mb, swap_mb, image_path) + except exception.ProcessExecutionError, err: + # Log output if there was a error + LOG.error("Cmd : %s" % err.cmd) + LOG.error("StdOut : %s" % err.stdout) + LOG.error("StdErr : %s" % err.stderr) finally: logout_iscsi(address, port, iqn) switch_pxe_config(pxe_config_path, root_uuid) diff --git a/bin/nova-cells b/bin/nova-cells index bb955e9ec..380e71266 100755 --- a/bin/nova-cells +++ b/bin/nova-cells @@ -21,6 +21,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -34,6 +35,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) + from nova import config from nova.openstack.common import log as logging from nova import service diff --git a/bin/nova-cert b/bin/nova-cert index c6d9ddbad..861f3ba8f 100755 --- a/bin/nova-cert +++ b/bin/nova-cert @@ -20,6 +20,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -33,6 +34,7 @@ POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-compute b/bin/nova-compute index 26d81d8cc..a7ca4de5b 100755 --- a/bin/nova-compute +++ b/bin/nova-compute @@ -29,6 +29,7 @@ if os.name == 'nt': else: eventlet.monkey_patch() +import gettext import os import sys import traceback @@ -43,6 +44,7 @@ POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')): sys.path.insert(0, POSSIBLE_TOPDIR) +gettext.install('nova', unicode=1) from nova import config import nova.db.api diff --git a/bin/nova-conductor b/bin/nova-conductor index 30d426f42..72e89804f 100755 --- a/bin/nova-conductor +++ b/bin/nova-conductor @@ -20,6 +20,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -33,6 +34,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-console b/bin/nova-console index 6d6569104..af037bb3c 100755 --- a/bin/nova-console +++ b/bin/nova-console @@ -21,6 +21,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -34,6 +35,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-consoleauth b/bin/nova-consoleauth index 0cbec669a..f867c8c7b 100755 --- a/bin/nova-consoleauth +++ b/bin/nova-consoleauth @@ -21,6 +21,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -32,6 +33,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.consoleauth import manager diff --git a/bin/nova-manage b/bin/nova-manage index f80660010..3bcccfcce 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -227,26 +227,44 @@ class ProjectCommands(object): @args('--key', metavar='<key>', help='Key') @args('--value', metavar='<value>', help='Value') def quota(self, project_id, key=None, value=None): - """Set or display quotas for project.""" + """ + Create, update or display quotas for project + + If no quota key is provided, the quota will be displayed. + If a valid quota key is provided and it does not exist, + it will be created. Otherwise, it will be updated. + """ + ctxt = context.get_admin_context() project_quota = QUOTAS.get_project_quotas(ctxt, project_id) - if key and key in project_quota: - if value.lower() == 'unlimited': - value = -1 - try: - db.quota_update(ctxt, project_id, key, value) - except exception.ProjectQuotaNotFound: - db.quota_create(ctxt, project_id, key, value) - else: - print _('%(key)s is not a valid quota key. Valid options are: ' - '%(options)s.') % {'key': key, - 'options': ', '.join(project_quota)} - sys.exit(2) + # if key is None, that means we need to show the quotas instead + # of updating them + if key: + if key in project_quota: + if value.lower() == 'unlimited': + value = -1 + try: + db.quota_update(ctxt, project_id, key, value) + except exception.ProjectQuotaNotFound: + db.quota_create(ctxt, project_id, key, value) + else: + print _('%(key)s is not a valid quota key. Valid options are: ' + '%(options)s.') % {'key': key, + 'options': ', '.join(project_quota)} + sys.exit(2) + print_format = "%-36s %-10s %-10s %-10s" + print print_format % ( + _('Quota'), + _('Limit'), + _('In Use'), + _('Reserved')) + # Retrieve the quota after update project_quota = QUOTAS.get_project_quotas(ctxt, project_id) for key, value in project_quota.iteritems(): if value['limit'] < 0 or value['limit'] is None: value['limit'] = 'unlimited' - print '%s: %s' % (key, value['limit']) + print print_format % (key, value['limit'], value['in_use'], + value['reserved']) @args('--project', dest='project_id', metavar='<Project name>', help='Project name') diff --git a/bin/nova-network b/bin/nova-network index d0ee61ed9..b79785214 100755 --- a/bin/nova-network +++ b/bin/nova-network @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -35,6 +36,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/bin/nova-novncproxy b/bin/nova-novncproxy index 29981f53f..c40fdbfd5 100755 --- a/bin/nova-novncproxy +++ b/bin/nova-novncproxy @@ -21,11 +21,14 @@ Websocket proxy that is compatible with OpenStack Nova noVNC consoles. Leverages websockify.py by Joel Martin """ +import gettext import os import sys from oslo.config import cfg +gettext.install('nova', unicode=1) + from nova import config from nova.console import websocketproxy diff --git a/bin/nova-objectstore b/bin/nova-objectstore index 8ec9fbf35..f60868946 100755 --- a/bin/nova-objectstore +++ b/bin/nova-objectstore @@ -22,6 +22,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -33,6 +34,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.objectstore import s3server diff --git a/bin/nova-spicehtml5proxy b/bin/nova-spicehtml5proxy index 012a202ec..1d8fe81dc 100755 --- a/bin/nova-spicehtml5proxy +++ b/bin/nova-spicehtml5proxy @@ -21,11 +21,14 @@ Websocket proxy that is compatible with OpenStack Nova SPICE HTML5 consoles. Leverages websockify.py by Joel Martin """ +import gettext import os import sys from oslo.config import cfg +gettext.install('nova', unicode=1) + from nova import config from nova.console import websocketproxy diff --git a/bin/nova-xvpvncproxy b/bin/nova-xvpvncproxy index 6ad61d0ba..905c3de4f 100755 --- a/bin/nova-xvpvncproxy +++ b/bin/nova-xvpvncproxy @@ -21,6 +21,7 @@ import eventlet eventlet.monkey_patch() +import gettext import os import sys @@ -30,6 +31,7 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), if os.path.exists(os.path.join(possible_topdir, 'nova', '__init__.py')): sys.path.insert(0, possible_topdir) +gettext.install('nova', unicode=1) from nova import config from nova.openstack.common import log as logging diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json index e5748a4cd..6e477722d 100644 --- a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json +++ b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json @@ -1,7 +1,7 @@ { "quota_class_set": { "cores": 20, - "fixed_ips": 10, + "fixed_ips": -1, "floating_ips": 10, "id": "test_class", "injected_file_content_bytes": 10240, @@ -14,4 +14,4 @@ "security_group_rules": 20, "security_groups": 10 } -}
\ No newline at end of file +} diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml index 8e7444634..91929d34a 100644 --- a/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml +++ b/doc/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <quota_class_set id="test_class"> <cores>20</cores> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <floating_ips>10</floating_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>10</security_groups> -</quota_class_set>
\ No newline at end of file +</quota_class_set> diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json index 6325bb562..c86f86063 100644 --- a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json @@ -1,7 +1,7 @@ { "quota_class_set": { "cores": 50, - "fixed_ips": 10, + "fixed_ips": -1, "floating_ips": 10, "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, @@ -13,4 +13,4 @@ "security_group_rules": 20, "security_groups": 10 } -}
\ No newline at end of file +} diff --git a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml index 26a29fc23..23eb5088c 100644 --- a/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml +++ b/doc/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <quota_class_set> <cores>50</cores> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <floating_ips>10</floating_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>10</security_groups> -</quota_class_set>
\ No newline at end of file +</quota_class_set> diff --git a/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json b/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json index efc35cf00..239c64d23 100644 --- a/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json +++ b/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json @@ -1,7 +1,7 @@ { "quota_set": { "cores": 20, - "fixed_ips": 10, + "fixed_ips": -1, "floating_ips": 10, "id": "fake_tenant", "injected_file_content_bytes": 10240, @@ -14,4 +14,4 @@ "security_group_rules": 20, "security_groups": 10 } -}
\ No newline at end of file +} diff --git a/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml b/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml index dd4c6d66d..76a9292c1 100644 --- a/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml +++ b/doc/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <quota_set id="fake_tenant"> <cores>20</cores> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <floating_ips>10</floating_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>10</security_groups> -</quota_set>
\ No newline at end of file +</quota_set> diff --git a/doc/api_samples/os-quota-sets/quotas-show-get-resp.json b/doc/api_samples/os-quota-sets/quotas-show-get-resp.json index efc35cf00..239c64d23 100644 --- a/doc/api_samples/os-quota-sets/quotas-show-get-resp.json +++ b/doc/api_samples/os-quota-sets/quotas-show-get-resp.json @@ -1,7 +1,7 @@ { "quota_set": { "cores": 20, - "fixed_ips": 10, + "fixed_ips": -1, "floating_ips": 10, "id": "fake_tenant", "injected_file_content_bytes": 10240, @@ -14,4 +14,4 @@ "security_group_rules": 20, "security_groups": 10 } -}
\ No newline at end of file +} diff --git a/doc/api_samples/os-quota-sets/quotas-show-get-resp.xml b/doc/api_samples/os-quota-sets/quotas-show-get-resp.xml index dd4c6d66d..76a9292c1 100644 --- a/doc/api_samples/os-quota-sets/quotas-show-get-resp.xml +++ b/doc/api_samples/os-quota-sets/quotas-show-get-resp.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <quota_set id="fake_tenant"> <cores>20</cores> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <floating_ips>10</floating_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>10</security_groups> -</quota_set>
\ No newline at end of file +</quota_set> diff --git a/doc/api_samples/os-quota-sets/quotas-update-post-resp.json b/doc/api_samples/os-quota-sets/quotas-update-post-resp.json index 14324e365..2be76d472 100644 --- a/doc/api_samples/os-quota-sets/quotas-update-post-resp.json +++ b/doc/api_samples/os-quota-sets/quotas-update-post-resp.json @@ -1,7 +1,7 @@ { "quota_set": { "cores": 20, - "fixed_ips": 10, + "fixed_ips": -1, "floating_ips": 10, "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, @@ -13,4 +13,4 @@ "security_group_rules": 20, "security_groups": 45 } -}
\ No newline at end of file +} diff --git a/doc/api_samples/os-quota-sets/quotas-update-post-resp.xml b/doc/api_samples/os-quota-sets/quotas-update-post-resp.xml index 5e6bb893e..e03a0bf5e 100644 --- a/doc/api_samples/os-quota-sets/quotas-update-post-resp.xml +++ b/doc/api_samples/os-quota-sets/quotas-update-post-resp.xml @@ -1,7 +1,7 @@ <?xml version='1.0' encoding='UTF-8'?> <quota_set> <cores>20</cores> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <floating_ips>10</floating_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>45</security_groups> -</quota_set>
\ No newline at end of file +</quota_set> diff --git a/doc/source/devref/il8n.rst b/doc/source/devref/il8n.rst index 2264630be..ce708449d 100644 --- a/doc/source/devref/il8n.rst +++ b/doc/source/devref/il8n.rst @@ -27,8 +27,7 @@ The ``_()`` function is brought into the global scope by doing:: import gettext gettext.install("nova", unicode=1) -In general, you shouldn't need to add these to any nova files, since the lines -are present in ``nova/__init__.py``. However, if this code is missing, it may -result in an error that looks like like:: +These lines are needed in any toplevel script before any nova modules are +imported. If this code is missing, it may result in an error that looks like:: NameError: name '_' is not defined diff --git a/etc/nova/rootwrap.d/baremetal-deploy-helper.filters b/etc/nova/rootwrap.d/baremetal-deploy-helper.filters index 65416bbf8..b4d11e24f 100644 --- a/etc/nova/rootwrap.d/baremetal-deploy-helper.filters +++ b/etc/nova/rootwrap.d/baremetal-deploy-helper.filters @@ -4,7 +4,7 @@ [Filters] # nova-baremetal-deploy-helper iscsiadm: CommandFilter, /sbin/iscsiadm, root -fdisk: CommandFilter, /sbin/fdisk, root +sfdisk: CommandFilter, /sbin/sfdisk, root dd: CommandFilter, /bin/dd, root mkswap: CommandFilter, /sbin/mkswap, root blkid: CommandFilter, /sbin/blkid, root diff --git a/nova/__init__.py b/nova/__init__.py index a9eca4848..e21bdd7b4 100644 --- a/nova/__init__.py +++ b/nova/__init__.py @@ -24,8 +24,3 @@ :platform: Unix :synopsis: Infrastructure-as-a-Service Cloud platform. """ - -import gettext - - -gettext.install('nova', unicode=1) diff --git a/nova/api/metadata/base.py b/nova/api/metadata/base.py index 90dcb9ca5..1f5e5b5b9 100644 --- a/nova/api/metadata/base.py +++ b/nova/api/metadata/base.py @@ -99,13 +99,12 @@ class InstanceMetadata(): self.extra_md = extra_md if conductor_api: - self.conductor_api = conductor_api + capi = conductor_api else: - self.conductor_api = conductor.API() + capi = conductor.API() ctxt = context.get_admin_context() - capi = self.conductor_api self.availability_zone = ec2utils.get_availability_zone_by_host( instance['host'], capi) diff --git a/nova/api/openstack/compute/contrib/extended_availability_zone.py b/nova/api/openstack/compute/contrib/extended_availability_zone.py index af557219f..a1ee85bcf 100644 --- a/nova/api/openstack/compute/contrib/extended_availability_zone.py +++ b/nova/api/openstack/compute/contrib/extended_availability_zone.py @@ -37,7 +37,7 @@ class ExtendedAZController(wsgi.Controller): self.mc = memorycache.get_client() def _get_host_az(self, context, instance): - host = instance.get('host') + host = str(instance.get('host')) if not host: return None cache_key = "azcache-%s" % host diff --git a/nova/api/openstack/compute/contrib/security_group_default_rules.py b/nova/api/openstack/compute/contrib/security_group_default_rules.py index e2bba8127..751a4d459 100644 --- a/nova/api/openstack/compute/contrib/security_group_default_rules.py +++ b/nova/api/openstack/compute/contrib/security_group_default_rules.py @@ -112,7 +112,7 @@ class SecurityGroupDefaultRulesController(sg.SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupDefaultRuleTemplate) @wsgi.deserializers(xml=SecurityGroupDefaultRulesXMLDeserializer) def create(self, req, body): - context = self._authorize_context(req) + context = sg._authorize_context(req) authorize(context) sg_rule = self._from_body(body, 'security_group_default_rule') @@ -146,7 +146,7 @@ class SecurityGroupDefaultRulesController(sg.SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupDefaultRuleTemplate) def show(self, req, id): - context = self._authorize_context(req) + context = sg._authorize_context(req) authorize(context) id = self.security_group_api.validate_id(id) @@ -161,7 +161,7 @@ class SecurityGroupDefaultRulesController(sg.SecurityGroupControllerBase): return {"security_group_default_rule": fmt_rule} def delete(self, req, id): - context = self._authorize_context(req) + context = sg._authorize_context(req) authorize(context) id = self.security_group_api.validate_id(id) @@ -175,7 +175,7 @@ class SecurityGroupDefaultRulesController(sg.SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupDefaultRulesTemplate) def index(self, req): - context = self._authorize_context(req) + context = sg._authorize_context(req) authorize(context) ret = {'security_group_default_rules': []} diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py index 354fab647..700d9b71e 100644 --- a/nova/api/openstack/compute/contrib/security_groups.py +++ b/nova/api/openstack/compute/contrib/security_groups.py @@ -77,6 +77,11 @@ def make_sg(elem): make_rule(rule) +def _authorize_context(req): + context = req.environ['nova.context'] + authorize(context) + return context + sg_nsmap = {None: wsgi.XMLNS_V11} @@ -213,11 +218,6 @@ class SecurityGroupControllerBase(object): context, rule)] return security_group - def _authorize_context(self, req): - context = req.environ['nova.context'] - authorize(context) - return context - def _from_body(self, body, key): if not body: raise exc.HTTPUnprocessableEntity() @@ -233,7 +233,7 @@ class SecurityGroupController(SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupTemplate) def show(self, req, id): """Return data about the given security group.""" - context = self._authorize_context(req) + context = _authorize_context(req) id = self.security_group_api.validate_id(id) @@ -245,7 +245,7 @@ class SecurityGroupController(SecurityGroupControllerBase): def delete(self, req, id): """Delete a security group.""" - context = self._authorize_context(req) + context = _authorize_context(req) id = self.security_group_api.validate_id(id) @@ -259,7 +259,7 @@ class SecurityGroupController(SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupsTemplate) def index(self, req): """Returns a list of security groups.""" - context = self._authorize_context(req) + context = _authorize_context(req) search_opts = {} search_opts.update(req.GET) @@ -280,7 +280,7 @@ class SecurityGroupController(SecurityGroupControllerBase): @wsgi.deserializers(xml=SecurityGroupXMLDeserializer) def create(self, req, body): """Creates a new security group.""" - context = self._authorize_context(req) + context = _authorize_context(req) security_group = self._from_body(body, 'security_group') @@ -303,7 +303,7 @@ class SecurityGroupRulesController(SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupRuleTemplate) @wsgi.deserializers(xml=SecurityGroupRulesXMLDeserializer) def create(self, req, body): - context = self._authorize_context(req) + context = _authorize_context(req) sg_rule = self._from_body(body, 'security_group_rule') @@ -358,7 +358,7 @@ class SecurityGroupRulesController(SecurityGroupControllerBase): cidr, ip_protocol, from_port, to_port) def delete(self, req, id): - context = self._authorize_context(req) + context = _authorize_context(req) id = self.security_group_api.validate_id(id) @@ -380,7 +380,7 @@ class ServerSecurityGroupController(SecurityGroupControllerBase): @wsgi.serializers(xml=SecurityGroupsTemplate) def index(self, req, server_id): """Returns a list of security groups for the given instance.""" - context = self._authorize_context(req) + context = _authorize_context(req) self.security_group_api.ensure_default(context) @@ -390,7 +390,7 @@ class ServerSecurityGroupController(SecurityGroupControllerBase): raise exc.HTTPNotFound(explanation=exp.format_message()) groups = self.security_group_api.get_instance_security_groups( - req, instance['id'], instance['uuid'], True) + context, instance['id'], instance['uuid'], True) result = [self._format_security_group(context, group) for group in groups] @@ -466,7 +466,10 @@ class SecurityGroupsOutputController(wsgi.Controller): openstack_driver.get_openstack_security_group_driver()) def _extend_servers(self, req, servers): + # TODO(arosen) this function should be refactored to reduce duplicate + # code and use get_instance_security_groups instead of get_db_instance. key = "security_groups" + context = _authorize_context(req) if not openstack_driver.is_quantum_security_groups(): for server in servers: instance = req.get_db_instance(server['id']) @@ -478,35 +481,38 @@ class SecurityGroupsOutputController(wsgi.Controller): # instance from the request. The reason for this is if using # quantum security groups the requested security groups for the # instance are not in the db and have not been sent to quantum yet. - instance_sgs = [] if req.method != 'POST': + sg_instance_bindings = ( + self.security_group_api + .get_instances_security_groups_bindings(context)) for server in servers: - instance_sgs = ( - self.security_group_api.get_instance_security_groups( - req, server['id'])) + groups = sg_instance_bindings.get(server['id']) + if groups: + server[key] = groups + # In this section of code len(servers) == 1 as you can only POST + # one server in an API request. else: try: # try converting to json req_obj = json.loads(req.body) # Add security group to server, if no security group was in # request add default since that is the group it is part of - instance_sgs = req_obj['server'].get( + servers[0][key] = req_obj['server'].get( key, [{'name': 'default'}]) except ValueError: root = minidom.parseString(req.body) sg_root = root.getElementsByTagName(key) + groups = [] if sg_root: security_groups = sg_root[0].getElementsByTagName( 'security_group') for security_group in security_groups: - instance_sgs.append( + groups.append( {'name': security_group.getAttribute('name')}) - if not instance_sgs: - instance_sgs = [{'name': 'default'}] + if not groups: + groups = [{'name': 'default'}] - if instance_sgs: - for server in servers: - server[key] = instance_sgs + servers[0][key] = groups def _show(self, req, resp_obj): if not softauth(req.environ['nova.context']): diff --git a/nova/api/openstack/compute/contrib/simple_tenant_usage.py b/nova/api/openstack/compute/contrib/simple_tenant_usage.py index 0428c8a77..b653564c0 100644 --- a/nova/api/openstack/compute/contrib/simple_tenant_usage.py +++ b/nova/api/openstack/compute/contrib/simple_tenant_usage.py @@ -106,7 +106,7 @@ class SimpleTenantUsageController(object): def _get_flavor(self, context, compute_api, instance, flavors_cache): """Get flavor information from the instance's system_metadata, - allowing a fallback to lookup by-id for deleted instances only""" + allowing a fallback to lookup by-id for deleted instances only.""" try: return instance_types.extract_instance_type(instance) except KeyError: diff --git a/nova/compute/api.py b/nova/compute/api.py index 0d915bfc9..8b75613d2 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -40,7 +40,6 @@ from nova.compute import task_states from nova.compute import utils as compute_utils from nova.compute import vm_states from nova.consoleauth import rpcapi as consoleauth_rpcapi -from nova import context from nova import crypto from nova.db import base from nova import exception @@ -69,6 +68,10 @@ compute_opts = [ default=False, help='Allow destination machine to match source for resize. ' 'Useful when testing in single-host environments.'), + cfg.BoolOpt('allow_migrate_to_same_host', + default=False, + help='Allow migrate machine to the same host. ' + 'Useful when testing in single-host environments.'), cfg.StrOpt('default_schedule_zone', default=None, help='availability zone to use when user doesn\'t specify one'), @@ -2036,6 +2039,10 @@ class API(base.Base): if not CONF.allow_resize_to_same_host: filter_properties['ignore_hosts'].append(instance['host']) + # Here when flavor_id is None, the process is considered as migrate. + if (not flavor_id and not CONF.allow_migrate_to_same_host): + filter_properties['ignore_hosts'].append(instance['host']) + # With cells, the best we can do right now is commit the reservations # immediately... if CONF.cells.enable and reservations: @@ -3164,12 +3171,11 @@ class SecurityGroupAPI(base.Base, security_group_base.SecurityGroupBase): self.security_group_rpcapi.refresh_instance_security_rules( context, instance['host'], instance) - def get_instance_security_groups(self, req, instance_id, + def get_instance_security_groups(self, context, instance_id, instance_uuid=None, detailed=False): if detailed: - return self.db.security_group_get_by_instance( - context.get_admin_context(), instance_id) - instance = req.get_db_instance(instance_id) + return self.db.security_group_get_by_instance(context, instance_id) + instance = self.db.instance_get(context, instance_id) groups = instance.get('security_groups') if groups: return [{'name': group['name']} for group in groups] diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 6cb0bbb94..30e33d8e0 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -744,6 +744,21 @@ class ComputeManager(manager.SchedulerDependentManager): return block_device_info + def _decode_files(self, injected_files): + """Base64 decode the list of files to inject.""" + if not injected_files: + return [] + + def _decode(f): + path, contents = f + try: + decoded = base64.b64decode(contents) + return path, decoded + except TypeError: + raise exception.Base64Exception(path=path) + + return [_decode(f) for f in injected_files] + def _run_instance(self, context, request_spec, filter_properties, requested_networks, injected_files, admin_password, is_first_time, node, instance): @@ -788,6 +803,10 @@ class ComputeManager(manager.SchedulerDependentManager): bdms = self.conductor_api.block_device_mapping_get_all_by_instance( context, instance) + # b64 decode the files to inject: + injected_files_orig = injected_files + injected_files = self._decode_files(injected_files) + rt = self._get_resource_tracker(node) try: limits = filter_properties.get('limits', {}) @@ -833,8 +852,9 @@ class ComputeManager(manager.SchedulerDependentManager): exc_info = sys.exc_info() # try to re-schedule instance: self._reschedule_or_reraise(context, instance, exc_info, - requested_networks, admin_password, injected_files, - is_first_time, request_spec, filter_properties, bdms) + requested_networks, admin_password, + injected_files_orig, is_first_time, request_spec, + filter_properties, bdms) else: # Spawn success: self._notify_about_instance_usage(context, instance, @@ -1067,6 +1087,7 @@ class ComputeManager(manager.SchedulerDependentManager): injected_files, admin_password, self._legacy_nw_info(network_info), block_device_info) + except Exception: with excutils.save_and_reraise_exception(): LOG.exception(_('Instance failed to spawn'), instance=instance) @@ -1180,11 +1201,6 @@ class ComputeManager(manager.SchedulerDependentManager): if filter_properties is None: filter_properties = {} - if injected_files is None: - injected_files = [] - else: - injected_files = [(path, base64.b64decode(contents)) - for path, contents in injected_files] @lockutils.synchronized(instance['uuid'], 'nova-') def do_run_instance(): @@ -3434,8 +3450,8 @@ class ComputeManager(manager.SchedulerDependentManager): instance=instance) continue try: - self.compute_api.confirm_resize(context, instance, - migration_ref=migration) + self.conductor_api.compute_confirm_resize( + context, instance, migration_ref=migration) except Exception, e: msg = _("Error auto-confirming resize: %(e)s. " "Will retry later.") diff --git a/nova/conductor/api.py b/nova/conductor/api.py index 1825a9e7e..cebe6bf1f 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -337,6 +337,10 @@ class LocalAPI(object): def compute_stop(self, context, instance, do_cast=True): return self._manager.compute_stop(context, instance, do_cast) + def compute_confirm_resize(self, context, instance, migration_ref): + return self._manager.compute_confirm_resize(context, instance, + migration_ref) + class API(object): """Conductor API that does updates via RPC to the ConductorManager.""" @@ -671,3 +675,8 @@ class API(object): def compute_stop(self, context, instance, do_cast=True): return self.conductor_rpcapi.compute_stop(context, instance, do_cast) + + def compute_confirm_resize(self, context, instance, migration_ref): + return self.conductor_rpcapi.compute_confirm_resize(context, + instance, + migration_ref) diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 71b08bad4..b4e35066c 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -49,7 +49,7 @@ datetime_fields = ['launched_at', 'terminated_at', 'updated_at'] class ConductorManager(manager.Manager): """Mission: TBD.""" - RPC_API_VERSION = '1.45' + RPC_API_VERSION = '1.46' def __init__(self, *args, **kwargs): super(ConductorManager, self).__init__(*args, **kwargs) @@ -422,3 +422,6 @@ class ConductorManager(manager.Manager): def compute_stop(self, context, instance, do_cast=True): self.compute_api.stop(context, instance, do_cast) + + def compute_confirm_resize(self, context, instance, migration_ref): + self.compute_api.confirm_resize(context, instance, migration_ref) diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py index 22b1b039f..d8daecf9c 100644 --- a/nova/conductor/rpcapi.py +++ b/nova/conductor/rpcapi.py @@ -83,6 +83,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): 1.43 - Added compute_stop 1.44 - Added compute_node_delete 1.45 - Added project_id to quota_commit and quota_rollback + 1.46 - Added compute_confirm_resize """ BASE_RPC_API_VERSION = '1.0' @@ -437,3 +438,10 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): msg = self.make_msg('compute_stop', instance=instance_p, do_cast=do_cast) return self.call(context, msg, version='1.43') + + def compute_confirm_resize(self, context, instance, migration_ref): + instance_p = jsonutils.to_primitive(instance) + migration_p = jsonutils.to_primitive(migration_ref) + msg = self.make_msg('compute_confirm_resize', instance=instance_p, + migration_ref=migration_p) + return self.call(context, msg, version='1.46') diff --git a/nova/exception.py b/nova/exception.py index 1f32b0671..b3b3d1f1f 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -1083,6 +1083,11 @@ class DuplicateVlan(Duplicate): message = _("Detected existing vlan with id %(vlan)d") +class CidrConflict(NovaException): + message = _("There was a conflict when trying to complete your request.") + code = 409 + + class InstanceNotFound(NotFound): message = _("Instance %(instance_id)s could not be found.") @@ -1200,3 +1205,7 @@ class UnsupportedVirtType(Invalid): class UnsupportedHardware(Invalid): message = _("Requested hardware '%(model)s' is not supported by " "the '%(virt)s' virt driver") + + +class Base64Exception(NovaException): + message = _("Invalid Base 64 data for file %(path)s") diff --git a/nova/locale/nova.pot b/nova/locale/nova.pot index c2e0ef6c5..8593e89a3 100644 --- a/nova/locale/nova.pot +++ b/nova/locale/nova.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: nova jenkins.nova.propose.translation.update.200\n" +"Project-Id-Version: nova jenkins.nova.propose.translation.update.201\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-03-28 00:03+0000\n" +"POT-Creation-Date: 2013-03-29 00:03+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" @@ -1292,27 +1292,27 @@ msgstr "" msgid "Running %(name)s post-hook: %(obj)s" msgstr "" -#: nova/manager.py:171 +#: nova/manager.py:172 #, python-format msgid "Skipping periodic task %(task)s because its interval is negative" msgstr "" -#: nova/manager.py:176 +#: nova/manager.py:177 #, python-format msgid "Skipping periodic task %(task)s because it is disabled" msgstr "" -#: nova/manager.py:237 +#: nova/manager.py:238 #, python-format msgid "Running periodic task %(full_task_name)s" msgstr "" -#: nova/manager.py:245 +#: nova/manager.py:246 #, python-format msgid "Error during %(full_task_name)s: %(e)s" msgstr "" -#: nova/manager.py:318 +#: nova/manager.py:315 msgid "Notifying Schedulers of capabilities ..." msgstr "" @@ -3232,7 +3232,7 @@ msgstr "" msgid "stop instance" msgstr "" -#: nova/api/openstack/compute/contrib/simple_tenant_usage.py:199 +#: nova/api/openstack/compute/contrib/simple_tenant_usage.py:226 msgid "Invalid start time. The start time cannot occur after the end time." msgstr "" @@ -4845,123 +4845,123 @@ msgstr "" msgid "This shouldn't be getting called except during testing." msgstr "" -#: nova/network/linux_net.py:215 +#: nova/network/linux_net.py:219 #, python-format msgid "Attempted to remove chain %s which does not exist" msgstr "" -#: nova/network/linux_net.py:250 +#: nova/network/linux_net.py:254 #, python-format msgid "Unknown chain: %r" msgstr "" -#: nova/network/linux_net.py:275 +#: nova/network/linux_net.py:279 #, python-format msgid "" "Tried to remove rule that was not there: %(chain)r %(rule)r %(wrap)r " "%(top)r" msgstr "" -#: nova/network/linux_net.py:420 +#: nova/network/linux_net.py:424 msgid "IPTablesManager.apply completed with success" msgstr "" -#: nova/network/linux_net.py:676 +#: nova/network/linux_net.py:680 #, python-format msgid "arping error for ip %s" msgstr "" -#: nova/network/linux_net.py:726 +#: nova/network/linux_net.py:730 #, python-format msgid "Removed %(num)d duplicate rules for floating ip %(float)s" msgstr "" -#: nova/network/linux_net.py:962 +#: nova/network/linux_net.py:966 #, python-format msgid "Pid %d is stale, skip killing dnsmasq" msgstr "" -#: nova/network/linux_net.py:1007 +#: nova/network/linux_net.py:1011 #, python-format msgid "Hupping dnsmasq threw %s" msgstr "" -#: nova/network/linux_net.py:1009 +#: nova/network/linux_net.py:1013 #, python-format msgid "Pid %d is stale, relaunching dnsmasq" msgstr "" -#: nova/network/linux_net.py:1084 +#: nova/network/linux_net.py:1089 #, python-format msgid "killing radvd threw %s" msgstr "" -#: nova/network/linux_net.py:1086 +#: nova/network/linux_net.py:1091 #, python-format msgid "Pid %d is stale, relaunching radvd" msgstr "" -#: nova/network/linux_net.py:1218 +#: nova/network/linux_net.py:1223 #, python-format msgid "Error clearing stale veth %s" msgstr "" -#: nova/network/linux_net.py:1377 +#: nova/network/linux_net.py:1382 #, python-format msgid "Starting VLAN interface %s" msgstr "" -#: nova/network/linux_net.py:1409 +#: nova/network/linux_net.py:1414 #, python-format msgid "Failed unplugging VLAN interface '%s'" msgstr "" -#: nova/network/linux_net.py:1411 +#: nova/network/linux_net.py:1416 #, python-format msgid "Unplugged VLAN interface '%s'" msgstr "" -#: nova/network/linux_net.py:1433 +#: nova/network/linux_net.py:1438 #, python-format msgid "Starting Bridge %s" msgstr "" -#: nova/network/linux_net.py:1445 +#: nova/network/linux_net.py:1450 #, python-format msgid "Adding interface %(interface)s to bridge %(bridge)s" msgstr "" -#: nova/network/linux_net.py:1481 +#: nova/network/linux_net.py:1486 #, python-format msgid "Failed to add interface: %s" msgstr "" -#: nova/network/linux_net.py:1518 +#: nova/network/linux_net.py:1529 #, python-format msgid "Failed unplugging bridge interface '%s'" msgstr "" -#: nova/network/linux_net.py:1521 +#: nova/network/linux_net.py:1532 #, python-format msgid "Unplugged bridge interface '%s'" msgstr "" -#: nova/network/linux_net.py:1690 +#: nova/network/linux_net.py:1721 #, python-format msgid "Starting bridge %s " msgstr "" -#: nova/network/linux_net.py:1698 +#: nova/network/linux_net.py:1729 #, python-format msgid "Done starting bridge %s" msgstr "" -#: nova/network/linux_net.py:1718 +#: nova/network/linux_net.py:1749 #, python-format msgid "Failed unplugging gateway interface '%s'" msgstr "" -#: nova/network/linux_net.py:1720 +#: nova/network/linux_net.py:1751 #, python-format msgid "Unplugged gateway interface '%s'" msgstr "" @@ -5152,49 +5152,49 @@ msgstr "" msgid "Fail to delete port %(portid)s with failure: %(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:314 +#: nova/network/quantumv2/api.py:315 #, python-format msgid "deallocate_for_instance() for %s" msgstr "" -#: nova/network/quantumv2/api.py:323 +#: nova/network/quantumv2/api.py:324 #, python-format msgid "Failed to delete quantum port %(portid)s " msgstr "" -#: nova/network/quantumv2/api.py:342 +#: nova/network/quantumv2/api.py:343 #, python-format msgid "Failed to delete quantum port %(port_id)s " msgstr "" -#: nova/network/quantumv2/api.py:364 +#: nova/network/quantumv2/api.py:365 #, python-format msgid "get_instance_nw_info() for %s" msgstr "" -#: nova/network/quantumv2/api.py:396 +#: nova/network/quantumv2/api.py:397 #, python-format msgid "" "Unable to update port %(portid)s on subnet %(subnet_id)s with failure: " "%(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:426 +#: nova/network/quantumv2/api.py:427 #, python-format msgid "Unable to update port %(portid)s with failure: %(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:436 +#: nova/network/quantumv2/api.py:437 #, python-format msgid "validate_networks() for %s" msgstr "" -#: nova/network/quantumv2/api.py:693 +#: nova/network/quantumv2/api.py:694 #, python-format msgid "Multiple floating IP pools matches found for name '%s'" msgstr "" -#: nova/network/quantumv2/api.py:798 +#: nova/network/quantumv2/api.py:799 #, python-format msgid "Network %(net)s for port %(port_id)s not found!" msgstr "" @@ -6263,12 +6263,12 @@ msgstr "" msgid "uuid" msgstr "" -#: nova/tests/test_xenapi.py:884 +#: nova/tests/test_xenapi.py:897 #, python-format msgid "Creating files in %s to simulate guest agent" msgstr "" -#: nova/tests/test_xenapi.py:895 +#: nova/tests/test_xenapi.py:908 #, python-format msgid "Removing simulated guest agent files in %s" msgstr "" @@ -9215,7 +9215,7 @@ msgstr "" msgid "Migrated VM to host %s" msgstr "" -#: nova/virt/vmwareapi/vmops.py:1050 nova/virt/xenapi/vmops.py:1316 +#: nova/virt/vmwareapi/vmops.py:1050 nova/virt/xenapi/vmops.py:1324 #, python-format msgid "Found %(instance_count)d hung reboots older than %(timeout)d seconds" msgstr "" @@ -9373,19 +9373,19 @@ msgstr "" msgid "Mountpoint %(mountpoint)s detached from instance %(instance_name)s" msgstr "" -#: nova/virt/xenapi/agent.py:88 nova/virt/xenapi/vmops.py:1556 +#: nova/virt/xenapi/agent.py:88 nova/virt/xenapi/vmops.py:1564 #, python-format msgid "TIMEOUT: The call to %(method)s timed out. args=%(args)r" msgstr "" -#: nova/virt/xenapi/agent.py:92 nova/virt/xenapi/vmops.py:1560 +#: nova/virt/xenapi/agent.py:92 nova/virt/xenapi/vmops.py:1568 #, python-format msgid "" "NOT IMPLEMENTED: The call to %(method)s is not supported by the agent. " "args=%(args)r" msgstr "" -#: nova/virt/xenapi/agent.py:97 nova/virt/xenapi/vmops.py:1565 +#: nova/virt/xenapi/agent.py:97 nova/virt/xenapi/vmops.py:1573 #, python-format msgid "The call to %(method)s returned an error: %(e)s. args=%(args)r" msgstr "" @@ -9511,32 +9511,32 @@ msgstr "" msgid "Got exception: %s" msgstr "" -#: nova/virt/xenapi/fake.py:680 nova/virt/xenapi/fake.py:784 -#: nova/virt/xenapi/fake.py:803 nova/virt/xenapi/fake.py:871 +#: nova/virt/xenapi/fake.py:687 nova/virt/xenapi/fake.py:791 +#: nova/virt/xenapi/fake.py:810 nova/virt/xenapi/fake.py:878 msgid "Raising NotImplemented" msgstr "" -#: nova/virt/xenapi/fake.py:682 +#: nova/virt/xenapi/fake.py:689 #, python-format msgid "xenapi.fake does not have an implementation for %s" msgstr "" -#: nova/virt/xenapi/fake.py:716 +#: nova/virt/xenapi/fake.py:723 #, python-format msgid "Calling %(localname)s %(impl)s" msgstr "" -#: nova/virt/xenapi/fake.py:721 +#: nova/virt/xenapi/fake.py:728 #, python-format msgid "Calling getter %s" msgstr "" -#: nova/virt/xenapi/fake.py:724 +#: nova/virt/xenapi/fake.py:731 #, python-format msgid "Calling setter %s" msgstr "" -#: nova/virt/xenapi/fake.py:786 +#: nova/virt/xenapi/fake.py:793 #, python-format msgid "" "xenapi.fake does not have an implementation for %s or it has been called " @@ -9698,324 +9698,324 @@ msgstr "" msgid "Unable to destroy VBD %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:405 +#: nova/virt/xenapi/vm_utils.py:408 #, python-format msgid "Creating %(vbd_type)s-type VBD for VM %(vm_ref)s, VDI %(vdi_ref)s ... " msgstr "" -#: nova/virt/xenapi/vm_utils.py:408 +#: nova/virt/xenapi/vm_utils.py:411 #, python-format msgid "Created VBD %(vbd_ref)s for VM %(vm_ref)s, VDI %(vdi_ref)s." msgstr "" -#: nova/virt/xenapi/vm_utils.py:424 +#: nova/virt/xenapi/vm_utils.py:437 #, python-format msgid "Unable to destroy VDI %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:456 +#: nova/virt/xenapi/vm_utils.py:469 #, python-format msgid "" "Created VDI %(vdi_ref)s (%(name_label)s, %(virtual_size)s, %(read_only)s)" " on %(sr_ref)s." msgstr "" -#: nova/virt/xenapi/vm_utils.py:470 +#: nova/virt/xenapi/vm_utils.py:483 msgid "SR not present and could not be introduced" msgstr "" -#: nova/virt/xenapi/vm_utils.py:495 +#: nova/virt/xenapi/vm_utils.py:508 #, python-format msgid "block device info: %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:581 +#: nova/virt/xenapi/vm_utils.py:594 #, python-format msgid "Cloned VDI %(vdi_ref)s from VDI %(vdi_to_clone_ref)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:601 +#: nova/virt/xenapi/vm_utils.py:614 #, python-format msgid "No primary VDI found for %(vm_ref)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:614 +#: nova/virt/xenapi/vm_utils.py:627 msgid "Starting snapshot for VM" msgstr "" -#: nova/virt/xenapi/vm_utils.py:664 +#: nova/virt/xenapi/vm_utils.py:677 #, python-format msgid "Destroying cached VDI '%(vdi_uuid)s'" msgstr "" -#: nova/virt/xenapi/vm_utils.py:911 +#: nova/virt/xenapi/vm_utils.py:930 #, python-format msgid "" "Fast cloning is only supported on default local SR of type ext. SR on " "this system was found to be of type %(sr_type)s. Ignoring the cow flag." msgstr "" -#: nova/virt/xenapi/vm_utils.py:967 +#: nova/virt/xenapi/vm_utils.py:986 #, python-format msgid "Unrecognized cache_images value '%s', defaulting to True" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1001 +#: nova/virt/xenapi/vm_utils.py:1020 #, python-format msgid "Fetched VDIs of type '%(vdi_type)s' with UUID '%(vdi_uuid)s'" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1013 +#: nova/virt/xenapi/vm_utils.py:1032 #, python-format msgid "" "download_vhd %(image_id)s, attempt %(attempt_num)d/%(max_attempts)d, " "params: %(params)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1026 +#: nova/virt/xenapi/vm_utils.py:1045 #, python-format msgid "download_vhd failed: %r" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1060 +#: nova/virt/xenapi/vm_utils.py:1079 #, python-format msgid "Invalid value '%s' for xenapi_torrent_images" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1071 +#: nova/virt/xenapi/vm_utils.py:1090 #, python-format msgid "Asking xapi to fetch vhd image %(image_id)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1135 +#: nova/virt/xenapi/vm_utils.py:1154 #, python-format msgid "vdi_uuid=%(cur_vdi_uuid)s vdi_size_bytes=%(vdi_size_bytes)d" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1150 +#: nova/virt/xenapi/vm_utils.py:1169 #, python-format msgid "image_size_bytes=%(size_bytes)d, allowed_size_bytes=%(allowed_size_bytes)d" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1154 +#: nova/virt/xenapi/vm_utils.py:1173 #, python-format msgid "" "Image size %(size_bytes)d exceeded instance_type allowed size " "%(allowed_size_bytes)d" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1176 +#: nova/virt/xenapi/vm_utils.py:1195 #, python-format msgid "Fetching image %(image_id)s, type %(image_type_str)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1189 +#: nova/virt/xenapi/vm_utils.py:1208 #, python-format msgid "Size for image %(image_id)s: %(virtual_size)d" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1198 +#: nova/virt/xenapi/vm_utils.py:1217 #, python-format msgid "" "Kernel/Ramdisk image is too large: %(vdi_size)d bytes, max %(max_size)d " "bytes" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1217 +#: nova/virt/xenapi/vm_utils.py:1236 #, python-format msgid "Copying VDI %s to /boot/guest on dom0" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1231 +#: nova/virt/xenapi/vm_utils.py:1250 #, python-format msgid "Kernel/Ramdisk VDI %s destroyed" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1240 +#: nova/virt/xenapi/vm_utils.py:1259 msgid "Failed to fetch glance image" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1281 +#: nova/virt/xenapi/vm_utils.py:1300 #, python-format msgid "Detected %(image_type_str)s format for image %(image_ref)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1312 +#: nova/virt/xenapi/vm_utils.py:1331 #, python-format msgid "Looking up vdi %s for PV kernel" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1330 +#: nova/virt/xenapi/vm_utils.py:1349 #, python-format msgid "" "Image format is None: trying to determine PV status using pygrub; if " "instance with vdi %s does not boot correctly, try with image metadata." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1336 +#: nova/virt/xenapi/vm_utils.py:1355 #, python-format msgid "Unknown image format %(disk_image_type)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1367 +#: nova/virt/xenapi/vm_utils.py:1386 #, python-format msgid "VDI %s is still available" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1463 +#: nova/virt/xenapi/vm_utils.py:1482 #, python-format msgid "Unable to parse rrd of %(vm_uuid)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1490 +#: nova/virt/xenapi/vm_utils.py:1509 #, python-format msgid "Re-scanning SR %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1518 +#: nova/virt/xenapi/vm_utils.py:1537 #, python-format msgid "Flag sr_matching_filter '%s' does not respect formatting convention" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1536 +#: nova/virt/xenapi/vm_utils.py:1555 msgid "" "XenAPI is unable to find a Storage Repository to install guest instances " "on. Please check your configuration and/or configure the flag " "'sr_matching_filter'" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1549 +#: nova/virt/xenapi/vm_utils.py:1568 msgid "Cannot find SR of content-type ISO" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1557 +#: nova/virt/xenapi/vm_utils.py:1576 #, python-format msgid "ISO: looking at SR %(sr_rec)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1559 +#: nova/virt/xenapi/vm_utils.py:1578 msgid "ISO: not iso content" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1562 +#: nova/virt/xenapi/vm_utils.py:1581 msgid "ISO: iso content_type, no 'i18n-key' key" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1565 +#: nova/virt/xenapi/vm_utils.py:1584 msgid "ISO: iso content_type, i18n-key value not 'local-storage-iso'" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1569 +#: nova/virt/xenapi/vm_utils.py:1588 msgid "ISO: SR MATCHing our criteria" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1571 +#: nova/virt/xenapi/vm_utils.py:1590 msgid "ISO: ISO, looking to see if it is host local" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1574 +#: nova/virt/xenapi/vm_utils.py:1593 #, python-format msgid "ISO: PBD %(pbd_ref)s disappeared" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1577 +#: nova/virt/xenapi/vm_utils.py:1596 #, python-format msgid "ISO: PBD matching, want %(pbd_rec)s, have %(host)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1580 +#: nova/virt/xenapi/vm_utils.py:1599 msgid "ISO: SR with local PBD" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1602 +#: nova/virt/xenapi/vm_utils.py:1621 #, python-format msgid "" "Unable to obtain RRD XML for VM %(vm_uuid)s with server details: " "%(server)s." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1618 +#: nova/virt/xenapi/vm_utils.py:1637 #, python-format msgid "Unable to obtain RRD XML updates with server details: %(server)s." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1672 +#: nova/virt/xenapi/vm_utils.py:1691 #, python-format msgid "Invalid statistics data from Xenserver: %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1732 +#: nova/virt/xenapi/vm_utils.py:1751 #, python-format msgid "VHD %(vdi_uuid)s has parent %(parent_uuid)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1819 +#: nova/virt/xenapi/vm_utils.py:1838 #, python-format msgid "" "Parent %(parent_uuid)s doesn't match original parent " "%(original_parent_uuid)s, waiting for coalesce..." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1829 +#: nova/virt/xenapi/vm_utils.py:1848 #, python-format msgid "VHD coalesce attempts exceeded (%(max_attempts)d), giving up..." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1864 +#: nova/virt/xenapi/vm_utils.py:1883 #, python-format msgid "Timeout waiting for device %s to be created" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1884 +#: nova/virt/xenapi/vm_utils.py:1903 #, python-format msgid "Disconnecting stale VDI %s from compute domU" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1897 +#: nova/virt/xenapi/vm_utils.py:1916 #, python-format msgid "Plugging VBD %s ... " msgstr "" -#: nova/virt/xenapi/vm_utils.py:1900 +#: nova/virt/xenapi/vm_utils.py:1919 #, python-format msgid "Plugging VBD %s done." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1902 +#: nova/virt/xenapi/vm_utils.py:1921 #, python-format msgid "VBD %(vbd_ref)s plugged as %(orig_dev)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1905 +#: nova/virt/xenapi/vm_utils.py:1924 #, python-format msgid "VBD %(vbd_ref)s plugged into wrong dev, remapping to %(dev)s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1910 +#: nova/virt/xenapi/vm_utils.py:1929 #, python-format msgid "Destroying VBD for VDI %s ... " msgstr "" -#: nova/virt/xenapi/vm_utils.py:1918 +#: nova/virt/xenapi/vm_utils.py:1937 #, python-format msgid "Destroying VBD for VDI %s done." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1945 +#: nova/virt/xenapi/vm_utils.py:1964 #, python-format msgid "Running pygrub against %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1953 +#: nova/virt/xenapi/vm_utils.py:1972 #, python-format msgid "Found Xen kernel %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1955 +#: nova/virt/xenapi/vm_utils.py:1974 msgid "No Xen kernel found. Booting HVM." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1957 +#: nova/virt/xenapi/vm_utils.py:1976 msgid "" "Error while executing pygrub! Please, ensure the binary is installed " "correctly, and available in your PATH; on some Linux distros, pygrub may " @@ -10023,251 +10023,247 @@ msgid "" "mode." msgstr "" -#: nova/virt/xenapi/vm_utils.py:1974 +#: nova/virt/xenapi/vm_utils.py:1993 msgid "Partitions:" msgstr "" -#: nova/virt/xenapi/vm_utils.py:1980 +#: nova/virt/xenapi/vm_utils.py:1999 #, python-format msgid " %(num)s: %(ptype)s %(size)d sectors" msgstr "" -#: nova/virt/xenapi/vm_utils.py:2005 +#: nova/virt/xenapi/vm_utils.py:2024 #, python-format msgid "" "Writing partition table %(primary_first)d %(primary_last)d to " "%(dev_path)s..." msgstr "" -#: nova/virt/xenapi/vm_utils.py:2018 +#: nova/virt/xenapi/vm_utils.py:2037 #, python-format msgid "Writing partition table %s done." msgstr "" -#: nova/virt/xenapi/vm_utils.py:2072 +#: nova/virt/xenapi/vm_utils.py:2091 #, python-format msgid "" "Starting sparse_copy src=%(src_path)s dst=%(dst_path)s " "virtual_size=%(virtual_size)d block_size=%(block_size)d" msgstr "" -#: nova/virt/xenapi/vm_utils.py:2105 +#: nova/virt/xenapi/vm_utils.py:2124 #, python-format msgid "" "Finished sparse_copy in %(duration).2f secs, %(compression_pct).2f%% " "reduction in size" msgstr "" -#: nova/virt/xenapi/vm_utils.py:2157 +#: nova/virt/xenapi/vm_utils.py:2176 msgid "Manipulating interface files directly" msgstr "" -#: nova/virt/xenapi/vm_utils.py:2166 +#: nova/virt/xenapi/vm_utils.py:2185 #, python-format msgid "Failed to mount filesystem (expected for non-linux instances): %s" msgstr "" -#: nova/virt/xenapi/vm_utils.py:2278 +#: nova/virt/xenapi/vm_utils.py:2297 msgid "This domU must be running on the host specified by xenapi_connection_url" msgstr "" -#: nova/virt/xenapi/vmops.py:134 nova/virt/xenapi/vmops.py:784 +#: nova/virt/xenapi/vmops.py:139 nova/virt/xenapi/vmops.py:792 #, python-format msgid "Updating progress to %(progress)d" msgstr "" -#: nova/virt/xenapi/vmops.py:169 +#: nova/virt/xenapi/vmops.py:174 #, python-format msgid "Importing image upload handler: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:182 +#: nova/virt/xenapi/vmops.py:187 msgid "Error: Agent is disabled" msgstr "" -#: nova/virt/xenapi/vmops.py:290 +#: nova/virt/xenapi/vmops.py:295 msgid "Starting instance" msgstr "" -#: nova/virt/xenapi/vmops.py:376 +#: nova/virt/xenapi/vmops.py:381 msgid "Removing kernel/ramdisk files from dom0" msgstr "" -#: nova/virt/xenapi/vmops.py:449 +#: nova/virt/xenapi/vmops.py:454 #, python-format msgid "Block device information present: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:480 +#: nova/virt/xenapi/vmops.py:485 msgid "Failed to spawn, rolling back" msgstr "" -#: nova/virt/xenapi/vmops.py:559 -msgid "Detected ISO image type, creating blank VM for install" -msgstr "" - -#: nova/virt/xenapi/vmops.py:576 +#: nova/virt/xenapi/vmops.py:584 msgid "Auto configuring disk, attempting to resize partition..." msgstr "" -#: nova/virt/xenapi/vmops.py:622 +#: nova/virt/xenapi/vmops.py:630 msgid "Starting VM" msgstr "" -#: nova/virt/xenapi/vmops.py:628 +#: nova/virt/xenapi/vmops.py:636 msgid "Waiting for instance state to become running" msgstr "" -#: nova/virt/xenapi/vmops.py:642 +#: nova/virt/xenapi/vmops.py:650 #, python-format msgid "" "Latest agent build for %(hypervisor)s/%(os)s/%(architecture)s is " "%(version)s" msgstr "" -#: nova/virt/xenapi/vmops.py:645 +#: nova/virt/xenapi/vmops.py:653 #, python-format msgid "No agent build found for %(hypervisor)s/%(os)s/%(architecture)s" msgstr "" -#: nova/virt/xenapi/vmops.py:656 +#: nova/virt/xenapi/vmops.py:664 #, python-format msgid "Instance agent version: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:687 +#: nova/virt/xenapi/vmops.py:695 msgid "Setting VCPU weight" msgstr "" -#: nova/virt/xenapi/vmops.py:695 +#: nova/virt/xenapi/vmops.py:703 #, python-format msgid "Could not find VM with name %s" msgstr "" -#: nova/virt/xenapi/vmops.py:753 +#: nova/virt/xenapi/vmops.py:761 msgid "Finished snapshot and upload for VM" msgstr "" -#: nova/virt/xenapi/vmops.py:757 +#: nova/virt/xenapi/vmops.py:765 #, python-format msgid "Migrating VHD '%(vdi_uuid)s' with seq_num %(seq_num)d" msgstr "" -#: nova/virt/xenapi/vmops.py:765 +#: nova/virt/xenapi/vmops.py:773 msgid "Failed to transfer vhd to new host" msgstr "" -#: nova/virt/xenapi/vmops.py:802 +#: nova/virt/xenapi/vmops.py:810 #, python-format msgid "Resizing down VDI %(vdi_uuid)s from %(old_gb)dGB to %(new_gb)dGB" msgstr "" -#: nova/virt/xenapi/vmops.py:808 nova/virt/xenapi/vmops.py:858 +#: nova/virt/xenapi/vmops.py:816 nova/virt/xenapi/vmops.py:866 msgid "Clean shutdown did not complete successfully, trying hard shutdown." msgstr "" -#: nova/virt/xenapi/vmops.py:887 +#: nova/virt/xenapi/vmops.py:895 msgid "Resize down not allowed without auto_disk_config" msgstr "" -#: nova/virt/xenapi/vmops.py:932 +#: nova/virt/xenapi/vmops.py:940 #, python-format msgid "Resizing up VDI %(vdi_uuid)s from %(old_gb)dGB to %(new_gb)dGB" msgstr "" -#: nova/virt/xenapi/vmops.py:937 +#: nova/virt/xenapi/vmops.py:945 msgid "Resize complete" msgstr "" -#: nova/virt/xenapi/vmops.py:981 +#: nova/virt/xenapi/vmops.py:989 msgid "Starting halted instance found during reboot" msgstr "" -#: nova/virt/xenapi/vmops.py:987 +#: nova/virt/xenapi/vmops.py:995 msgid "" "Reboot failed due to bad volumes, detaching bad volumes and starting " "halted instance" msgstr "" -#: nova/virt/xenapi/vmops.py:1081 +#: nova/virt/xenapi/vmops.py:1089 msgid "Unable to find root VBD/VDI for VM" msgstr "" -#: nova/virt/xenapi/vmops.py:1085 +#: nova/virt/xenapi/vmops.py:1093 msgid "Destroying VDIs" msgstr "" -#: nova/virt/xenapi/vmops.py:1112 +#: nova/virt/xenapi/vmops.py:1120 msgid "Using RAW or VHD, skipping kernel and ramdisk deletion" msgstr "" -#: nova/virt/xenapi/vmops.py:1119 +#: nova/virt/xenapi/vmops.py:1127 msgid "instance has a kernel or ramdisk but not both" msgstr "" -#: nova/virt/xenapi/vmops.py:1126 +#: nova/virt/xenapi/vmops.py:1134 msgid "kernel/ramdisk files removed" msgstr "" -#: nova/virt/xenapi/vmops.py:1153 +#: nova/virt/xenapi/vmops.py:1161 msgid "Destroying VM" msgstr "" -#: nova/virt/xenapi/vmops.py:1182 +#: nova/virt/xenapi/vmops.py:1190 msgid "VM is not present, skipping destroy..." msgstr "" -#: nova/virt/xenapi/vmops.py:1233 +#: nova/virt/xenapi/vmops.py:1241 #, python-format msgid "Instance is already in Rescue Mode: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:1267 +#: nova/virt/xenapi/vmops.py:1275 msgid "VM is not present, skipping soft delete..." msgstr "" -#: nova/virt/xenapi/vmops.py:1320 +#: nova/virt/xenapi/vmops.py:1328 msgid "Automatically hard rebooting" msgstr "" -#: nova/virt/xenapi/vmops.py:1460 +#: nova/virt/xenapi/vmops.py:1468 msgid "Injecting network info to xenstore" msgstr "" -#: nova/virt/xenapi/vmops.py:1479 +#: nova/virt/xenapi/vmops.py:1487 msgid "Creating vifs" msgstr "" -#: nova/virt/xenapi/vmops.py:1488 +#: nova/virt/xenapi/vmops.py:1496 #, python-format msgid "Creating VIF for network %(network_ref)s" msgstr "" -#: nova/virt/xenapi/vmops.py:1491 +#: nova/virt/xenapi/vmops.py:1499 #, python-format msgid "Created VIF %(vif_ref)s, network %(network_ref)s" msgstr "" -#: nova/virt/xenapi/vmops.py:1519 +#: nova/virt/xenapi/vmops.py:1527 msgid "Injecting hostname to xenstore" msgstr "" -#: nova/virt/xenapi/vmops.py:1615 +#: nova/virt/xenapi/vmops.py:1623 #, python-format msgid "" "Destination host:%(hostname)s must be in the same aggregate as the source" " server" msgstr "" -#: nova/virt/xenapi/vmops.py:1647 +#: nova/virt/xenapi/vmops.py:1655 msgid "Migrate Receive failed" msgstr "" -#: nova/virt/xenapi/vmops.py:1695 +#: nova/virt/xenapi/vmops.py:1703 msgid "VM.assert_can_migratefailed" msgstr "" -#: nova/virt/xenapi/vmops.py:1732 +#: nova/virt/xenapi/vmops.py:1740 msgid "Migrate Send failed" msgstr "" diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index a56bbfe25..4a63f275d 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -1019,7 +1019,6 @@ def restart_dhcp(context, dev, network_ref): '--strict-order', '--bind-interfaces', '--conf-file=%s' % CONF.dnsmasq_config_file, - '--domain=\'%s\'' % CONF.dhcp_domain, '--pid-file=%s' % _dhcp_file(dev, 'pid'), '--listen-address=%s' % network_ref['dhcp_server'], '--except-interface=lo', @@ -1033,6 +1032,11 @@ def restart_dhcp(context, dev, network_ref): '--dhcp-script=%s' % CONF.dhcpbridge, '--leasefile-ro'] + # dnsmasq currently gives an error for an empty domain, + # rather than ignoring. So only specify it if defined. + if CONF.dhcp_domain: + cmd.append('--domain=%s' % CONF.dhcp_domain) + dns_servers = set(CONF.dns_server) if CONF.use_network_dns_servers: if network_ref.get('dns1'): @@ -1513,14 +1517,17 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): for rule in get_gateway_rules(bridge): ipv4_filter.remove_rule(*rule) else: - ipv4_filter.remove_rule('FORWARD', - ('--in-interface %s -j %s' - % (bridge, - CONF.iptables_drop_action))) - ipv4_filter.remove_rule('FORWARD', - ('--out-interface %s -j %s' - % (bridge, - CONF.iptables_drop_action))) + drop_actions = ['DROP'] + if CONF.iptables_drop_action != 'DROP': + drop_actions.append(CONF.iptables_drop_action) + + for drop_action in drop_actions: + ipv4_filter.remove_rule('FORWARD', + ('--in-interface %s -j %s' + % (bridge, drop_action))) + ipv4_filter.remove_rule('FORWARD', + ('--out-interface %s -j %s' + % (bridge, drop_action))) try: utils.execute('ip', 'link', 'delete', bridge, run_as_root=True, check_exit_code=[0, 2, 254]) @@ -1591,27 +1598,34 @@ def remove_isolate_dhcp_address(interface, address): # NOTE(vish): the above is not possible with iptables/arptables # block dhcp broadcast traffic across the interface ipv4_filter = iptables_manager.ipv4['filter'] - ipv4_filter.remove_rule('FORWARD', - ('-m physdev --physdev-in %s -d 255.255.255.255 ' - '-p udp --dport 67 -j %s' - % (interface, CONF.iptables_drop_action)), - top=True) - ipv4_filter.remove_rule('FORWARD', - ('-m physdev --physdev-out %s -d 255.255.255.255 ' - '-p udp --dport 67 -j %s' - % (interface, CONF.iptables_drop_action)), - top=True) - # block ip traffic to address across the interface - ipv4_filter.remove_rule('FORWARD', - ('-m physdev --physdev-in %s -d %s -j %s' - % (interface, address, - CONF.iptables_drop_action)), - top=True) - ipv4_filter.remove_rule('FORWARD', - ('-m physdev --physdev-out %s -s %s -j %s' - % (interface, address, - CONF.iptables_drop_action)), - top=True) + + drop_actions = ['DROP'] + if CONF.iptables_drop_action != 'DROP': + drop_actions.append(CONF.iptables_drop_action) + + for drop_action in drop_actions: + ipv4_filter.remove_rule('FORWARD', + ('-m physdev --physdev-in %s ' + '-d 255.255.255.255 ' + '-p udp --dport 67 -j %s' + % (interface, drop_action)), + top=True) + ipv4_filter.remove_rule('FORWARD', + ('-m physdev --physdev-out %s ' + '-d 255.255.255.255 ' + '-p udp --dport 67 -j %s' + % (interface, drop_action)), + top=True) + + # block ip traffic to address across the interface + ipv4_filter.remove_rule('FORWARD', + ('-m physdev --physdev-in %s -d %s -j %s' + % (interface, address, drop_action)), + top=True) + ipv4_filter.remove_rule('FORWARD', + ('-m physdev --physdev-out %s -s %s -j %s' + % (interface, address, drop_action)), + top=True) def get_gateway_rules(bridge): diff --git a/nova/network/manager.py b/nova/network/manager.py index b9c8efe44..ac413135a 100644 --- a/nova/network/manager.py +++ b/nova/network/manager.py @@ -1115,13 +1115,13 @@ class NetworkManager(manager.Manager): subnets_v4.append(next_subnet) subnet = next_subnet else: - raise ValueError(_('cidr already in use')) + raise exception.CidrConflict(_('cidr already in use')) for used_subnet in used_subnets: if subnet in used_subnet: msg = _('requested cidr (%(cidr)s) conflicts with ' 'existing supernet (%(super)s)') - raise ValueError(msg % {'cidr': subnet, - 'super': used_subnet}) + raise exception.CidrConflict( + msg % {'cidr': subnet, 'super': used_subnet}) if used_subnet in subnet: next_subnet = find_next(subnet) if next_subnet: @@ -1132,8 +1132,8 @@ class NetworkManager(manager.Manager): msg = _('requested cidr (%(cidr)s) conflicts ' 'with existing smaller cidr ' '(%(smaller)s)') - raise ValueError(msg % {'cidr': subnet, - 'smaller': used_subnet}) + raise exception.CidrConflict( + msg % {'cidr': subnet, 'smaller': used_subnet}) networks = [] subnets = itertools.izip_longest(subnets_v4, subnets_v6) diff --git a/nova/network/security_group/quantum_driver.py b/nova/network/security_group/quantum_driver.py index 5a24a74ab..aecafe8d1 100644 --- a/nova/network/security_group/quantum_driver.py +++ b/nova/network/security_group/quantum_driver.py @@ -23,7 +23,6 @@ from quantumclient.quantum import v2_0 as quantumv20 from webob import exc from nova.compute import api as compute_api -from nova import context from nova import exception from nova.network import quantumv2 from nova.network.security_group import security_group_base @@ -246,14 +245,43 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): raise e return self._convert_to_nova_security_group_rule_format(rule) - def get_instance_security_groups(self, req, instance_id, + def get_instances_security_groups_bindings(self, context): + """Returns a dict(instance_id, [security_groups]) to allow obtaining + all of the instances and their security groups in one shot.""" + quantum = quantumv2.get_client(context) + ports = quantum.list_ports().get('ports') + security_groups = quantum.list_security_groups().get('security_groups') + security_group_lookup = {} + instances_security_group_bindings = {} + for security_group in security_groups: + security_group_lookup[security_group['id']] = security_group + + for port in ports: + for port_security_group in port.get('security_groups', []): + try: + sg = security_group_lookup[port_security_group] + # name is optional in quantum so if not specified return id + if sg.get('name'): + sg_entry = {'name': sg['name']} + else: + sg_entry = {'name': sg['id']} + instances_security_group_bindings.setdefault( + port['device_id'], []).append(sg_entry) + except KeyError: + # This should only happen due to a race condition + # if the security group on a port was deleted after the + # ports were returned. We pass since this security + # group is no longer on the port. + pass + return instances_security_group_bindings + + def get_instance_security_groups(self, context, instance_id, instance_uuid=None, detailed=False): """Returns the security groups that are associated with an instance. If detailed is True then it also returns the full details of the security groups associated with an instance. """ - admin_context = context.get_admin_context() - quantum = quantumv2.get_client(admin_context) + quantum = quantumv2.get_client(context) if instance_uuid: params = {'device_id': instance_uuid} else: @@ -281,7 +309,7 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): name = security_group['id'] ret.append({'name': name}) except KeyError: - # If this should only happen due to a race condition + # This should only happen due to a race condition # if the security group on a port was deleted after the # ports were returned. We pass since this security # group is no longer on the port. diff --git a/nova/network/security_group/security_group_base.py b/nova/network/security_group/security_group_base.py index 4a82bd881..3babf4b00 100644 --- a/nova/network/security_group/security_group_base.py +++ b/nova/network/security_group/security_group_base.py @@ -204,7 +204,8 @@ class SecurityGroupBase(object): def get_rule(self, context, id): raise NotImplementedError() - def get_instance_security_groups(self, req, instance_id): + def get_instance_security_groups(self, context, instance_id, + instance_uuid=None, detailed=False): raise NotImplementedError() def add_to_instance(self, context, instance, security_group_name): diff --git a/nova/openstack/common/db/sqlalchemy/session.py b/nova/openstack/common/db/sqlalchemy/session.py index cf6713581..010254e7a 100644 --- a/nova/openstack/common/db/sqlalchemy/session.py +++ b/nova/openstack/common/db/sqlalchemy/session.py @@ -264,7 +264,8 @@ sql_opts = [ os.path.abspath(os.path.join(os.path.dirname(__file__), '../', '$sqlite_db')), help='The SQLAlchemy connection string used to connect to the ' - 'database'), + 'database', + secret=True), cfg.StrOpt('sqlite_db', default='nova.sqlite', help='the filename to use with sqlite'), diff --git a/nova/openstack/common/db/sqlalchemy/utils.py b/nova/openstack/common/db/sqlalchemy/utils.py index 6a9cb846f..3f5ae737a 100644 --- a/nova/openstack/common/db/sqlalchemy/utils.py +++ b/nova/openstack/common/db/sqlalchemy/utils.py @@ -2,7 +2,7 @@ # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. -# Copyright 2010-2011 OpenStack Foundation +# Copyright 2010-2011 OpenStack Foundation. # Copyright 2012 Justin Santa Barbara # All Rights Reserved. # diff --git a/nova/openstack/common/gettextutils.py b/nova/openstack/common/gettextutils.py index d52309e62..b9993b491 100644 --- a/nova/openstack/common/gettextutils.py +++ b/nova/openstack/common/gettextutils.py @@ -26,7 +26,7 @@ Usual usage in an openstack.common module: import gettext -t = gettext.translation('openstack-common', 'locale', fallback=True) +t = gettext.translation('nova', 'locale', fallback=True) def _(msg): diff --git a/nova/openstack/common/rpc/impl_qpid.py b/nova/openstack/common/rpc/impl_qpid.py index fd4b25e7f..d3cc12d3c 100644 --- a/nova/openstack/common/rpc/impl_qpid.py +++ b/nova/openstack/common/rpc/impl_qpid.py @@ -40,8 +40,8 @@ qpid_opts = [ cfg.StrOpt('qpid_hostname', default='localhost', help='Qpid broker hostname'), - cfg.StrOpt('qpid_port', - default='5672', + cfg.IntOpt('qpid_port', + default=5672, help='Qpid broker port'), cfg.ListOpt('qpid_hosts', default=['$qpid_hostname:$qpid_port'], diff --git a/nova/openstack/common/rpc/matchmaker.py b/nova/openstack/common/rpc/matchmaker.py index e4862396a..dcee752b2 100644 --- a/nova/openstack/common/rpc/matchmaker.py +++ b/nova/openstack/common/rpc/matchmaker.py @@ -35,10 +35,10 @@ matchmaker_opts = [ default='/etc/nova/matchmaker_ring.json', help='Matchmaker ring file (JSON)'), cfg.IntOpt('matchmaker_heartbeat_freq', - default='300', + default=300, help='Heartbeat frequency'), cfg.IntOpt('matchmaker_heartbeat_ttl', - default='600', + default=600, help='Heartbeat time-to-live.'), ] diff --git a/nova/quota.py b/nova/quota.py index 3903a6add..8aaa3ed31 100644 --- a/nova/quota.py +++ b/nova/quota.py @@ -44,7 +44,7 @@ quota_opts = [ default=10, help='number of floating ips allowed per project'), cfg.IntOpt('quota_fixed_ips', - default=10, + default=-1, help=('number of fixed ips allowed per project (this should be ' 'at least the number of instances allowed)')), cfg.IntOpt('quota_metadata_items', diff --git a/nova/tests/api/openstack/compute/contrib/test_flavor_access.py b/nova/tests/api/openstack/compute/contrib/test_flavor_access.py index fc5543409..b3564dede 100644 --- a/nova/tests/api/openstack/compute/contrib/test_flavor_access.py +++ b/nova/tests/api/openstack/compute/contrib/test_flavor_access.py @@ -98,6 +98,20 @@ def fake_get_all_types(context, inactive=0, filters=None): class FakeRequest(object): environ = {"nova.context": context.get_admin_context()} + def get_db_flavor(self, flavor_id): + return INSTANCE_TYPES[flavor_id] + + +class FakeResponse(object): + obj = {'flavor': {'id': '0'}, + 'flavors': [ + {'id': '0'}, + {'id': '2'}] + } + + def attach(self, **kwargs): + pass + class FlavorAccessTest(test.TestCase): def setUp(self): @@ -209,6 +223,28 @@ class FlavorAccessTest(test.TestCase): result = self.flavor_controller.index(req) self._verify_flavor_list(result['flavors'], expected['flavors']) + def test_show(self): + resp = FakeResponse() + self.flavor_action_controller.show(self.req, resp, '0') + self.assertEqual({'id': '0', 'os-flavor-access:is_public': True}, + resp.obj['flavor']) + self.flavor_action_controller.show(self.req, resp, '2') + self.assertEqual({'id': '0', 'os-flavor-access:is_public': False}, + resp.obj['flavor']) + + def test_detail(self): + resp = FakeResponse() + self.flavor_action_controller.detail(self.req, resp) + self.assertEqual([{'id': '0', 'os-flavor-access:is_public': True}, + {'id': '2', 'os-flavor-access:is_public': False}], + resp.obj['flavors']) + + def test_create(self): + resp = FakeResponse() + self.flavor_action_controller.create(self.req, {}, resp) + self.assertEqual({'id': '0', 'os-flavor-access:is_public': True}, + resp.obj['flavor']) + def test_add_tenant_access(self): def stub_add_instance_type_access(flavorid, projectid, ctxt=None): self.assertEqual('3', flavorid, "flavorid") diff --git a/nova/tests/api/openstack/compute/contrib/test_quantum_security_groups.py b/nova/tests/api/openstack/compute/contrib/test_quantum_security_groups.py index 98526bdad..94bc36b1f 100644 --- a/nova/tests/api/openstack/compute/contrib/test_quantum_security_groups.py +++ b/nova/tests/api/openstack/compute/contrib/test_quantum_security_groups.py @@ -31,6 +31,7 @@ import nova.db from nova import exception from nova.network import quantumv2 from nova.network.quantumv2 import api as quantum_api +from nova.network.security_group import quantum_driver from nova.openstack.common import jsonutils from nova import test from nova.tests.api.openstack.compute.contrib import test_security_groups @@ -129,7 +130,7 @@ class TestQuantumSecurityGroups( net = self._create_network() self._create_port( network_id=net['network']['id'], security_groups=[sg['id']], - device_id=test_security_groups.FAKE_UUID) + device_id=test_security_groups.FAKE_UUID1) expected = [{'rules': [], 'tenant_id': 'fake_tenant', 'id': sg['id'], 'name': 'test', 'description': 'test-description'}] self.stubs.Set(nova.db, 'instance_get', @@ -137,9 +138,9 @@ class TestQuantumSecurityGroups( self.stubs.Set(nova.db, 'instance_get_by_uuid', test_security_groups.return_server_by_uuid) req = fakes.HTTPRequest.blank('/v2/fake/servers/%s/os-security-groups' - % test_security_groups.FAKE_UUID) + % test_security_groups.FAKE_UUID1) res_dict = self.server_controller.index( - req, test_security_groups.FAKE_UUID)['security_groups'] + req, test_security_groups.FAKE_UUID1)['security_groups'] self.assertEquals(expected, res_dict) def test_get_security_group_by_id(self): @@ -191,7 +192,7 @@ class TestQuantumSecurityGroups( net = self._create_network() self._create_port( network_id=net['network']['id'], security_groups=[sg['id']], - device_id=test_security_groups.FAKE_UUID) + device_id=test_security_groups.FAKE_UUID1) self.stubs.Set(nova.db, 'instance_get', test_security_groups.return_server) @@ -228,7 +229,7 @@ class TestQuantumSecurityGroups( net = self._create_network() self._create_port( network_id=net['network']['id'], security_groups=[sg['id']], - device_id=test_security_groups.FAKE_UUID) + device_id=test_security_groups.FAKE_UUID1) self.stubs.Set(nova.db, 'instance_get', test_security_groups.return_server) @@ -239,6 +240,34 @@ class TestQuantumSecurityGroups( req = fakes.HTTPRequest.blank('/v2/fake/servers/1/action') self.manager._removeSecurityGroup(req, '1', body) + def test_get_instances_security_groups_bindings(self): + sg1 = self._create_sg_template(name='test1').get('security_group') + sg2 = self._create_sg_template(name='test2').get('security_group') + # test name='' is replaced with id + sg3 = self._create_sg_template(name='').get('security_group') + net = self._create_network() + self._create_port( + network_id=net['network']['id'], security_groups=[sg1['id'], + sg2['id']], + device_id=test_security_groups.FAKE_UUID1) + self._create_port( + network_id=net['network']['id'], security_groups=[sg2['id'], + sg3['id']], + device_id=test_security_groups.FAKE_UUID2) + expected = {test_security_groups.FAKE_UUID1: [{'name': sg1['name']}, + {'name': sg2['name']}], + test_security_groups.FAKE_UUID2: [{'name': sg2['name']}, + {'name': sg3['id']}]} + self.stubs.Set(nova.db, 'instance_get', + test_security_groups.return_server) + self.stubs.Set(nova.db, 'instance_get_by_uuid', + test_security_groups.return_server_by_uuid) + security_group_api = self.controller.security_group_api + bindings = ( + security_group_api.get_instances_security_groups_bindings( + context.get_admin_context())) + self.assertEquals(bindings, expected) + class TestQuantumSecurityGroupRulesTestCase(TestQuantumSecurityGroupsTestCase): def setUp(self): @@ -323,8 +352,14 @@ class TestQuantumSecurityGroupsOutputTest(TestQuantumSecurityGroupsTestCase): self.controller = security_groups.SecurityGroupController() self.stubs.Set(compute.api.API, 'get', test_security_groups.fake_compute_get) + self.stubs.Set(compute.api.API, 'get_all', + test_security_groups.fake_compute_get_all) self.stubs.Set(compute.api.API, 'create', test_security_groups.fake_compute_create) + self.stubs.Set(quantum_driver.SecurityGroupAPI, + 'get_instances_security_groups_bindings', + (test_security_groups. + fake_get_instances_security_groups_bindings)) self.flags( osapi_compute_extension=[ 'nova.api.openstack.compute.contrib.select_extensions'], @@ -371,6 +406,16 @@ class TestQuantumSecurityGroupsOutputTest(TestQuantumSecurityGroupsTestCase): name = 'fake-2-%s' % i self.assertEqual(group.get('name'), name) + def test_create_server_get_default_security_group(self): + url = '/v2/fake/servers' + image_uuid = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77' + server = dict(name='server_test', imageRef=image_uuid, flavorRef=2) + res = self._make_request(url, {'server': server}) + self.assertEqual(res.status_int, 202) + server = self._get_server(res.body) + group = self._get_groups(server)[0] + self.assertEquals(group.get('name'), 'default') + def test_show(self): url = '/v2/fake/servers' image_uuid = 'c905cedb-7281-47e4-8a62-f26bc5fc4c77' @@ -629,7 +674,6 @@ class MockClient(object): for port in self._fake_ports.values(): if device_id: if device_id == port['device_id']: - print port ret.append(port) else: ret.append(port) diff --git a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py index 8286661a0..c4f79118e 100644 --- a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py +++ b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py @@ -25,7 +25,7 @@ from nova.tests.api.openstack import fakes def quota_set(class_name): return {'quota_class_set': {'id': class_name, 'metadata_items': 128, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'instances': 10, + 'fixed_ips': -1, 'instances': 10, 'injected_files': 5, 'cores': 20, 'injected_file_content_bytes': 10240, 'security_groups': 10, @@ -45,7 +45,7 @@ class QuotaClassSetsTest(test.TestCase): 'cores': 20, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_path_bytes': 255, @@ -64,7 +64,7 @@ class QuotaClassSetsTest(test.TestCase): self.assertEqual(qs['cores'], 20) self.assertEqual(qs['ram'], 51200) self.assertEqual(qs['floating_ips'], 10) - self.assertEqual(qs['fixed_ips'], 10) + self.assertEqual(qs['fixed_ips'], -1) self.assertEqual(qs['metadata_items'], 128) self.assertEqual(qs['injected_files'], 5) self.assertEqual(qs['injected_file_path_bytes'], 255) @@ -90,7 +90,7 @@ class QuotaClassSetsTest(test.TestCase): def test_quotas_update_as_admin(self): body = {'quota_class_set': {'instances': 50, 'cores': 50, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'injected_file_path_bytes': 255, @@ -108,7 +108,7 @@ class QuotaClassSetsTest(test.TestCase): def test_quotas_update_as_user(self): body = {'quota_class_set': {'instances': 50, 'cores': 50, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'security_groups': 10, @@ -136,7 +136,7 @@ class QuotaTemplateXMLSerializerTest(test.TestCase): injected_file_content_bytes=20, ram=50, floating_ips=60, - fixed_ips=10, + fixed_ips=-1, instances=70, injected_files=80, security_groups=10, @@ -161,7 +161,7 @@ class QuotaTemplateXMLSerializerTest(test.TestCase): injected_file_content_bytes='20', ram='50', floating_ips='60', - fixed_ips='10', + fixed_ips='-1', instances='70', injected_files='80', security_groups='10', @@ -175,7 +175,7 @@ class QuotaTemplateXMLSerializerTest(test.TestCase): '</injected_file_content_bytes>' '<ram>50</ram>' '<floating_ips>60</floating_ips>' - '<fixed_ips>10</fixed_ips>' + '<fixed_ips>-1</fixed_ips>' '<instances>70</instances>' '<injected_files>80</injected_files>' '<cores>90</cores>' diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py index 1ff7e60ab..c95c41614 100644 --- a/nova/tests/api/openstack/compute/contrib/test_quotas.py +++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py @@ -26,7 +26,7 @@ from nova.tests.api.openstack import fakes def quota_set(id): return {'quota_set': {'id': id, 'metadata_items': 128, - 'ram': 51200, 'floating_ips': 10, 'fixed_ips': 10, + 'ram': 51200, 'floating_ips': 10, 'fixed_ips': -1, 'instances': 10, 'injected_files': 5, 'cores': 20, 'injected_file_content_bytes': 10240, 'security_groups': 10, 'security_group_rules': 20, @@ -45,7 +45,7 @@ class QuotaSetsTest(test.TestCase): 'cores': 20, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_path_bytes': 255, @@ -62,7 +62,7 @@ class QuotaSetsTest(test.TestCase): self.assertEqual(qs['cores'], 20) self.assertEqual(qs['ram'], 51200) self.assertEqual(qs['floating_ips'], 10) - self.assertEqual(qs['fixed_ips'], 10) + self.assertEqual(qs['fixed_ips'], -1) self.assertEqual(qs['metadata_items'], 128) self.assertEqual(qs['injected_files'], 5) self.assertEqual(qs['injected_file_path_bytes'], 255) @@ -83,7 +83,7 @@ class QuotaSetsTest(test.TestCase): 'cores': 20, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_path_bytes': 255, @@ -109,13 +109,13 @@ class QuotaSetsTest(test.TestCase): def test_quotas_update_as_admin(self): body = {'quota_set': {'instances': 50, 'cores': 50, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'injected_file_path_bytes': 255, 'security_groups': 10, 'security_group_rules': 20, - 'key_pairs': 100, 'fixed_ips': 10}} + 'key_pairs': 100, 'fixed_ips': -1}} req = fakes.HTTPRequest.blank('/v2/fake4/os-quota-sets/update_me', use_admin_context=True) @@ -126,7 +126,7 @@ class QuotaSetsTest(test.TestCase): def test_quotas_update_as_user(self): body = {'quota_set': {'instances': 50, 'cores': 50, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'security_groups': 10, @@ -163,7 +163,7 @@ class QuotaSetsTest(test.TestCase): expected_resp = {'quota_set': { 'instances': 50, 'cores': 50, 'ram': 51200, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'injected_file_path_bytes': 255, @@ -174,7 +174,7 @@ class QuotaSetsTest(test.TestCase): # when PUT JSON format with empty string for quota body = {'quota_set': {'instances': 50, 'cores': 50, 'ram': '', 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'injected_file_path_bytes': 255, @@ -189,7 +189,7 @@ class QuotaSetsTest(test.TestCase): # when PUT XML format with empty string for quota body = {'quota_set': {'instances': 50, 'cores': 50, 'ram': {}, 'floating_ips': 10, - 'fixed_ips': 10, 'metadata_items': 128, + 'fixed_ips': -1, 'metadata_items': 128, 'injected_files': 5, 'injected_file_content_bytes': 10240, 'injected_file_path_bytes': 255, @@ -216,7 +216,7 @@ class QuotaXMLSerializerTest(test.TestCase): injected_file_content_bytes=20, ram=50, floating_ips=60, - fixed_ips=10, + fixed_ips=-1, instances=70, injected_files=80, security_groups=10, @@ -240,7 +240,7 @@ class QuotaXMLSerializerTest(test.TestCase): injected_file_content_bytes='20', ram='50', floating_ips='60', - fixed_ips='10', + fixed_ips='-1', instances='70', injected_files='80', security_groups='10', @@ -254,7 +254,7 @@ class QuotaXMLSerializerTest(test.TestCase): '</injected_file_content_bytes>' '<ram>50</ram>' '<floating_ips>60</floating_ips>' - '<fixed_ips>10</fixed_ips>' + '<fixed_ips>-1</fixed_ips>' '<instances>70</instances>' '<injected_files>80</injected_files>' '<security_groups>10</security_groups>' diff --git a/nova/tests/api/openstack/compute/contrib/test_security_groups.py b/nova/tests/api/openstack/compute/contrib/test_security_groups.py index 6c7a8ae8c..480156b97 100644 --- a/nova/tests/api/openstack/compute/contrib/test_security_groups.py +++ b/nova/tests/api/openstack/compute/contrib/test_security_groups.py @@ -34,7 +34,8 @@ from nova.tests.api.openstack import fakes from nova.tests import utils CONF = cfg.CONF -FAKE_UUID = 'a47ae74e-ab08-447f-8eee-ffd43fc46c16' +FAKE_UUID1 = 'a47ae74e-ab08-447f-8eee-ffd43fc46c16' +FAKE_UUID2 = 'c6e6430a-6563-4efa-9542-5e93c9e97d18' class AttrDict(dict): @@ -81,7 +82,7 @@ def return_server(context, server_id): return {'id': int(server_id), 'power_state': 0x01, 'host': "localhost", - 'uuid': FAKE_UUID, + 'uuid': FAKE_UUID1, 'name': 'asdf'} @@ -95,12 +96,12 @@ def return_server_by_uuid(context, server_uuid): def return_non_running_server(context, server_id): return {'id': server_id, 'power_state': power_state.SHUTDOWN, - 'uuid': FAKE_UUID, 'host': "localhost", 'name': 'asdf'} + 'uuid': FAKE_UUID1, 'host': "localhost", 'name': 'asdf'} def return_security_group_by_name(context, project_id, group_name): return {'id': 1, 'name': group_name, - "instances": [{'id': 1, 'uuid': FAKE_UUID}]} + "instances": [{'id': 1, 'uuid': FAKE_UUID1}]} def return_security_group_without_instances(context, project_id, group_name): @@ -347,7 +348,7 @@ class TestSecurityGroups(test.TestCase): expected = {'security_groups': groups} def return_instance(context, server_id): - self.assertEquals(server_id, FAKE_UUID) + self.assertEquals(server_id, FAKE_UUID1) return return_server_by_uuid(context, server_id) self.stubs.Set(nova.db, 'instance_get_by_uuid', @@ -361,8 +362,8 @@ class TestSecurityGroups(test.TestCase): return_security_groups) req = fakes.HTTPRequest.blank('/v2/%s/servers/%s/os-security-groups' % - ('fake', FAKE_UUID)) - res_dict = self.server_controller.index(req, FAKE_UUID) + ('fake', FAKE_UUID1)) + res_dict = self.server_controller.index(req, FAKE_UUID1) self.assertEquals(res_dict, expected) @@ -1388,6 +1389,11 @@ def fake_compute_create(*args, **kwargs): return ([fake_compute_get()], '') +def fake_get_instances_security_groups_bindings(inst, context): + return {UUID1: [{'name': 'fake-0-0'}, {'name': 'fake-0-1'}], + UUID2: [{'name': 'fake-1-0'}, {'name': 'fake-1-1'}]} + + class SecurityGroupsOutputTest(test.TestCase): content_type = 'application/json' diff --git a/nova/tests/baremetal/db/utils.py b/nova/tests/baremetal/db/utils.py index e3a7b8489..74553f895 100644 --- a/nova/tests/baremetal/db/utils.py +++ b/nova/tests/baremetal/db/utils.py @@ -66,17 +66,3 @@ def new_bm_interface(**kwargs): raise test.TestingException("unknown field: %s" % ','.join(kwargs.keys())) return x - - -def new_bm_deployment(**kwargs): - x = bm_models.BareMetalDeployment() - x.id = kwargs.pop('id', None) - x.key = kwargs.pop('key', None) - x.image_path = kwargs.pop('image_path', None) - x.pxe_config_path = kwargs.pop('pxe_config_path', None) - x.root_mb = kwargs.pop('root_mb', None) - x.swap_mb = kwargs.pop('swap_mb', None) - if len(kwargs) > 0: - raise test.TestingException("unknown field: %s" - % ','.join(kwargs.keys())) - return x diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 3a1526522..097c87848 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -3654,7 +3654,7 @@ class ComputeTestCase(BaseTestCase): fake_migration_get_unconfirmed_by_dest_compute) self.stubs.Set(self.compute.conductor_api, 'migration_update', fake_migration_update) - self.stubs.Set(self.compute.compute_api, 'confirm_resize', + self.stubs.Set(self.compute.conductor_api, 'compute_confirm_resize', fake_confirm_resize) def fetch_instance_migration_status(instance_uuid): @@ -5552,6 +5552,7 @@ class ComputeAPITestCase(BaseTestCase): self.stubs.Set(rpc, 'cast', _fake_cast) self.flags(allow_resize_to_same_host=True) + self.flags(allow_migrate_to_same_host=True) instance = self._create_fake_instance(dict(host='host2')) instance = db.instance_get_by_uuid(self.context, instance['uuid']) @@ -7976,3 +7977,69 @@ class EvacuateHostTestCase(BaseTestCase): lambda x: True) self.assertRaises(exception.InstanceRecreateNotSupported, lambda: self._rebuild(on_shared_storage=True)) + + +class ComputeInjectedFilesTestCase(BaseTestCase): + # Test that running instances with injected_files decodes files correctly + + def setUp(self): + super(ComputeInjectedFilesTestCase, self).setUp() + self.instance = self._create_fake_instance() + self.stubs.Set(self.compute.driver, 'spawn', self._spawn) + + def _spawn(self, context, instance, image_meta, injected_files, + admin_password, nw_info, block_device_info): + self.assertEqual(self.expected, injected_files) + + def _test(self, injected_files, decoded_files): + self.expected = decoded_files + self.compute.run_instance(self.context, self.instance, + injected_files=injected_files) + + def test_injected_none(self): + # test an input of None for injected_files + self._test(None, []) + + def test_injected_empty(self): + # test an input of [] for injected_files + self._test([], []) + + def test_injected_success(self): + # test with valid b64 encoded content. + injected_files = [ + ('/a/b/c', base64.b64encode('foobarbaz')), + ('/d/e/f', base64.b64encode('seespotrun')), + ] + + decoded_files = [ + ('/a/b/c', 'foobarbaz'), + ('/d/e/f', 'seespotrun'), + ] + self._test(injected_files, decoded_files) + + def test_injected_invalid(self): + # test with invalid b64 encoded content + injected_files = [ + ('/a/b/c', base64.b64encode('foobarbaz')), + ('/d/e/f', 'seespotrun'), + ] + + self.assertRaises(exception.Base64Exception, self.compute.run_instance, + self.context, self.instance, injected_files=injected_files) + + def test_reschedule(self): + # test that rescheduling is done with original encoded files + expected = [ + ('/a/b/c', base64.b64encode('foobarbaz')), + ('/d/e/f', base64.b64encode('seespotrun')), + ] + + def _ror(context, instance, exc_info, requested_networks, + admin_password, injected_files, is_first_time, request_spec, + filter_properties, bdms=None): + self.assertEqual(expected, injected_files) + + self.stubs.Set(self.compute, '_reschedule_or_reraise', _ror) + + self.compute.run_instance(self.context, self.instance, + injected_files=expected) diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index df0f5e73b..1c675ec61 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -599,6 +599,16 @@ class _BaseTestCase(object): self.mox.ReplayAll() self.conductor.compute_stop(self.context, 'instance') + def test_compute_confirm_resize(self): + self.mox.StubOutWithMock(self.conductor_manager.compute_api, + 'confirm_resize') + self.conductor_manager.compute_api.confirm_resize(self.context, + 'instance', + 'migration') + self.mox.ReplayAll() + self.conductor.compute_confirm_resize(self.context, 'instance', + 'migration') + class ConductorTestCase(_BaseTestCase, test.TestCase): """Conductor Manager Tests.""" diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl index c393ab0c7..f9a94e760 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.json.tpl @@ -2,7 +2,7 @@ "quota_class_set": { "cores": 20, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "id": "%(set_id)s", "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl index 8ab8436d7..fb8e7992a 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-show-get-resp.xml.tpl @@ -2,7 +2,7 @@ <quota_class_set id="%(set_id)s"> <cores>20</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl index 3974f65db..483fda8c5 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.json.tpl @@ -4,7 +4,7 @@ "cores": 50, "ram": 51200, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "metadata_items": 128, "injected_files": 5, "injected_file_content_bytes": 10240, diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl index f27082ab3..150fb6a42 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-req.xml.tpl @@ -2,7 +2,7 @@ <quota_class_set> <cores>50</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl index 8d195b924..c36783f2f 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.json.tpl @@ -2,7 +2,7 @@ "quota_class_set": { "cores": 50, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, "injected_files": 5, @@ -13,4 +13,4 @@ "security_group_rules": 20, "security_groups": 10 } -}
\ No newline at end of file +} diff --git a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl index 5c12a81e7..cd674a24d 100644 --- a/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-class-sets/quota-classes-update-post-resp.xml.tpl @@ -2,7 +2,7 @@ <quota_class_set> <cores>50</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> @@ -12,4 +12,4 @@ <ram>51200</ram> <security_group_rules>20</security_group_rules> <security_groups>10</security_groups> -</quota_class_set>
\ No newline at end of file +</quota_class_set> diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json.tpl index 364a59f7a..2f0fd9857 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.json.tpl @@ -2,7 +2,7 @@ "quota_set": { "cores": 20, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "id": "fake_tenant", "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml.tpl index 36e6da544..f56987563 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-defaults-get-resp.xml.tpl @@ -2,7 +2,7 @@ <quota_set id="fake_tenant"> <cores>20</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.json.tpl index 364a59f7a..2f0fd9857 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.json.tpl @@ -2,7 +2,7 @@ "quota_set": { "cores": 20, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "id": "fake_tenant", "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.xml.tpl index 36e6da544..f56987563 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-show-get-resp.xml.tpl @@ -2,7 +2,7 @@ <quota_set id="fake_tenant"> <cores>20</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.json.tpl index 43525cfd5..34df1fe01 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.json.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.json.tpl @@ -2,7 +2,7 @@ "quota_set": { "cores": 20, "floating_ips": 10, - "fixed_ips": 10, + "fixed_ips": -1, "injected_file_content_bytes": 10240, "injected_file_path_bytes": 255, "injected_files": 5, diff --git a/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.xml.tpl index 3c411e8e5..91ac3a0dd 100644 --- a/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.xml.tpl +++ b/nova/tests/integrated/api_samples/os-quota-sets/quotas-update-post-resp.xml.tpl @@ -2,7 +2,7 @@ <quota_set> <cores>20</cores> <floating_ips>10</floating_ips> - <fixed_ips>10</fixed_ips> + <fixed_ips>-1</fixed_ips> <injected_file_content_bytes>10240</injected_file_content_bytes> <injected_file_path_bytes>255</injected_file_path_bytes> <injected_files>5</injected_files> diff --git a/nova/tests/network/test_linux_net.py b/nova/tests/network/test_linux_net.py index 53748ef25..4829f2d93 100644 --- a/nova/tests/network/test_linux_net.py +++ b/nova/tests/network/test_linux_net.py @@ -484,7 +484,6 @@ class LinuxNetworkTestCase(test.TestCase): 'dns1': '8.8.4.4', 'dhcp_start': '1.0.0.2', 'dhcp_server': '10.0.0.1'} - executes = [] def fake_execute(*args, **kwargs): executes.append(args) @@ -496,29 +495,37 @@ class LinuxNetworkTestCase(test.TestCase): self.stubs.Set(linux_net, 'write_to_file', lambda *a, **kw: None) self.stubs.Set(linux_net, '_dnsmasq_pid_for', lambda *a, **kw: None) dev = 'br100' - linux_net.restart_dhcp(self.context, dev, network_ref) - expected = ['env', - 'CONFIG_FILE=%s' % jsonutils.dumps(CONF.dhcpbridge_flagfile), - 'NETWORK_ID=fake', - 'dnsmasq', - '--strict-order', - '--bind-interfaces', - '--conf-file=%s' % CONF.dnsmasq_config_file, - '--domain=\'%s\'' % CONF.dhcp_domain, - '--pid-file=%s' % linux_net._dhcp_file(dev, 'pid'), - '--listen-address=%s' % network_ref['dhcp_server'], - '--except-interface=lo', - "--dhcp-range=set:%s,%s,static,%s,%ss" % (network_ref['label'], - network_ref['dhcp_start'], - network_ref['netmask'], - CONF.dhcp_lease_time), - '--dhcp-lease-max=256', - '--dhcp-hostsfile=%s' % linux_net._dhcp_file(dev, 'conf'), - '--dhcp-script=%s' % CONF.dhcpbridge, - '--leasefile-ro'] - if extra_expected: - expected += extra_expected - self.assertEqual([tuple(expected)], executes) + + default_domain = CONF.dhcp_domain + for domain in ('', default_domain): + executes = [] + CONF.dhcp_domain = domain + linux_net.restart_dhcp(self.context, dev, network_ref) + expected = ['env', + 'CONFIG_FILE=%s' % jsonutils.dumps(CONF.dhcpbridge_flagfile), + 'NETWORK_ID=fake', + 'dnsmasq', + '--strict-order', + '--bind-interfaces', + '--conf-file=%s' % CONF.dnsmasq_config_file, + '--pid-file=%s' % linux_net._dhcp_file(dev, 'pid'), + '--listen-address=%s' % network_ref['dhcp_server'], + '--except-interface=lo', + "--dhcp-range=set:%s,%s,static,%s,%ss" % (network_ref['label'], + network_ref['dhcp_start'], + network_ref['netmask'], + CONF.dhcp_lease_time), + '--dhcp-lease-max=256', + '--dhcp-hostsfile=%s' % linux_net._dhcp_file(dev, 'conf'), + '--dhcp-script=%s' % CONF.dhcpbridge, + '--leasefile-ro'] + + if CONF.dhcp_domain: + expected.append('--domain=%s' % CONF.dhcp_domain) + + if extra_expected: + expected += extra_expected + self.assertEqual([tuple(expected)], executes) def test_dnsmasq_execute(self): self._test_dnsmasq_execute() diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index c4ce649f0..f0d8e58a9 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -1309,11 +1309,12 @@ class CommonNetworkTestCase(test.TestCase): manager.db.network_get_all(ctxt).AndReturn([{'id': 1, 'cidr': '192.168.2.9/25'}]) self.mox.ReplayAll() - # ValueError: requested cidr (192.168.2.0/24) conflicts with - # existing smaller cidr + # CidrConflict: requested cidr (192.168.2.0/24) conflicts with + # existing smaller cidr args = (None, 'fake', '192.168.2.0/24', False, 1, 256, None, None, None, None, None) - self.assertRaises(ValueError, manager.create_networks, *args) + self.assertRaises(exception.CidrConflict, + manager.create_networks, *args) def test_validate_cidrs_split_smaller_cidr_in_use(self): manager = fake_network.FakeNetworkManager() @@ -1361,10 +1362,11 @@ class CommonNetworkTestCase(test.TestCase): self.mox.ReplayAll() args = (None, 'fake', '192.168.2.0/24', False, 3, 64, None, None, None, None, None) - # ValueError: Not enough subnets avail to satisfy requested num_ - # networks - some subnets in requested range already - # in use - self.assertRaises(ValueError, manager.create_networks, *args) + # CidrConflict: Not enough subnets avail to satisfy requested num_ + # networks - some subnets in requested range already + # in use + self.assertRaises(exception.CidrConflict, + manager.create_networks, *args) def test_validate_cidrs_one_in_use(self): manager = fake_network.FakeNetworkManager() @@ -1380,10 +1382,11 @@ class CommonNetworkTestCase(test.TestCase): manager.db.network_get_all(ctxt).AndReturn([{'id': 1, 'cidr': '192.168.0.0/24'}]) self.mox.ReplayAll() - # ValueError: cidr already in use + # CidrConflict: cidr already in use args = (None, 'fake', '192.168.0.0/24', False, 1, 256, None, None, None, None, None) - self.assertRaises(ValueError, manager.create_networks, *args) + self.assertRaises(exception.CidrConflict, + manager.create_networks, *args) def test_validate_cidrs_too_many(self): manager = fake_network.FakeNetworkManager() @@ -1411,9 +1414,10 @@ class CommonNetworkTestCase(test.TestCase): self.mox.ReplayAll() args = (None, 'fake', '192.168.0.0/24', False, 1, 256, None, None, None, None, None) - # ValueError: requested cidr (192.168.0.0/24) conflicts - # with existing supernet - self.assertRaises(ValueError, manager.create_networks, *args) + # CidrConflict: requested cidr (192.168.0.0/24) conflicts + # with existing supernet + self.assertRaises(exception.CidrConflict, + manager.create_networks, *args) def test_create_networks(self): cidr = '192.168.0.0/24' @@ -1433,7 +1437,8 @@ class CommonNetworkTestCase(test.TestCase): self.mox.ReplayAll() args = [None, 'foo', '192.168.0.0/24', None, 1, 256, 'fd00::/48', None, None, None, None, None] - self.assertRaises(ValueError, manager.create_networks, *args) + self.assertRaises(exception.CidrConflict, + manager.create_networks, *args) def test_create_networks_many(self): cidr = '192.168.0.0/16' diff --git a/nova/tests/test_metadata.py b/nova/tests/test_metadata.py index e695ab5fe..01f274f7c 100644 --- a/nova/tests/test_metadata.py +++ b/nova/tests/test_metadata.py @@ -25,6 +25,11 @@ import hmac import json import re +try: + import cPickle as pickle +except ImportError: + import pickle + from oslo.config import cfg import webob @@ -132,6 +137,12 @@ class MetadataTestCase(test.TestCase): fake_network.stub_out_nw_api_get_instance_nw_info(self.stubs, spectacular=True) + def test_can_pickle_metadata(self): + # Make sure that InstanceMetadata is possible to pickle. This is + # required for memcache backend to work correctly. + md = fake_InstanceMetadata(self.stubs, copy.copy(self.instance)) + pickle.dumps(md, protocol=0) + def test_user_data(self): inst = copy.copy(self.instance) inst['user_data'] = base64.b64encode("happy") diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index 49f9f3256..727746b18 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -366,7 +366,8 @@ class ProjectCommandsTestCase(test.TestCase): sys.stdout = sys.__stdout__ result = output.getvalue() - self.assertEquals(('instances: unlimited' in result), True) + print_format = "%-36s %-10s" % ('instances', 'unlimited') + self.assertEquals((print_format in result), True) def test_quota_update_invalid_key(self): self.assertRaises(SystemExit, diff --git a/tools/hacking.py b/tools/hacking.py index 4e2331054..94053991e 100755 --- a/tools/hacking.py +++ b/tools/hacking.py @@ -21,6 +21,7 @@ Built on top of pep8.py """ +import gettext import imp import inspect import logging @@ -643,6 +644,7 @@ imports_on_separate_lines_N301_compliant = r""" """ if __name__ == "__main__": + gettext.install('nova', unicode=1) #include nova path sys.path.append(os.getcwd()) #Run once tests (not per line) |