diff options
604 files changed, 5724 insertions, 2796 deletions
diff --git a/HACKING.rst b/HACKING.rst index 223f3ed7b..307d7477c 100644 --- a/HACKING.rst +++ b/HACKING.rst @@ -271,8 +271,8 @@ Commit Messages Using a common format for commit messages will help keep our git history readable. Follow these guidelines: - First, provide a brief summary (it is recommended to keep the commit title - under 50 chars). + First, provide a brief summary of 50 characters or less. Summaries + of greater then 72 characters will be rejected by the gate. The first line of the commit message should provide an accurate description of the change, not just a reference to a bug or diff --git a/README.rst b/README.rst index 43f6b9d51..8e50b4584 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,7 @@ OpenStack Nova README OpenStack Nova provides a cloud computing fabric controller, supporting a wide variety of virtualization technologies, -including KVM, Xen, LXC, VMWare, and more. In addition to +including KVM, Xen, LXC, VMware, and more. In addition to its native API, it includes compatibility with the commonly encountered Amazon EC2 and S3 APIs. diff --git a/bin/nova-all b/bin/nova-all index 5fb1748e8..ace305727 100755 --- a/bin/nova-all +++ b/bin/nova-all @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack, LLC +# Copyright 2011 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/bin/nova-baremetal-deploy-helper b/bin/nova-baremetal-deploy-helper index 0d2d21984..756305776 100755 --- a/bin/nova-baremetal-deploy-helper +++ b/bin/nova-baremetal-deploy-helper @@ -121,6 +121,7 @@ def dd(src, dst): 'if=%s' % src, 'of=%s' % dst, 'bs=1M', + 'oflag=direct', run_as_root=True, check_exit_code=[0]) diff --git a/bin/nova-cert b/bin/nova-cert index d309cc028..c6d9ddbad 100755 --- a/bin/nova-cert +++ b/bin/nova-cert @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack, LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/bin/nova-clear-rabbit-queues b/bin/nova-clear-rabbit-queues index 3e8b8e56d..32a7fe5d1 100755 --- a/bin/nova-clear-rabbit-queues +++ b/bin/nova-clear-rabbit-queues @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/bin/nova-console b/bin/nova-console index c567f28b1..6d6569104 100755 --- a/bin/nova-console +++ b/bin/nova-console @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/bin/nova-consoleauth b/bin/nova-consoleauth index 776ee9b35..0cbec669a 100755 --- a/bin/nova-consoleauth +++ b/bin/nova-consoleauth @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/bin/nova-dhcpbridge b/bin/nova-dhcpbridge index c00578821..1acaf4cd1 100755 --- a/bin/nova-dhcpbridge +++ b/bin/nova-dhcpbridge @@ -42,6 +42,7 @@ from nova import context from nova import db from nova.network import rpcapi as network_rpcapi from nova.openstack.common import importutils +from nova.openstack.common import jsonutils from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -121,7 +122,8 @@ def main(): except KeyError: config_file = os.environ['FLAGFILE'] - config.parse_args(sys.argv, default_config_files=[config_file]) + config.parse_args(sys.argv, + default_config_files=jsonutils.loads(config_file)) logging.setup("nova") diff --git a/bin/nova-manage b/bin/nova-manage index c4e9841ce..274ae4640 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -80,7 +80,7 @@ from nova import db from nova.db import migration from nova import exception from nova.openstack.common import cliutils -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.openstack.common import importutils from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -790,12 +790,15 @@ class DbCommands(object): @args('--max_rows', dest='max_rows', metavar='<number>', help='Maximum number of deleted rows to archive') - def archive_deleted_rows(self, max_rows=None): + def archive_deleted_rows(self, max_rows): """Move up to max_rows deleted rows from production tables to shadow tables. """ if max_rows is not None: max_rows = int(max_rows) + if max_rows < 0: + print _("Must supply a positive value for max_rows") + sys.exit(1) admin_context = context.get_admin_context() db.archive_deleted_rows(admin_context, max_rows) @@ -861,7 +864,7 @@ class InstanceTypeCommands(object): except exception.InstanceTypeNotFound: print _("Valid instance type name is required") sys.exit(1) - except db_session.DBError, e: + except db_exc.DBError, e: print _("DB Error: %s") % e sys.exit(2) except Exception: @@ -878,7 +881,7 @@ class InstanceTypeCommands(object): inst_types = instance_types.get_all_types() else: inst_types = instance_types.get_instance_type_by_name(name) - except db_session.DBError, e: + except db_exc.DBError, e: _db_error(e) if isinstance(inst_types.values()[0], dict): for k, v in inst_types.iteritems(): @@ -909,7 +912,7 @@ class InstanceTypeCommands(object): ext_spec) print _("Key %(key)s set to %(value)s on instance" " type %(name)s") % locals() - except db_session.DBError, e: + except db_exc.DBError, e: _db_error(e) @args('--name', dest='name', metavar='<name>', @@ -932,7 +935,7 @@ class InstanceTypeCommands(object): key) print _("Key %(key)s on instance type %(name)s unset") % locals() - except db_session.DBError, e: + except db_exc.DBError, e: _db_error(e) diff --git a/bin/nova-novncproxy b/bin/nova-novncproxy index 45f272ada..37486f6a4 100755 --- a/bin/nova-novncproxy +++ b/bin/nova-novncproxy @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/bin/nova-rootwrap b/bin/nova-rootwrap index 35e2f47f3..e42f383dc 100755 --- a/bin/nova-rootwrap +++ b/bin/nova-rootwrap @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/bin/nova-rpc-zmq-receiver b/bin/nova-rpc-zmq-receiver index 90b652b91..7995fbe80 100755 --- a/bin/nova-rpc-zmq-receiver +++ b/bin/nova-rpc-zmq-receiver @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -39,10 +39,10 @@ from nova.openstack.common.rpc import impl_zmq CONF = cfg.CONF CONF.register_opts(rpc.rpc_opts) CONF.register_opts(impl_zmq.zmq_opts) -CONF(sys.argv[1:], project='nova') def main(): + CONF(sys.argv[1:], project='nova') logging.setup("nova") with contextlib.closing(impl_zmq.ZmqProxy(CONF)) as reactor: diff --git a/bin/nova-spicehtml5proxy b/bin/nova-spicehtml5proxy index 23d250ca3..a4c97a73d 100755 --- a/bin/nova-spicehtml5proxy +++ b/bin/nova-spicehtml5proxy @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/bin/nova-xvpvncproxy b/bin/nova-xvpvncproxy index c24f41176..6ad61d0ba 100755 --- a/bin/nova-xvpvncproxy +++ b/bin/nova-xvpvncproxy @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/doc/api_samples/os-volumes/attach-volume-to-server-req.json b/doc/api_samples/os-volumes/attach-volume-to-server-req.json new file mode 100644 index 000000000..4062687fc --- /dev/null +++ b/doc/api_samples/os-volumes/attach-volume-to-server-req.json @@ -0,0 +1,6 @@ +{ + "volumeAttachment": { + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "device": "/dev/vdd" + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/attach-volume-to-server-req.xml b/doc/api_samples/os-volumes/attach-volume-to-server-req.xml new file mode 100644 index 000000000..eedfc329a --- /dev/null +++ b/doc/api_samples/os-volumes/attach-volume-to-server-req.xml @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<volumeAttachment volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803" device="/dev/vdd" />
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/attach-volume-to-server-resp.json b/doc/api_samples/os-volumes/attach-volume-to-server-resp.json new file mode 100644 index 000000000..2e512ac99 --- /dev/null +++ b/doc/api_samples/os-volumes/attach-volume-to-server-resp.json @@ -0,0 +1,8 @@ +{ + "volumeAttachment": { + "device": "/dev/vdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "0c92f3f6-c253-4c9b-bd43-e880a8d2eb0a", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/attach-volume-to-server-resp.xml b/doc/api_samples/os-volumes/attach-volume-to-server-resp.xml new file mode 100644 index 000000000..aaa85dd43 --- /dev/null +++ b/doc/api_samples/os-volumes/attach-volume-to-server-resp.xml @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachment device="/dev/vdd" serverId="20f0cb44-7b00-4019-a612-364777cd2931" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/list-volume-attachments-resp.json b/doc/api_samples/os-volumes/list-volume-attachments-resp.json new file mode 100644 index 000000000..9ae9b4a2a --- /dev/null +++ b/doc/api_samples/os-volumes/list-volume-attachments-resp.json @@ -0,0 +1,16 @@ +{ + "volumeAttachments": [ + { + "device": "/dev/sdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + }, + { + "device": "/dev/sdc", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "serverId": "4d8c3732-a248-40ed-bebc-539a6ffd25c0", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" + } + ] +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/list-volume-attachments-resp.xml b/doc/api_samples/os-volumes/list-volume-attachments-resp.xml new file mode 100644 index 000000000..7d70882c0 --- /dev/null +++ b/doc/api_samples/os-volumes/list-volume-attachments-resp.xml @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachments> + <volumeAttachment device="/dev/sdd" serverId="4335bab6-6086-4247-8274-8b8b048edaaa" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + <volumeAttachment device="/dev/sdc" serverId="4335bab6-6086-4247-8274-8b8b048edaaa" id="a26887c6-c47b-4654-abb5-dfadf7d3f804" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f804"/> +</volumeAttachments>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-detail-resp.json b/doc/api_samples/os-volumes/os-volumes-detail-resp.json new file mode 100644 index 000000000..95be0419e --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-detail-resp.json @@ -0,0 +1,24 @@ +{ + "volumes": [ + { + "attachments": [ + { + "device": "/", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "3912f2b4-c5ba-4aec-9165-872876fe202e", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "1999-01-01T01:01:01", + "displayDescription": "Volume Description", + "displayName": "Volume Name", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } + ] +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-detail-resp.xml b/doc/api_samples/os-volumes/os-volumes-detail-resp.xml new file mode 100644 index 000000000..b849c2d2e --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-detail-resp.xml @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumes> + <volume status="in-use" displayDescription="Volume Description" availabilityZone="zone1:host1" displayName="Volume Name" volumeType="Backup" snapshotId="None" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" createdAt="2008-12-01T11:01:55" size="100"> + <attachments> + <attachment device="/" serverId="3912f2b4-c5ba-4aec-9165-872876fe202e" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + </attachments> + <metadata/> + </volume> +</volumes>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-get-resp.json b/doc/api_samples/os-volumes/os-volumes-get-resp.json new file mode 100644 index 000000000..5c8429cb1 --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-get-resp.json @@ -0,0 +1,22 @@ +{ + "volume": { + "attachments": [ + { + "device": "/", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "3912f2b4-c5ba-4aec-9165-872876fe202e", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "2013-02-18T14:51:18.528085", + "displayDescription": "Volume Description", + "displayName": "Volume Name", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-get-resp.xml b/doc/api_samples/os-volumes/os-volumes-get-resp.xml new file mode 100644 index 000000000..1a516d5d2 --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-get-resp.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volume status="in-use" displayDescription="Volume Description" availabilityZone="zone1:host1" displayName="Volume Name" volumeType="Backup" snapshotId="None" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" createdAt="2008-12-01T11:01:55" size="100"> + <attachments> + <attachment device="/" serverId="3912f2b4-c5ba-4aec-9165-872876fe202e" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + </attachments> + <metadata/> +</volume>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-index-resp.json b/doc/api_samples/os-volumes/os-volumes-index-resp.json new file mode 100644 index 000000000..c0fa4b891 --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-index-resp.json @@ -0,0 +1,24 @@ +{ + "volumes": [ + { + "attachments": [ + { + "device": "/", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "3912f2b4-c5ba-4aec-9165-872876fe202e", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "2013-02-19T20:01:40.274897", + "displayDescription": "Volume Description", + "displayName": "Volume Name", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } + ] +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-index-resp.xml b/doc/api_samples/os-volumes/os-volumes-index-resp.xml new file mode 100644 index 000000000..b849c2d2e --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-index-resp.xml @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumes> + <volume status="in-use" displayDescription="Volume Description" availabilityZone="zone1:host1" displayName="Volume Name" volumeType="Backup" snapshotId="None" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" createdAt="2008-12-01T11:01:55" size="100"> + <attachments> + <attachment device="/" serverId="3912f2b4-c5ba-4aec-9165-872876fe202e" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + </attachments> + <metadata/> + </volume> +</volumes>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-post-req.json b/doc/api_samples/os-volumes/os-volumes-post-req.json new file mode 100644 index 000000000..c8b218adb --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-post-req.json @@ -0,0 +1,9 @@ +{ + "volume": + { + "availability_zone": "zone1:host1", + "display_name": "Volume Name", + "display_description": "Volume Description", + "size": 100 + } +} diff --git a/doc/api_samples/os-volumes/os-volumes-post-req.xml b/doc/api_samples/os-volumes/os-volumes-post-req.xml new file mode 100644 index 000000000..68a0b5864 --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-post-req.xml @@ -0,0 +1,3 @@ +<?xml version='1.0' encoding='UTF-8'?> + <volume displayDescription="Volume Description" availabilityZone="zone1:host1" displayName="Volume Name" size="100"/> + diff --git a/doc/api_samples/os-volumes/os-volumes-post-resp.json b/doc/api_samples/os-volumes/os-volumes-post-resp.json new file mode 100644 index 000000000..ba3795a0b --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-post-resp.json @@ -0,0 +1,22 @@ +{ + "volume": { + "attachments": [ + { + "device": "/", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "3912f2b4-c5ba-4aec-9165-872876fe202e", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "2013-02-18T14:51:17.970024", + "displayDescription": "Volume Description", + "displayName": "Volume Name", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/os-volumes-post-resp.xml b/doc/api_samples/os-volumes/os-volumes-post-resp.xml new file mode 100644 index 000000000..1a516d5d2 --- /dev/null +++ b/doc/api_samples/os-volumes/os-volumes-post-resp.xml @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volume status="in-use" displayDescription="Volume Description" availabilityZone="zone1:host1" displayName="Volume Name" volumeType="Backup" snapshotId="None" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" createdAt="2008-12-01T11:01:55" size="100"> + <attachments> + <attachment device="/" serverId="3912f2b4-c5ba-4aec-9165-872876fe202e" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + </attachments> + <metadata/> +</volume>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/server-post-req.json b/doc/api_samples/os-volumes/server-post-req.json new file mode 100644 index 000000000..d88eb4122 --- /dev/null +++ b/doc/api_samples/os-volumes/server-post-req.json @@ -0,0 +1,16 @@ +{ + "server" : { + "name" : "new-server-test", + "imageRef" : "http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b", + "flavorRef" : "http://openstack.example.com/openstack/flavors/1", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality" : [ + { + "path" : "/etc/banner.txt", + "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ] + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/server-post-req.xml b/doc/api_samples/os-volumes/server-post-req.xml new file mode 100644 index 000000000..0a3c8bb53 --- /dev/null +++ b/doc/api_samples/os-volumes/server-post-req.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="http://openstack.example.com/openstack/images/70a599e0-31e7-49b7-b260-868f441e862b" flavorRef="http://openstack.example.com/openstack/flavors/1" name="new-server-test"> + <metadata> + <meta key="My Server Name">Apache1</meta> + </metadata> + <personality> + <file path="/etc/banner.txt"> + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + </file> + </personality> +</server>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/server-post-resp.json b/doc/api_samples/os-volumes/server-post-resp.json new file mode 100644 index 000000000..6ae553403 --- /dev/null +++ b/doc/api_samples/os-volumes/server-post-resp.json @@ -0,0 +1,16 @@ +{ + "server": { + "adminPass": "8VqALQcVB9MT", + "id": "a80b9477-84c1-4242-9731-14a3c2a04241", + "links": [ + { + "href": "http://openstack.example.com/v2/openstack/servers/a80b9477-84c1-4242-9731-14a3c2a04241", + "rel": "self" + }, + { + "href": "http://openstack.example.com/openstack/servers/a80b9477-84c1-4242-9731-14a3c2a04241", + "rel": "bookmark" + } + ] + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/server-post-resp.xml b/doc/api_samples/os-volumes/server-post-resp.xml new file mode 100644 index 000000000..b2474027d --- /dev/null +++ b/doc/api_samples/os-volumes/server-post-resp.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="b11339a0-3a3e-496d-ade0-4539dbb5d816" adminPass="J3qyiuLMEWV3"> + <metadata/> + <atom:link href="http://openstack.example.com/v2/openstack/servers/b11339a0-3a3e-496d-ade0-4539dbb5d816" rel="self"/> + <atom:link href="http://openstack.example.com/openstack/servers/b11339a0-3a3e-496d-ade0-4539dbb5d816" rel="bookmark"/> +</server>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshot-create-req.json b/doc/api_samples/os-volumes/snapshot-create-req.json new file mode 100644 index 000000000..8ad5b3cb0 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshot-create-req.json @@ -0,0 +1,8 @@ +{ + "snapshot": { + "display_name": "snap-001", + "display_description": "Daily backup", + "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", + "force": false + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshot-create-req.xml b/doc/api_samples/os-volumes/snapshot-create-req.xml new file mode 100644 index 000000000..e5001cf06 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshot-create-req.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> + <snapshot> + <display_name>snap-001</display_name> + <display_description>Daily backup</display_description> + <volume_id>521752a6-acf6-4b2d-bc7a-119f9148cd8c</volume_id> + <force>false</force> + </snapshot>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshot-create-resp.json b/doc/api_samples/os-volumes/snapshot-create-resp.json new file mode 100644 index 000000000..1a14bea01 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshot-create-resp.json @@ -0,0 +1,32 @@ +{ + "snapshot": { + "createdAt": "2013-02-25T16:27:54.680544", + "displayDescription": "Daily backup", + "displayName": "snap-001", + "id": 100, + "size": 100, + "status": "available", + "volumeId": { + "attach_status": "attached", + "availability_zone": "fakeaz", + "created_at": "1999-01-01T01:01:01.000000", + "display_description": "displaydesc", + "display_name": "displayname", + "host": "fakehost", + "id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c", + "instance_uuid": "fakeuuid", + "mountpoint": "/", + "name": "vol name", + "project_id": "fakeproject", + "size": 1, + "snapshot_id": null, + "status": "fakestatus", + "user_id": "fakeuser", + "volume_metadata": [], + "volume_type": { + "name": "vol_type_name" + }, + "volume_type_id": "fakevoltype" + } + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshot-create-resp.xml b/doc/api_samples/os-volumes/snapshot-create-resp.xml new file mode 100644 index 000000000..ad815f723 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshot-create-resp.xml @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshot status="available" displayDescription="Daily backup" displayName="snap-001" volumeId="{'instance_uuid': 'fakeuuid', 'status': 'fakestatus', 'user_id': 'fakeuser', 'name': 'vol name', 'display_name': 'displayname', 'availability_zone': 'fakeaz', 'created_at': datetime.datetime(1999, 1, 1, 1, 1, 1), 'attach_status': 'attached', 'display_description': 'displaydesc', 'host': 'fakehost', 'volume_type_id': 'fakevoltype', 'volume_metadata': [], 'volume_type': {'name': 'vol_type_name'}, 'snapshot_id': None, 'mountpoint': '/', 'project_id': 'fakeproject', 'id': u'521752a6-acf6-4b2d-bc7a-119f9148cd8c', 'size': 1}" id="100" createdAt="2013-02-25 16:27:36.840121" size="100"/>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-detail-resp.json b/doc/api_samples/os-volumes/snapshots-detail-resp.json new file mode 100644 index 000000000..796e522c4 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-detail-resp.json @@ -0,0 +1,31 @@ +{ + "snapshots": [ + { + "createdAt": "2013-02-25T16:27:54.671372", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 100, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "2013-02-25T16:27:54.671378", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 101, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "2013-02-25T16:27:54.671381", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 102, + "size": 100, + "status": "available", + "volumeId": 12 + } + ] +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-detail-resp.xml b/doc/api_samples/os-volumes/snapshots-detail-resp.xml new file mode 100644 index 000000000..5e946939f --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-detail-resp.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshots> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="100" createdAt="2013-02-25 16:27:36.862459" size="100"/> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="101" createdAt="2013-02-25 16:27:36.862466" size="100"/> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="102" createdAt="2013-02-25 16:27:36.862469" size="100"/> +</snapshots>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-list-resp.json b/doc/api_samples/os-volumes/snapshots-list-resp.json new file mode 100644 index 000000000..9b7cb412a --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-list-resp.json @@ -0,0 +1,31 @@ +{ + "snapshots": [ + { + "createdAt": "2013-02-25T16:27:54.684999", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 100, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "2013-02-25T16:27:54.685005", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 101, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "2013-02-25T16:27:54.685008", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 102, + "size": 100, + "status": "available", + "volumeId": 12 + } + ] +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-list-resp.xml b/doc/api_samples/os-volumes/snapshots-list-resp.xml new file mode 100644 index 000000000..6714c98bc --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-list-resp.xml @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshots> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="100" createdAt="2013-02-25 16:27:36.769149" size="100"/> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="101" createdAt="2013-02-25 16:27:36.769154" size="100"/> + <snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="102" createdAt="2013-02-25 16:27:36.769157" size="100"/> +</snapshots>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-show-resp.json b/doc/api_samples/os-volumes/snapshots-show-resp.json new file mode 100644 index 000000000..d7b3f26e4 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-show-resp.json @@ -0,0 +1,11 @@ +{ + "snapshot": { + "createdAt": "2013-02-25T16:27:54.724209", + "displayDescription": "Default description", + "displayName": "Default name", + "id": "100", + "size": 100, + "status": "available", + "volumeId": 12 + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/snapshots-show-resp.xml b/doc/api_samples/os-volumes/snapshots-show-resp.xml new file mode 100644 index 000000000..3c70cf033 --- /dev/null +++ b/doc/api_samples/os-volumes/snapshots-show-resp.xml @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshot status="available" displayDescription="Default description" displayName="Default name" volumeId="12" id="100" createdAt="2013-02-25 16:27:36.854206" size="100"/>
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/volume-attachment-detail-resp.json b/doc/api_samples/os-volumes/volume-attachment-detail-resp.json new file mode 100644 index 000000000..5375033bb --- /dev/null +++ b/doc/api_samples/os-volumes/volume-attachment-detail-resp.json @@ -0,0 +1,8 @@ +{ + "volumeAttachment": { + "device": "/dev/sdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "2390fb4d-1693-45d7-b309-e29c4af16538", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } +}
\ No newline at end of file diff --git a/doc/api_samples/os-volumes/volume-attachment-detail-resp.xml b/doc/api_samples/os-volumes/volume-attachment-detail-resp.xml new file mode 100644 index 000000000..dea235292 --- /dev/null +++ b/doc/api_samples/os-volumes/volume-attachment-detail-resp.xml @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachment device="/dev/sdd" serverId="20f12907-3993-44f7-a680-d51e2ceedbd9" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/>
\ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index 9af5f5494..4fa13e045 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -58,7 +58,7 @@ master_doc = 'index' # General information about the project. project = u'nova' -copyright = u'2010-present, OpenStack, LLC' +copyright = u'2010-present, OpenStack Foundation' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/doc/source/devref/addmethod.openstackapi.rst b/doc/source/devref/addmethod.openstackapi.rst index 18123f8cc..fe6b77c87 100644 --- a/doc/source/devref/addmethod.openstackapi.rst +++ b/doc/source/devref/addmethod.openstackapi.rst @@ -1,5 +1,5 @@ .. - Copyright 2010-2011 OpenStack LLC + Copyright 2010-2011 OpenStack Foundation All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/doc/source/devref/aggregates.rst b/doc/source/devref/aggregates.rst index ecc6329ba..7e854e6ae 100644 --- a/doc/source/devref/aggregates.rst +++ b/doc/source/devref/aggregates.rst @@ -1,5 +1,5 @@ .. - Copyright 2012 OpenStack, LLC + Copyright 2012 OpenStack Foundation Copyright 2012 Citrix Systems, Inc. Copyright 2012, The Cloudscaling Group, Inc. All Rights Reserved. diff --git a/doc/source/man/nova-all.rst b/doc/source/man/nova-all.rst index 4cb0b21c5..05bf128a1 100644 --- a/doc/source/man/nova-all.rst +++ b/doc/source/man/nova-all.rst @@ -8,7 +8,7 @@ Server for all Nova services :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-api-ec2.rst b/doc/source/man/nova-api-ec2.rst index ce3126480..209809cd9 100644 --- a/doc/source/man/nova-api-ec2.rst +++ b/doc/source/man/nova-api-ec2.rst @@ -8,7 +8,7 @@ Server for the Nova EC2 API :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-api-metadata.rst b/doc/source/man/nova-api-metadata.rst index 6c5a0d8f8..281f279a2 100644 --- a/doc/source/man/nova-api-metadata.rst +++ b/doc/source/man/nova-api-metadata.rst @@ -8,7 +8,7 @@ Server for the Nova Metadata API :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-api-os-compute.rst b/doc/source/man/nova-api-os-compute.rst index 4819285c0..f4fac477e 100644 --- a/doc/source/man/nova-api-os-compute.rst +++ b/doc/source/man/nova-api-os-compute.rst @@ -8,7 +8,7 @@ Server for the Nova OpenStack Compute APIs :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-api.rst b/doc/source/man/nova-api.rst index fe378f721..247b10cae 100644 --- a/doc/source/man/nova-api.rst +++ b/doc/source/man/nova-api.rst @@ -8,7 +8,7 @@ Server for the Nova EC2 and OpenStack APIs :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-baremetal-deploy-helper.rst b/doc/source/man/nova-baremetal-deploy-helper.rst index 106cb85e7..4ba3830f6 100644 --- a/doc/source/man/nova-baremetal-deploy-helper.rst +++ b/doc/source/man/nova-baremetal-deploy-helper.rst @@ -8,7 +8,7 @@ Writes images to a bare-metal node and switch it to instance-mode :Author: openstack@lists.launchpad.net :Date: 2012-10-17 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2013.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-baremetal-manage.rst b/doc/source/man/nova-baremetal-manage.rst index 1fab368e5..10de08dfc 100644 --- a/doc/source/man/nova-baremetal-manage.rst +++ b/doc/source/man/nova-baremetal-manage.rst @@ -8,7 +8,7 @@ Manage bare-metal DB in OpenStack Nova :Author: openstack@lists.launchpad.net :Date: 2012-10-17 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2013.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-cert.rst b/doc/source/man/nova-cert.rst index f8c6d0c2d..f7a5c72ef 100644 --- a/doc/source/man/nova-cert.rst +++ b/doc/source/man/nova-cert.rst @@ -8,7 +8,7 @@ Server for the Nova Cert :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-compute.rst b/doc/source/man/nova-compute.rst index 97a4b447b..9dd100c98 100644 --- a/doc/source/man/nova-compute.rst +++ b/doc/source/man/nova-compute.rst @@ -8,7 +8,7 @@ Nova Compute Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-conductor.rst b/doc/source/man/nova-conductor.rst index 7a32730e1..2b98d62c2 100644 --- a/doc/source/man/nova-conductor.rst +++ b/doc/source/man/nova-conductor.rst @@ -8,7 +8,7 @@ Server for the Nova Conductor :Author: openstack@lists.launchpad.net :Date: 2012-11-16 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-console.rst b/doc/source/man/nova-console.rst index 60d910b0e..895edf867 100644 --- a/doc/source/man/nova-console.rst +++ b/doc/source/man/nova-console.rst @@ -8,7 +8,7 @@ Nova Console Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-consoleauth.rst b/doc/source/man/nova-consoleauth.rst index fe0cf1bcf..11f6d7712 100644 --- a/doc/source/man/nova-consoleauth.rst +++ b/doc/source/man/nova-consoleauth.rst @@ -8,7 +8,7 @@ Nova Console Authentication Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-dhcpbridge.rst b/doc/source/man/nova-dhcpbridge.rst index 3405a9c4e..63faaf35d 100644 --- a/doc/source/man/nova-dhcpbridge.rst +++ b/doc/source/man/nova-dhcpbridge.rst @@ -8,7 +8,7 @@ Handles Lease Database updates from DHCP servers :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-manage.rst b/doc/source/man/nova-manage.rst index a3a742af9..1800a4875 100644 --- a/doc/source/man/nova-manage.rst +++ b/doc/source/man/nova-manage.rst @@ -8,7 +8,7 @@ control and manage cloud computer instances and images :Author: openstack@lists.launchpad.net :Date: 2012-04-05 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-network.rst b/doc/source/man/nova-network.rst index 1073a6834..42e017534 100644 --- a/doc/source/man/nova-network.rst +++ b/doc/source/man/nova-network.rst @@ -8,7 +8,7 @@ Nova Network Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-novncproxy.rst b/doc/source/man/nova-novncproxy.rst index 5302fd063..a7068e8c4 100644 --- a/doc/source/man/nova-novncproxy.rst +++ b/doc/source/man/nova-novncproxy.rst @@ -8,7 +8,7 @@ Websocket novnc Proxy for OpenStack Nova noVNC consoles. :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-objectstore.rst b/doc/source/man/nova-objectstore.rst index c4bc16d3e..70c7dde1f 100644 --- a/doc/source/man/nova-objectstore.rst +++ b/doc/source/man/nova-objectstore.rst @@ -8,7 +8,7 @@ Nova Objectstore Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-rootwrap.rst b/doc/source/man/nova-rootwrap.rst index 8bc089a35..d8050d094 100644 --- a/doc/source/man/nova-rootwrap.rst +++ b/doc/source/man/nova-rootwrap.rst @@ -8,7 +8,7 @@ Root wrapper for Nova :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-rpc-zmq-receiver.rst b/doc/source/man/nova-rpc-zmq-receiver.rst index c42afae6d..72ed6a76e 100644 --- a/doc/source/man/nova-rpc-zmq-receiver.rst +++ b/doc/source/man/nova-rpc-zmq-receiver.rst @@ -8,7 +8,7 @@ Receiver for 0MQ based nova RPC :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-scheduler.rst b/doc/source/man/nova-scheduler.rst index b125352a0..1d8b9c995 100644 --- a/doc/source/man/nova-scheduler.rst +++ b/doc/source/man/nova-scheduler.rst @@ -8,7 +8,7 @@ Nova Scheduler :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-spicehtml5proxy.rst b/doc/source/man/nova-spicehtml5proxy.rst index 4d0aaa202..0d06b6eb1 100644 --- a/doc/source/man/nova-spicehtml5proxy.rst +++ b/doc/source/man/nova-spicehtml5proxy.rst @@ -8,7 +8,7 @@ Websocket Proxy for OpenStack Nova SPICE HTML5 consoles. :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/doc/source/man/nova-xvpvncproxy.rst b/doc/source/man/nova-xvpvncproxy.rst index e6f8904e7..7c624f6ad 100644 --- a/doc/source/man/nova-xvpvncproxy.rst +++ b/doc/source/man/nova-xvpvncproxy.rst @@ -8,7 +8,7 @@ XVP VNC Console Proxy Server :Author: openstack@lists.launchpad.net :Date: 2012-09-27 -:Copyright: OpenStack LLC +:Copyright: OpenStack Foundation :Version: 2012.1 :Manual section: 1 :Manual group: cloud computing diff --git a/etc/nova/nova.conf.sample b/etc/nova/nova.conf.sample index 9cbb8c1a5..ed989ce86 100644 --- a/etc/nova/nova.conf.sample +++ b/etc/nova/nova.conf.sample @@ -577,12 +577,14 @@ # a raw disk image instead (string value) #null_kernel=nokernel -# The full class name of the security group handler class -# (string value) -#security_group_handler=nova.network.sg.NullSecurityGroupHandler - -# The full class name of the security API class (string value) -#security_group_api=nova.compute.api.SecurityGroupAPI +# When creating multiple instances with a single request using +# the os-multiple-create API extension, this template will be +# used to build the display name for each instance. The +# benefit is that the instances end up with different +# hostnames. To restore legacy behavior of every instance +# having the same name, set this option to "%(name)s". Valid +# keys for the template are: name, uuid, count. (string value) +#multi_instance_display_name_template=%(name)s-%(uuid)s # @@ -781,9 +783,6 @@ # Options defined in nova.db.api # -# The backend to use for db (string value) -#db_backend=sqlalchemy - # Services to be added to the available pool on create # (boolean value) #enable_new_services=true @@ -970,7 +969,7 @@ # Options defined in nova.network.linux_net # -# location of flagfile for dhcpbridge (string value) +# location of flagfiles for dhcpbridge (multi valued) #dhcpbridge_flagfile=/etc/nova/nova-dhcpbridge.conf # Location to keep network config files (string value) @@ -991,12 +990,22 @@ # Lifetime of a DHCP lease in seconds (integer value) #dhcp_lease_time=120 -# if set, uses specific dns server for dnsmasq (string value) -#dns_server=<None> +# if set, uses specific dns server for dnsmasq. Canbe +# specified multiple times. (multi valued) +#dns_server= + +# if set, uses the dns1 and dns2 from the network ref.as dns +# servers. (boolean value) +#use_network_dns_servers=false # A list of dmz range that should be accepted (list value) #dmz_cidr= +# Traffic to this range will always be snatted to the fallback +# ip, even if it would normally be bridged out of the node. +# Can be specified multiple times. (multi valued) +#force_snat_range= + # Override the default dnsmasq settings with this file (string # value) #dnsmasq_config_file= @@ -1029,6 +1038,14 @@ # the port for the metadata api port (integer value) #metadata_port=8775 +# Regular expression to match iptables rule that shouldalways +# be on the top. (string value) +#iptables_top_regex= + +# Regular expression to match iptables rule that shouldalways +# be on the bottom. (string value) +#iptables_bottom_regex= + # # Options defined in nova.network.manager @@ -1157,6 +1174,9 @@ # value) #quantum_admin_auth_url=http://localhost:5000/v2.0 +# if set, ignore any SSL validation issues (boolean value) +#quantum_api_insecure=false + # auth strategy for connecting to quantum in admin context # (string value) #quantum_auth_strategy=keystone @@ -1165,6 +1185,10 @@ # value) #quantum_ovs_bridge=br-int +# Number of seconds before querying quantum for extensions +# (integer value) +#quantum_extension_sync_interval=600 + # # Options defined in nova.network.rpcapi @@ -1180,6 +1204,63 @@ # +# Options defined in nova.network.security_group.openstack_driver +# + +# The full class name of the security API class (string value) +#security_group_api=nova + +# The full class name of the security group handler class +# (string value) +#security_group_handler=nova.network.sg.NullSecurityGroupHandler + + +# +# Options defined in bin.nova-clear-rabbit-queues +# + +# Queues to delete (multi valued) +#queues= + +# delete nova exchange too. (boolean value) +#delete_exchange=false + + +# +# Options defined in bin.nova-novncproxy +# + +# Record sessions to FILE.[session_number] (boolean value) +#record=false + +# Become a daemon (background process) (boolean value) +#daemon=false + +# Disallow non-encrypted connections (boolean value) +#ssl_only=false + +# Source is ipv6 (boolean value) +#source_is_ipv6=false + +# SSL certificate file (string value) +#cert=self.pem + +# SSL key file (if separate from cert) (string value) +#key=<None> + +# Run webserver on same port. Serve files from DIR. (string +# value) +#web=/usr/share/novnc + +# Host on which to listen for incoming requests (string value) +#novncproxy_host=0.0.0.0 + +# Port on which to listen for incoming requests (integer +# value) +#novncproxy_port=6080 + + +# # Options defined in nova.objectstore.s3server # @@ -1194,12 +1275,24 @@ # +# Options defined in nova.openstack.common.db.api +# + +# The backend to use for db (string value) +#db_backend=sqlalchemy + +# Enable the experimental use of thread pooling for all DB API +# calls (boolean value) +#dbapi_use_tpool=false + + +# # Options defined in nova.openstack.common.db.sqlalchemy.session # # The SQLAlchemy connection string used to connect to the # database (string value) -#sql_connection=sqlite:////home/markmc/git/openstack/nova/nova/openstack/common/db/$sqlite_db +#sql_connection=sqlite:////nova/openstack/common/db/$sqlite_db # the filename to use with sqlite (string value) #sqlite_db=nova.sqlite @@ -1239,10 +1332,6 @@ # value) #sql_connection_trace=false -# enable the use of eventlet's db_pool for MySQL (boolean -# value) -#sql_dbpool_enable=false - # # Options defined in nova.openstack.common.eventlet_backdoor @@ -1259,8 +1348,9 @@ # Whether to disable inter-process locks (boolean value) #disable_process_locking=false -# Directory to use for lock files (string value) -#lock_path=/usr/lib/python/site-packages/nova/openstack +# Directory to use for lock files. Default to a temp directory +# (string value) +#lock_path=<None> # @@ -1352,6 +1442,7 @@ # Driver or drivers to handle sending notifications (multi # valued) +#notification_driver= # Default notification level for outgoing notifications # (string value) @@ -1405,6 +1496,15 @@ # +# Options defined in nova.openstack.common.rpc.amqp +# + +# Enable a fast single reply queue if using AMQP based RPC +# like RabbitMQ or Qpid. (boolean value) +#amqp_rpc_single_reply_queue=false + + +# # Options defined in nova.openstack.common.rpc.impl_kombu # @@ -1519,6 +1619,10 @@ # Number of ZeroMQ contexts, defaults to 1 (integer value) #rpc_zmq_contexts=1 +# Maximum number of ingress messages to locally buffer per +# topic. Default is unlimited. (integer value) +#rpc_zmq_topic_backlog=<None> + # Directory for holding IPC sockets (string value) #rpc_zmq_ipc_dir=/var/run/openstack @@ -1549,6 +1653,19 @@ # +# Options defined in nova.scheduler.filter_scheduler +# + +# New instances will be scheduled on a host chosen randomly +# from a subset of the N best hosts. This property defines the +# subset size that a host is chosen from. A value of 1 chooses +# the first host returned by the weighing functions. This +# value must be at least 1. Any value less than 1 will be +# ignored, and 1 will be used instead (integer value) +#scheduler_host_subset_size=1 + + +# # Options defined in nova.scheduler.filters.core_filter # @@ -1751,6 +1868,11 @@ # with on creation. (string value) #default_ephemeral_format=<None> +# VM image preallocation mode: "none" => no storage +# provisioning is done up front, "space" => storage is fully +# allocated at instance start (string value) +#preallocate_images=none + # Whether to use cow images (boolean value) #use_cow_images=true @@ -1850,9 +1972,9 @@ # Inject the ssh public key at boot time (boolean value) #libvirt_inject_key=true -# The partition to inject to : -1 => inspect (libguestfs -# only), 0 => not partitioned, >0 => partition number (integer -# value) +# The partition to inject to : -2 => disable, -1 => inspect +# (libguestfs only), 0 => not partitioned, >0 => partition +# number (integer value) #libvirt_inject_partition=1 # Sync virtual and real mouse cursors in Windows VMs (boolean @@ -1881,7 +2003,7 @@ #libvirt_vif_driver=nova.virt.libvirt.vif.LibvirtGenericVIFDriver # Libvirt handlers for remote volumes. (list value) -#libvirt_volume_drivers=iscsi=nova.virt.libvirt.volume.LibvirtISCSIVolumeDriver,local=nova.virt.libvirt.volume.LibvirtVolumeDriver,fake=nova.virt.libvirt.volume.LibvirtFakeVolumeDriver,rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver,sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver,nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver +#libvirt_volume_drivers=iscsi=nova.virt.libvirt.volume.LibvirtISCSIVolumeDriver,local=nova.virt.libvirt.volume.LibvirtVolumeDriver,fake=nova.virt.libvirt.volume.LibvirtFakeVolumeDriver,rbd=nova.virt.libvirt.volume.LibvirtNetVolumeDriver,sheepdog=nova.virt.libvirt.volume.LibvirtNetVolumeDriver,nfs=nova.virt.libvirt.volume.LibvirtNFSVolumeDriver,aoe=nova.virt.libvirt.volume.LibvirtAOEVolumeDriver,glusterfs=nova.virt.libvirt.volume.LibvirtGlusterfsVolumeDriver,fibre_channel=nova.virt.libvirt.volume.LibvirtFibreChannelVolumeDriver,scality=nova.virt.libvirt.volume.LibvirtScalityVolumeDriver # Override the default disk prefix for the devices attached to # a server, which is dependent on libvirt_type. (valid options @@ -1919,6 +2041,10 @@ # Location where the Xen hvmloader is kept (string value) #xen_hvmloader_path=/usr/lib/xen/boot/hvmloader +# Specific cachemodes to use for different disk types e.g: +# ["file=directsync","block=none"] (list value) +#disk_cachemodes= + # # Options defined in nova.virt.libvirt.imagebackend @@ -1937,6 +2063,10 @@ # flag is set to True. (boolean value) #libvirt_sparse_logical_volumes=false +# The amount of storage (in megabytes) to allocate for LVM +# snapshot copy-on-write blocks. (integer value) +#libvirt_lvm_snapshot_size=1000 + # # Options defined in nova.virt.libvirt.imagecache @@ -1954,6 +2084,12 @@ # Should unused base images be removed? (boolean value) #remove_unused_base_images=true +# Should unused kernel images be removed? This is only safe to +# enable if all compute nodes have been updated to support +# this option. This will enabled by default in future. +# (boolean value) +#remove_unused_kernels=false + # Unused resized base images younger than this will not be # removed (integer value) #remove_unused_resized_minimum_age_seconds=3600 @@ -2015,6 +2151,24 @@ # nfs man page for details (string value) #nfs_mount_options=<None> +# number of times to rediscover AoE target to find volume +# (integer value) +#num_aoe_discover_tries=3 + +# Dir where the glusterfs volume is mounted on the compute +# node (string value) +#glusterfs_mount_point_base=$state_path/mnt + +# use multipath connection of the iSCSI volume (boolean value) +#libvirt_iscsi_use_multipath=false + +# Path or URL to Scality SOFS configuration file (string +# value) +#scality_sofs_config=<None> + +# Base dir where Scality SOFS shall be mounted (string value) +#scality_sofs_mount_point=$state_path/scality + # # Options defined in nova.virt.powervm.driver @@ -2032,11 +2186,14 @@ # PowerVM manager user password (string value) #powervm_mgr_passwd=<None> -# PowerVM image remote path (string value) -#powervm_img_remote_path=<None> +# PowerVM image remote path where images will be moved. Make +# sure this path can fit your biggest image in glance (string +# value) +#powervm_img_remote_path=/home/padmin -# Local directory to download glance images to (string value) -#powervm_img_local_path=<None> +# Local directory to download glance images to. Make sure this +# path can fit your biggest image in glance (string value) +#powervm_img_local_path=/tmp # @@ -2371,6 +2528,24 @@ # value) #cinder_api_insecure=false +# Allow attach between instance and volume in different +# availability zones. (boolean value) +#cinder_cross_az_attach=true + + +[HYPERV] + +# +# Options defined in nova.virt.hyperv.pathutils +# + +# The name of a Windows share name mapped to the +# "instances_path" dir and used by the resize feature to copy +# files to the target host. If left blank, an administrative +# share will be used, looking for the same "instances_path" +# used locally (string value) +#instances_path_share= + [conductor] @@ -2474,6 +2649,28 @@ #db_check_interval=60 +[zookeeper] + +# +# Options defined in nova.servicegroup.drivers.zk +# + +# The ZooKeeper addresses for servicegroup service in the +# format of host1:port,host2:port,host3:port (string value) +#address=<None> + +# recv_timeout parameter for the zk session (integer value) +#recv_timeout=4000 + +# The prefix used in ZooKeeper to store ephemeral nodes +# (string value) +#sg_prefix=/servicegroups + +# Number of seconds to wait until retrying to join the session +# (integer value) +#sg_retry_interval=5 + + [baremetal] # @@ -2567,6 +2764,28 @@ # Template file for PXE configuration (string value) #pxe_config_template=$pybasedir/nova/virt/baremetal/pxe_config.template +# Timeout for PXE deployments. Default: 0 (unlimited) (integer +# value) +#pxe_deploy_timeout=0 + + +# +# Options defined in nova.virt.baremetal.virtual_power_driver +# + +# ip or name to virtual power host (string value) +#virtual_power_ssh_host= + +# base command to use for virtual power(vbox,virsh) (string +# value) +#virtual_power_type=vbox + +# user to execute virtual power commands as (string value) +#virtual_power_host_user= + +# password for virtual power host_user (string value) +#virtual_power_host_pass= + # # Options defined in nova.virt.baremetal.volume_driver @@ -2656,4 +2875,4 @@ #keymap=en-us -# Total option count: 543 +# Total option count: 584 diff --git a/nova/api/auth.py b/nova/api/auth.py index 04bb34066..cc8264567 100644 --- a/nova/api/auth.py +++ b/nova/api/auth.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/ec2/__init__.py b/nova/api/ec2/__init__.py index 397190fae..7ce18685b 100644 --- a/nova/api/ec2/__init__.py +++ b/nova/api/ec2/__init__.py @@ -32,12 +32,12 @@ from nova.api.ec2 import apirequest from nova.api.ec2 import ec2utils from nova.api.ec2 import faults from nova.api import validator -from nova.common import memorycache from nova import context from nova import exception from nova.openstack.common import importutils from nova.openstack.common import jsonutils from nova.openstack.common import log as logging +from nova.openstack.common import memorycache from nova.openstack.common import timeutils from nova import utils from nova import wsgi @@ -442,7 +442,7 @@ class Validator(wsgi.Middleware): 'image_id': validator.validate_ec2_id, 'attribute': validator.validate_str(), 'image_location': validator.validate_image_path, - 'public_ip': validator.validate_ipv4, + 'public_ip': utils.is_valid_ipv4, 'region_name': validator.validate_str(), 'group_name': validator.validate_str(max_length=255), 'group_description': validator.validate_str(max_length=255), diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index dcbde3428..6bc5185bf 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -503,9 +503,17 @@ class CloudController(object): r['groups'] = [] r['ipRanges'] = [] if rule['group_id']: - source_group = rule['grantee_group'] - r['groups'] += [{'groupName': source_group['name'], - 'userId': source_group['project_id']}] + if rule.get('grantee_group'): + source_group = rule['grantee_group'] + r['groups'] += [{'groupName': source_group['name'], + 'userId': source_group['project_id']}] + else: + # rule is not always joined with grantee_group + # for example when using quantum driver. + source_group = self.security_group_api.get( + context, id=rule['group_id']) + r['groups'] += [{'groupName': source_group.get('name'), + 'userId': source_group.get('project_id')}] if rule['protocol']: r['ipProtocol'] = rule['protocol'].lower() r['fromPort'] = rule['from_port'] @@ -1692,13 +1700,13 @@ class EC2SecurityGroupExceptions(object): pass -class CloudSecurityGroupNovaAPI(compute_api.SecurityGroupAPI, - EC2SecurityGroupExceptions): +class CloudSecurityGroupNovaAPI(EC2SecurityGroupExceptions, + compute_api.SecurityGroupAPI): pass -class CloudSecurityGroupQuantumAPI(quantum_driver.SecurityGroupAPI, - EC2SecurityGroupExceptions): +class CloudSecurityGroupQuantumAPI(EC2SecurityGroupExceptions, + quantum_driver.SecurityGroupAPI): pass diff --git a/nova/api/metadata/__init__.py b/nova/api/metadata/__init__.py index cf0e1e320..f3d0c88ac 100644 --- a/nova/api/metadata/__init__.py +++ b/nova/api/metadata/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack, LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/metadata/handler.py b/nova/api/metadata/handler.py index 7cccbc324..bbaeba524 100644 --- a/nova/api/metadata/handler.py +++ b/nova/api/metadata/handler.py @@ -26,10 +26,10 @@ import webob.dec import webob.exc from nova.api.metadata import base -from nova.common import memorycache from nova import conductor from nova import exception from nova.openstack.common import log as logging +from nova.openstack.common import memorycache from nova import wsgi CACHE_EXPIRATION = 15 # in seconds diff --git a/nova/api/openstack/auth.py b/nova/api/openstack/auth.py index 979aa74b6..67d77f5a6 100644 --- a/nova/api/openstack/auth.py +++ b/nova/api/openstack/auth.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/common.py b/nova/api/openstack/common.py index 8b880720b..c6473a648 100644 --- a/nova/api/openstack/common.py +++ b/nova/api/openstack/common.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/consoles.py b/nova/api/openstack/compute/consoles.py index 613a375f2..f9c30943a 100644 --- a/nova/api/openstack/compute/consoles.py +++ b/nova/api/openstack/compute/consoles.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/admin_actions.py b/nova/api/openstack/compute/contrib/admin_actions.py index a3f68e828..8e5863706 100644 --- a/nova/api/openstack/compute/contrib/admin_actions.py +++ b/nova/api/openstack/compute/contrib/admin_actions.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack, LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/agents.py b/nova/api/openstack/compute/contrib/agents.py index 6590deafe..1ea92b4de 100644 --- a/nova/api/openstack/compute/contrib/agents.py +++ b/nova/api/openstack/compute/contrib/agents.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/availability_zone.py b/nova/api/openstack/compute/contrib/availability_zone.py index c79556839..f5092010c 100644 --- a/nova/api/openstack/compute/contrib/availability_zone.py +++ b/nova/api/openstack/compute/contrib/availability_zone.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/cells.py b/nova/api/openstack/compute/contrib/cells.py index 8e31777e2..efd2cd189 100644 --- a/nova/api/openstack/compute/contrib/cells.py +++ b/nova/api/openstack/compute/contrib/cells.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011-2012 OpenStack LLC. +# Copyright 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/certificates.py b/nova/api/openstack/compute/contrib/certificates.py index d2ce7bc5d..2d8e8ad6d 100644 --- a/nova/api/openstack/compute/contrib/certificates.py +++ b/nova/api/openstack/compute/contrib/certificates.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/cloudpipe.py b/nova/api/openstack/compute/contrib/cloudpipe.py index 20ae87fe1..01e6f8303 100644 --- a/nova/api/openstack/compute/contrib/cloudpipe.py +++ b/nova/api/openstack/compute/contrib/cloudpipe.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack, LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/cloudpipe_update.py b/nova/api/openstack/compute/contrib/cloudpipe_update.py index f6ed7bb3a..a096c7107 100644 --- a/nova/api/openstack/compute/contrib/cloudpipe_update.py +++ b/nova/api/openstack/compute/contrib/cloudpipe_update.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/config_drive.py b/nova/api/openstack/compute/contrib/config_drive.py index 5f1f7b16d..f0b3de5ed 100644 --- a/nova/api/openstack/compute/contrib/config_drive.py +++ b/nova/api/openstack/compute/contrib/config_drive.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/console_output.py b/nova/api/openstack/compute/contrib/console_output.py index 60594cb53..2cfa6e447 100644 --- a/nova/api/openstack/compute/contrib/console_output.py +++ b/nova/api/openstack/compute/contrib/console_output.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2011 Grid Dynamics # Copyright 2011 Eldar Nugaev, Kirill Shileev, Ilya Alekseyev # diff --git a/nova/api/openstack/compute/contrib/consoles.py b/nova/api/openstack/compute/contrib/consoles.py index 4895a9e7b..264f0b270 100644 --- a/nova/api/openstack/compute/contrib/consoles.py +++ b/nova/api/openstack/compute/contrib/consoles.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/coverage_ext.py b/nova/api/openstack/compute/contrib/coverage_ext.py index 6edf9244f..bafb6711e 100644 --- a/nova/api/openstack/compute/contrib/coverage_ext.py +++ b/nova/api/openstack/compute/contrib/coverage_ext.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -19,10 +19,12 @@ import os import re +import socket import sys import telnetlib import tempfile +from oslo.config import cfg from webob import exc from nova.api.openstack import extensions @@ -39,13 +41,13 @@ from nova.scheduler import rpcapi as scheduler_api LOG = logging.getLogger(__name__) authorize = extensions.extension_authorizer('compute', 'coverage_ext') +CONF = cfg.CONF class CoverageController(object): """The Coverage report API controller for the OpenStack API.""" def __init__(self): self.data_path = tempfile.mkdtemp(prefix='nova-coverage_') - data_out = os.path.join(self.data_path, '.nova-coverage') self.compute_api = compute_api.API() self.network_api = network_api.API() self.conductor_api = conductor_api.API() @@ -55,18 +57,25 @@ class CoverageController(object): self.cert_api = cert_api.CertAPI() self.services = [] self.combine = False - try: - import coverage - self.coverInst = coverage.coverage(data_file=data_out) - self.has_coverage = True - except ImportError: - self.has_coverage = False + self._cover_inst = None + self.host = CONF.host super(CoverageController, self).__init__() + @property + def coverInst(self): + if not self._cover_inst: + try: + import coverage + data_out = os.path.join(self.data_path, '.nova-coverage') + self._cover_inst = coverage.coverage(data_file=data_out) + except ImportError: + pass + return self._cover_inst + def _find_services(self, req): """Returns a list of services.""" context = req.environ['nova.context'] - services = db.service_get_all(context, False) + services = db.service_get_all(context) hosts = [] for serv in services: hosts.append({"service": serv["topic"], "host": serv["host"]}) @@ -109,14 +118,13 @@ class CoverageController(object): return ports def _start_coverage_telnet(self, tn, service): + data_file = os.path.join(self.data_path, + '.nova-coverage.%s' % str(service)) tn.write('import sys\n') tn.write('from coverage import coverage\n') - if self.combine: - data_file = os.path.join(self.data_path, - '.nova-coverage.%s' % str(service)) - tn.write("coverInst = coverage(data_file='%s')\n)" % data_file) - else: - tn.write('coverInst = coverage()\n') + tn.write("coverInst = coverage(data_file='%s') " + "if 'coverInst' not in locals() " + "else coverInst\n" % data_file) tn.write('coverInst.skipModules = sys.modules.keys()\n') tn.write("coverInst.start()\n") tn.write("print 'finished'\n") @@ -135,8 +143,21 @@ class CoverageController(object): ports = self._find_ports(req, hosts) self.services = [] for service in ports: - service['telnet'] = telnetlib.Telnet(service['host'], - service['port']) + try: + service['telnet'] = telnetlib.Telnet(service['host'], + service['port']) + # NOTE(mtreinish): Fallback to try connecting to lo if + # ECONNREFUSED is raised. If using the hostname that is returned + # for the service from the service_get_all() DB query raises + # ECONNREFUSED it most likely means that the hostname in the DB + # doesn't resolve to 127.0.0.1. Currently backdoors only open on + # loopback so this is for covering the common single host use case + except socket.error as e: + if 'ECONNREFUSED' in e and service['host'] == self.host: + service['telnet'] = telnetlib.Telnet('127.0.0.1', + service['port']) + else: + raise e self.services.append(service) self._start_coverage_telnet(service['telnet'], service['service']) @@ -242,7 +263,7 @@ class CoverageController(object): 'report': self._report_coverage, } authorize(req.environ['nova.context']) - if not self.has_coverage: + if not self.coverInst: msg = _("Python coverage module is not installed.") raise exc.HTTPServiceUnavailable(explanation=msg) for action, data in body.iteritems(): diff --git a/nova/api/openstack/compute/contrib/createserverext.py b/nova/api/openstack/compute/contrib/createserverext.py index db9838c98..337fedae6 100644 --- a/nova/api/openstack/compute/contrib/createserverext.py +++ b/nova/api/openstack/compute/contrib/createserverext.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/deferred_delete.py b/nova/api/openstack/compute/contrib/deferred_delete.py index 94bf63ab4..122fc7035 100644 --- a/nova/api/openstack/compute/contrib/deferred_delete.py +++ b/nova/api/openstack/compute/contrib/deferred_delete.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack, LLC +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/disk_config.py b/nova/api/openstack/compute/contrib/disk_config.py index 4a8fe9ce5..2c4d24332 100644 --- a/nova/api/openstack/compute/contrib/disk_config.py +++ b/nova/api/openstack/compute/contrib/disk_config.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/evacuate.py b/nova/api/openstack/compute/contrib/evacuate.py index 4c9229d1e..7877fa1fd 100644 --- a/nova/api/openstack/compute/contrib/evacuate.py +++ b/nova/api/openstack/compute/contrib/evacuate.py @@ -1,4 +1,4 @@ -# Copyright 2013 OpenStack, LLC. +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/extended_availability_zone.py b/nova/api/openstack/compute/contrib/extended_availability_zone.py index 734ddf7c8..af557219f 100644 --- a/nova/api/openstack/compute/contrib/extended_availability_zone.py +++ b/nova/api/openstack/compute/contrib/extended_availability_zone.py @@ -21,8 +21,8 @@ from nova.api.openstack import extensions from nova.api.openstack import wsgi from nova.api.openstack import xmlutil from nova import availability_zones -from nova.common import memorycache from nova.openstack.common import log as logging +from nova.openstack.common import memorycache LOG = logging.getLogger(__name__) # NOTE(vish): azs don't change that often, so cache them for an hour to diff --git a/nova/api/openstack/compute/contrib/extended_server_attributes.py b/nova/api/openstack/compute/contrib/extended_server_attributes.py index 51fd7f375..dd332ff13 100644 --- a/nova/api/openstack/compute/contrib/extended_server_attributes.py +++ b/nova/api/openstack/compute/contrib/extended_server_attributes.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack, LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/extended_status.py b/nova/api/openstack/compute/contrib/extended_status.py index 8a7c67f18..930893b27 100644 --- a/nova/api/openstack/compute/contrib/extended_status.py +++ b/nova/api/openstack/compute/contrib/extended_status.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack, LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/fixed_ips.py b/nova/api/openstack/compute/contrib/fixed_ips.py index e70416bac..6f0a36888 100644 --- a/nova/api/openstack/compute/contrib/fixed_ips.py +++ b/nova/api/openstack/compute/contrib/fixed_ips.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/flavor_access.py b/nova/api/openstack/compute/contrib/flavor_access.py index 744fea13b..ec5937094 100644 --- a/nova/api/openstack/compute/contrib/flavor_access.py +++ b/nova/api/openstack/compute/contrib/flavor_access.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/flavorextradata.py b/nova/api/openstack/compute/contrib/flavorextradata.py index 8f9640c98..313b83b5d 100644 --- a/nova/api/openstack/compute/contrib/flavorextradata.py +++ b/nova/api/openstack/compute/contrib/flavorextradata.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack, LLC +# Copyright 2012 OpenStack Foundation # Copyright 2011 Canonical Ltd. # All Rights Reserved. # diff --git a/nova/api/openstack/compute/contrib/floating_ip_dns.py b/nova/api/openstack/compute/contrib/floating_ip_dns.py index bddf3580c..5caea9ffa 100644 --- a/nova/api/openstack/compute/contrib/floating_ip_dns.py +++ b/nova/api/openstack/compute/contrib/floating_ip_dns.py @@ -14,7 +14,6 @@ # License for the specific language governing permissions and limitations # under the License -import socket import urllib import webob @@ -25,6 +24,7 @@ from nova.api.openstack import xmlutil from nova import exception from nova import network from nova.openstack.common import log as logging +from nova import utils LOG = logging.getLogger(__name__) @@ -210,15 +210,8 @@ class FloatingIPDNSEntryController(object): floating_ip = None # Check whether id is a valid ipv4/ipv6 address. - try: - socket.inet_pton(socket.AF_INET, id) + if utils.is_valid_ipv4(id) or utils.is_valid_ipv6(id): floating_ip = id - except socket.error: - try: - socket.inet_pton(socket.AF_INET6, id) - floating_ip = id - except socket.error: - pass if floating_ip: entries = self.network_api.get_dns_entries_by_address(context, diff --git a/nova/api/openstack/compute/contrib/floating_ips.py b/nova/api/openstack/compute/contrib/floating_ips.py index f7c1100a5..bf1246ccb 100644 --- a/nova/api/openstack/compute/contrib/floating_ips.py +++ b/nova/api/openstack/compute/contrib/floating_ips.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. # Copyright 2011 Grid Dynamics # Copyright 2011 Eldar Nugaev, Kirill Shileev, Ilya Alekseyev @@ -294,7 +294,9 @@ class FloatingIPActionController(wsgi.Controller): disassociate_floating_ip(self, context, instance, address) return webob.Response(status_int=202) else: - return webob.Response(status_int=404) + msg = _("Floating ip %(address)s is not associated with instance " + "%(id)s.") % locals() + raise webob.exc.HTTPUnprocessableEntity(explanation=msg) class Floating_ips(extensions.ExtensionDescriptor): diff --git a/nova/api/openstack/compute/contrib/floating_ips_bulk.py b/nova/api/openstack/compute/contrib/floating_ips_bulk.py index afd42e12f..e6a7fecee 100644 --- a/nova/api/openstack/compute/contrib/floating_ips_bulk.py +++ b/nova/api/openstack/compute/contrib/floating_ips_bulk.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/fping.py b/nova/api/openstack/compute/contrib/fping.py index 394d5924e..e1a8dfb8c 100644 --- a/nova/api/openstack/compute/contrib/fping.py +++ b/nova/api/openstack/compute/contrib/fping.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 Grid Dynamics -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/hide_server_addresses.py b/nova/api/openstack/compute/contrib/hide_server_addresses.py index 4d8bcd94e..08e33ce53 100644 --- a/nova/api/openstack/compute/contrib/hide_server_addresses.py +++ b/nova/api/openstack/compute/contrib/hide_server_addresses.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/hosts.py b/nova/api/openstack/compute/contrib/hosts.py index a3cfd229c..3ecfb9965 100644 --- a/nova/api/openstack/compute/contrib/hosts.py +++ b/nova/api/openstack/compute/contrib/hosts.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/hypervisors.py b/nova/api/openstack/compute/contrib/hypervisors.py index 7e477bbf3..28cb0f291 100644 --- a/nova/api/openstack/compute/contrib/hypervisors.py +++ b/nova/api/openstack/compute/contrib/hypervisors.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/instance_usage_audit_log.py b/nova/api/openstack/compute/contrib/instance_usage_audit_log.py index d6ffe3677..3c3aa23c0 100644 --- a/nova/api/openstack/compute/contrib/instance_usage_audit_log.py +++ b/nova/api/openstack/compute/contrib/instance_usage_audit_log.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/keypairs.py b/nova/api/openstack/compute/contrib/keypairs.py index ef93fb048..a79b39aae 100644 --- a/nova/api/openstack/compute/contrib/keypairs.py +++ b/nova/api/openstack/compute/contrib/keypairs.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -119,7 +119,10 @@ class KeypairController(object): context = req.environ['nova.context'] authorize(context) - keypair = self.api.get_key_pair(context, context.user_id, id) + try: + keypair = self.api.get_key_pair(context, context.user_id, id) + except exception.KeypairNotFound: + raise webob.exc.HTTPNotFound() return {'keypair': keypair} @wsgi.serializers(xml=KeypairsTemplate) diff --git a/nova/api/openstack/compute/contrib/multinic.py b/nova/api/openstack/compute/contrib/multinic.py index 7017422a1..30789a3f1 100644 --- a/nova/api/openstack/compute/contrib/multinic.py +++ b/nova/api/openstack/compute/contrib/multinic.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/multiple_create.py b/nova/api/openstack/compute/contrib/multiple_create.py index cbad2d439..fd450b6d8 100644 --- a/nova/api/openstack/compute/contrib/multiple_create.py +++ b/nova/api/openstack/compute/contrib/multiple_create.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/os_networks.py b/nova/api/openstack/compute/contrib/os_networks.py index bef2c3d1f..c6268f277 100644 --- a/nova/api/openstack/compute/contrib/os_networks.py +++ b/nova/api/openstack/compute/contrib/os_networks.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 Grid Dynamics -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/os_tenant_networks.py b/nova/api/openstack/compute/contrib/os_tenant_networks.py index c22e64b1f..5268ecd64 100644 --- a/nova/api/openstack/compute/contrib/os_tenant_networks.py +++ b/nova/api/openstack/compute/contrib/os_tenant_networks.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/quota_classes.py b/nova/api/openstack/compute/contrib/quota_classes.py index 7b94e45b1..361748df8 100644 --- a/nova/api/openstack/compute/contrib/quota_classes.py +++ b/nova/api/openstack/compute/contrib/quota_classes.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/quotas.py b/nova/api/openstack/compute/contrib/quotas.py index b1a461431..ddfe5bf08 100644 --- a/nova/api/openstack/compute/contrib/quotas.py +++ b/nova/api/openstack/compute/contrib/quotas.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/rescue.py b/nova/api/openstack/compute/contrib/rescue.py index c62ed5894..b6cf3a918 100644 --- a/nova/api/openstack/compute/contrib/rescue.py +++ b/nova/api/openstack/compute/contrib/rescue.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack, LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/scheduler_hints.py b/nova/api/openstack/compute/contrib/scheduler_hints.py index 5e54fbd37..637698b31 100644 --- a/nova/api/openstack/compute/contrib/scheduler_hints.py +++ b/nova/api/openstack/compute/contrib/scheduler_hints.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/security_groups.py b/nova/api/openstack/compute/contrib/security_groups.py index 092e89b9b..af97a2a6b 100644 --- a/nova/api/openstack/compute/contrib/security_groups.py +++ b/nova/api/openstack/compute/contrib/security_groups.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2012 Justin Santa Barbara # All Rights Reserved. # @@ -622,11 +622,11 @@ class NativeSecurityGroupExceptions(object): raise exc.HTTPNotFound(explanation=msg) -class NativeNovaSecurityGroupAPI(compute_api.SecurityGroupAPI, - NativeSecurityGroupExceptions): +class NativeNovaSecurityGroupAPI(NativeSecurityGroupExceptions, + compute_api.SecurityGroupAPI): pass -class NativeQuantumSecurityGroupAPI(quantum_driver.SecurityGroupAPI, - NativeSecurityGroupExceptions): +class NativeQuantumSecurityGroupAPI(NativeSecurityGroupExceptions, + quantum_driver.SecurityGroupAPI): pass diff --git a/nova/api/openstack/compute/contrib/server_diagnostics.py b/nova/api/openstack/compute/contrib/server_diagnostics.py index 1be4b664c..7711eb653 100644 --- a/nova/api/openstack/compute/contrib/server_diagnostics.py +++ b/nova/api/openstack/compute/contrib/server_diagnostics.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/services.py b/nova/api/openstack/compute/contrib/services.py index 0f91bf13f..3afd5ff45 100644 --- a/nova/api/openstack/compute/contrib/services.py +++ b/nova/api/openstack/compute/contrib/services.py @@ -1,7 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/simple_tenant_usage.py b/nova/api/openstack/compute/contrib/simple_tenant_usage.py index f219689f7..f759e90b0 100644 --- a/nova/api/openstack/compute/contrib/simple_tenant_usage.py +++ b/nova/api/openstack/compute/contrib/simple_tenant_usage.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/contrib/used_limits.py b/nova/api/openstack/compute/contrib/used_limits.py index a5e0b378b..df40fe91a 100644 --- a/nova/api/openstack/compute/contrib/used_limits.py +++ b/nova/api/openstack/compute/contrib/used_limits.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/contrib/user_data.py b/nova/api/openstack/compute/contrib/user_data.py index 1f58c102d..3e69a65cc 100644 --- a/nova/api/openstack/compute/contrib/user_data.py +++ b/nova/api/openstack/compute/contrib/user_data.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/openstack/compute/extensions.py b/nova/api/openstack/compute/extensions.py index 4e49482f5..5e6633f1d 100644 --- a/nova/api/openstack/compute/extensions.py +++ b/nova/api/openstack/compute/extensions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/flavors.py b/nova/api/openstack/compute/flavors.py index 8aa57a2b1..a0d33abd4 100644 --- a/nova/api/openstack/compute/flavors.py +++ b/nova/api/openstack/compute/flavors.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/image_metadata.py b/nova/api/openstack/compute/image_metadata.py index 7e78d6324..65ed72a23 100644 --- a/nova/api/openstack/compute/image_metadata.py +++ b/nova/api/openstack/compute/image_metadata.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/images.py b/nova/api/openstack/compute/images.py index 703d2fe2d..82db21c9e 100644 --- a/nova/api/openstack/compute/images.py +++ b/nova/api/openstack/compute/images.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/ips.py b/nova/api/openstack/compute/ips.py index 7b196d956..ee917e65e 100644 --- a/nova/api/openstack/compute/ips.py +++ b/nova/api/openstack/compute/ips.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/limits.py b/nova/api/openstack/compute/limits.py index 767280a45..2f69d5737 100644 --- a/nova/api/openstack/compute/limits.py +++ b/nova/api/openstack/compute/limits.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/server_metadata.py b/nova/api/openstack/compute/server_metadata.py index 0de5d536f..7dc6b0194 100644 --- a/nova/api/openstack/compute/server_metadata.py +++ b/nova/api/openstack/compute/server_metadata.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/servers.py b/nova/api/openstack/compute/servers.py index cc33537af..3464cfdbd 100644 --- a/nova/api/openstack/compute/servers.py +++ b/nova/api/openstack/compute/servers.py @@ -1,4 +1,4 @@ -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # Copyright 2011 Piston Cloud Computing, Inc # All Rights Reserved. # @@ -17,7 +17,6 @@ import base64 import os import re -import socket from oslo.config import cfg import webob @@ -704,16 +703,12 @@ class Controller(wsgi.Controller): raise exc.HTTPBadRequest(explanation=expl) def _validate_access_ipv4(self, address): - try: - socket.inet_aton(address) - except socket.error: + if not utils.is_valid_ipv4(address): expl = _('accessIPv4 is not proper IPv4 format') raise exc.HTTPBadRequest(explanation=expl) def _validate_access_ipv6(self, address): - try: - socket.inet_pton(socket.AF_INET6, address) - except socket.error: + if not utils.is_valid_ipv6(address): expl = _('accessIPv6 is not proper IPv6 format') raise exc.HTTPBadRequest(explanation=expl) @@ -830,7 +825,7 @@ class Controller(wsgi.Controller): max_count = server_dict.get('max_count', min_count) try: - min_count = int(min_count) + min_count = int(str(min_count)) except ValueError: msg = _('min_count must be an integer value') raise exc.HTTPBadRequest(explanation=msg) @@ -839,7 +834,7 @@ class Controller(wsgi.Controller): raise exc.HTTPBadRequest(explanation=msg) try: - max_count = int(max_count) + max_count = int(str(max_count)) except ValueError: msg = _('max_count must be an integer value') raise exc.HTTPBadRequest(explanation=msg) diff --git a/nova/api/openstack/compute/versions.py b/nova/api/openstack/compute/versions.py index 5c416908e..0d2117053 100644 --- a/nova/api/openstack/compute/versions.py +++ b/nova/api/openstack/compute/versions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/views/addresses.py b/nova/api/openstack/compute/views/addresses.py index e1d75a9aa..fd9c3d25e 100644 --- a/nova/api/openstack/compute/views/addresses.py +++ b/nova/api/openstack/compute/views/addresses.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/views/flavors.py b/nova/api/openstack/compute/views/flavors.py index fbbe5c45e..6cfb114e0 100644 --- a/nova/api/openstack/compute/views/flavors.py +++ b/nova/api/openstack/compute/views/flavors.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/views/images.py b/nova/api/openstack/compute/views/images.py index 6438f0aa9..cc0718a4e 100644 --- a/nova/api/openstack/compute/views/images.py +++ b/nova/api/openstack/compute/views/images.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/views/limits.py b/nova/api/openstack/compute/views/limits.py index 4ccf40de7..8ef49afd7 100644 --- a/nova/api/openstack/compute/views/limits.py +++ b/nova/api/openstack/compute/views/limits.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/compute/views/servers.py b/nova/api/openstack/compute/views/servers.py index 939515468..165d363a4 100644 --- a/nova/api/openstack/compute/views/servers.py +++ b/nova/api/openstack/compute/views/servers.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # diff --git a/nova/api/openstack/compute/views/versions.py b/nova/api/openstack/compute/views/versions.py index 105921ff0..7e8d15f0b 100644 --- a/nova/api/openstack/compute/views/versions.py +++ b/nova/api/openstack/compute/views/versions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/extensions.py b/nova/api/openstack/extensions.py index 94ce76ec7..b2cdacd1e 100644 --- a/nova/api/openstack/extensions.py +++ b/nova/api/openstack/extensions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2011 Justin Santa Barbara # All Rights Reserved. # diff --git a/nova/api/openstack/urlmap.py b/nova/api/openstack/urlmap.py index aa49226b3..d67b66c4d 100644 --- a/nova/api/openstack/urlmap.py +++ b/nova/api/openstack/urlmap.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/openstack/wsgi.py b/nova/api/openstack/wsgi.py index 8c77f1c9c..5b9900f72 100644 --- a/nova/api/openstack/wsgi.py +++ b/nova/api/openstack/wsgi.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -878,9 +878,6 @@ class Resource(wsgi.Application): def __call__(self, request): """WSGI method that controls (de)serialization and method dispatch.""" - LOG.info("%(method)s %(url)s" % {"method": request.method, - "url": request.url}) - # Identify the action, its arguments, and the requested # content type action_args = self.get_action_args(request.environ) @@ -923,7 +920,7 @@ class Resource(wsgi.Application): return Fault(webob.exc.HTTPBadRequest(explanation=msg)) if body: - LOG.info(_("Action: '%(action)s', body: %(body)s") % locals()) + LOG.debug(_("Action: '%(action)s', body: %(body)s") % locals()) LOG.debug(_("Calling method %s") % meth) # Now, deserialize the request body... @@ -988,15 +985,6 @@ class Resource(wsgi.Application): response = resp_obj.serialize(request, accept, self.default_serializers) - try: - msg_dict = dict(url=request.url, status=response.status_int) - msg = _("%(url)s returned with HTTP %(status)d") % msg_dict - except AttributeError, e: - msg_dict = dict(url=request.url, e=e) - msg = _("%(url)s returned a fault: %(e)s") % msg_dict - - LOG.info(msg) - return response def get_method(self, request, action, content_type, body): diff --git a/nova/api/openstack/xmlutil.py b/nova/api/openstack/xmlutil.py index 290732759..a2f5b7506 100644 --- a/nova/api/openstack/xmlutil.py +++ b/nova/api/openstack/xmlutil.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/api/sizelimit.py b/nova/api/sizelimit.py index 1e88f183e..f1bf3cf1b 100644 --- a/nova/api/sizelimit.py +++ b/nova/api/sizelimit.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/api/validator.py b/nova/api/validator.py index 9304387fd..2e7356391 100644 --- a/nova/api/validator.py +++ b/nova/api/validator.py @@ -18,7 +18,6 @@ import base64 import re -import socket from nova.openstack.common import log as logging @@ -94,14 +93,6 @@ def validate_image_path(val): return True -def validate_ipv4(addr): - try: - socket.inet_aton(addr) - except (socket.error, TypeError): - return False - return True - - def validate_user_data(user_data): """Check if the user_data is encoded properly.""" try: diff --git a/nova/availability_zones.py b/nova/availability_zones.py index 61486517d..45b790081 100644 --- a/nova/availability_zones.py +++ b/nova/availability_zones.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/cells/messaging.py b/nova/cells/messaging.py index db49cc8fd..f83f141dc 100644 --- a/nova/cells/messaging.py +++ b/nova/cells/messaging.py @@ -784,8 +784,13 @@ class _BroadcastMessageMethods(_BaseMessageMethods): # if we actually want this code to remain.. self.db.instance_create(message.ctxt, instance) if info_cache: - self.db.instance_info_cache_update(message.ctxt, instance_uuid, - info_cache, update_cells=False) + try: + self.db.instance_info_cache_update(message.ctxt, + instance_uuid, info_cache, update_cells=False) + except exception.InstanceInfoCacheNotFound: + # Can happen if we try to update a deleted instance's + # network information. + pass def instance_destroy_at_top(self, message, instance, **kwargs): """Destroy an instance from the DB if we're a top level cell.""" diff --git a/nova/cert/__init__.py b/nova/cert/__init__.py index 74cec6938..74704e5e6 100644 --- a/nova/cert/__init__.py +++ b/nova/cert/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack, LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/cert/manager.py b/nova/cert/manager.py index d1ffbd5a7..de959c8e7 100644 --- a/nova/cert/manager.py +++ b/nova/cert/manager.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack, LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/compute/api.py b/nova/compute/api.py index d45ee6703..76d4d06ba 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -332,6 +332,19 @@ class API(base.Base): LOG.warn(msg) raise exception.InvalidMetadataSize(reason=msg) + def _check_requested_secgroups(self, context, secgroups): + """ + Check if the security group requested exists and belongs to + the project. + """ + for secgroup in secgroups: + # NOTE(sdague): default is handled special + if secgroup == "default": + continue + if not self.security_group_api.get(context, secgroup): + raise exception.SecurityGroupNotFoundForProject( + project_id=context.project_id, security_group_id=secgroup) + def _check_requested_networks(self, context, requested_networks): """ Check if the networks requested belongs to the project @@ -447,7 +460,7 @@ class API(base.Base): image_href, kernel_id, ramdisk_id, min_count, max_count, display_name, display_description, - key_name, key_data, security_group, + key_name, key_data, security_groups, availability_zone, user_data, metadata, injected_files, access_ip_v4, access_ip_v6, @@ -460,8 +473,8 @@ class API(base.Base): if not metadata: metadata = {} - if not security_group: - security_group = 'default' + if not security_groups: + security_groups = ['default'] if not instance_type: instance_type = instance_types.get_default_instance_type() @@ -504,6 +517,7 @@ class API(base.Base): self._check_metadata_properties_quota(context, metadata) self._check_injected_file_quota(context, injected_files) + self._check_requested_secgroups(context, security_groups) self._check_requested_networks(context, requested_networks) if image_href: @@ -597,7 +611,8 @@ class API(base.Base): options = base_options.copy() instance = self.create_db_entry_for_new_instance( context, instance_type, image, options, - security_group, block_device_mapping, num_instances, i) + security_groups, block_device_mapping, + num_instances, i) instances.append(instance) instance_uuids.append(instance['uuid']) @@ -626,7 +641,7 @@ class API(base.Base): 'instance_type': instance_type, 'instance_uuids': instance_uuids, 'block_device_mapping': block_device_mapping, - 'security_group': security_group, + 'security_group': security_groups, } return (instances, request_spec, filter_properties) @@ -776,21 +791,18 @@ class API(base.Base): def _populate_instance_for_bdm(self, context, instance, instance_type, image, block_device_mapping): """Populate instance block device mapping information.""" - # FIXME(comstud): Why do the block_device_mapping DB calls - # require elevated context? - elevated = context.elevated() instance_uuid = instance['uuid'] image_properties = image.get('properties', {}) mappings = image_properties.get('mappings', []) if mappings: - self._update_image_block_device_mapping(elevated, + self._update_image_block_device_mapping(context, instance_type, instance_uuid, mappings) image_bdm = image_properties.get('block_device_mapping', []) for mapping in (image_bdm, block_device_mapping): if not mapping: continue - self._update_block_device_mapping(elevated, + self._update_block_device_mapping(context, instance_type, instance_uuid, mapping) def _populate_instance_shutdown_terminate(self, instance, image, @@ -859,7 +871,6 @@ class API(base.Base): instance['system_metadata']['image_base_image_ref'] = base_image_ref self.security_group_api.populate_security_groups(instance, security_groups) - return instance #NOTE(bcwaldon): No policy check since this is only used by scheduler and @@ -1069,6 +1080,10 @@ class API(base.Base): migration_ref) downsize_reservations = self._reserve_quota_delta(context, deltas) + + self._record_action_start(context, instance, + instance_actions.CONFIRM_RESIZE) + self.compute_rpcapi.confirm_resize(context, instance, migration_ref, host=src_host, cast=False, @@ -1308,11 +1323,14 @@ class API(base.Base): def get(self, context, instance_id): """Get a single instance with the given instance_id.""" # NOTE(ameade): we still need to support integer ids for ec2 - if uuidutils.is_uuid_like(instance_id): - instance = self.db.instance_get_by_uuid(context, instance_id) - elif utils.is_int_like(instance_id): - instance = self.db.instance_get(context, instance_id) - else: + try: + if uuidutils.is_uuid_like(instance_id): + instance = self.db.instance_get_by_uuid(context, instance_id) + elif utils.is_int_like(instance_id): + instance = self.db.instance_get(context, instance_id) + else: + raise exception.InstanceNotFound(instance_id=instance_id) + except exception.InvalidID: raise exception.InstanceNotFound(instance_id=instance_id) check_policy(context, 'get', instance) @@ -1578,17 +1596,10 @@ class API(base.Base): mapping = [] for bdm in bdms: - if bdm.no_device: + if bdm['no_device']: continue - m = {} - for attr in ('device_name', 'snapshot_id', 'volume_id', - 'volume_size', 'delete_on_termination', 'no_device', - 'virtual_name'): - val = getattr(bdm, attr) - if val is not None: - m[attr] = val - - volume_id = m.get('volume_id') + + volume_id = bdm.get('volume_id') if volume_id: # create snapshot based on volume_id volume = self.volume_api.get(context, volume_id) @@ -1598,11 +1609,10 @@ class API(base.Base): name = _('snapshot for %s') % image_meta['name'] snapshot = self.volume_api.create_snapshot_force( context, volume, name, volume['display_description']) - m['snapshot_id'] = snapshot['id'] - del m['volume_id'] + bdm['snapshot_id'] = snapshot['id'] + del bdm['volume_id'] - if m: - mapping.append(m) + mapping.append(bdm) for m in block_device.mappings_prepend_dev(properties.get('mappings', [])): @@ -1644,13 +1654,13 @@ class API(base.Base): #disk format of vhd is non-shrinkable if orig_image.get('disk_format') == 'vhd': - min_ram = instance['instance_type']['memory_mb'] min_disk = instance['instance_type']['root_gb'] else: #set new image values to the original image values - min_ram = orig_image.get('min_ram') min_disk = orig_image.get('min_disk') + min_ram = orig_image.get('min_ram') + return min_ram, min_disk def _get_block_device_info(self, context, instance_uuid): @@ -1677,8 +1687,7 @@ class API(base.Base): @wrap_check_policy @check_instance_lock @check_instance_state(vm_state=[vm_states.ACTIVE, vm_states.STOPPED, - vm_states.RESCUED, vm_states.PAUSED, - vm_states.SUSPENDED], + vm_states.PAUSED, vm_states.SUSPENDED], task_state=[None, task_states.REBOOTING, task_states.REBOOTING_HARD, task_states.RESUMING, @@ -1755,7 +1764,7 @@ class API(base.Base): """ Remove old image properties that we're storing as instance system metadata. These properties start with 'image_'. - Then add the properites for the new image. + Then add the properties for the new image. """ # FIXME(comstud): There's a race condition here in that @@ -2408,7 +2417,7 @@ class API(base.Base): bdms = self.get_instance_bdms(context, instance) for bdm in bdms: - if (block_device.strip_dev(bdm.device_name) == + if (block_device.strip_dev(bdm['device_name']) == block_device.strip_dev(instance['root_device_name'])): return True else: @@ -2438,10 +2447,10 @@ class API(base.Base): raising an exception. """ LOG.debug(_('vm evacuation scheduled')) - host = instance['host'] - service = self.db.service_get_by_compute_host(context, host) + inst_host = instance['host'] + service = self.db.service_get_by_compute_host(context, inst_host) if self.servicegroup_api.service_is_up(service): - msg = (_('Instance compute service state on %(host)s ' + msg = (_('Instance compute service state on %(inst_host)s ' 'expected to be down, but it was up.' ) % locals()) LOG.error(msg) @@ -3001,21 +3010,6 @@ class SecurityGroupAPI(base.Base, security_group_base.SecurityGroupBase): self.trigger_handler('instance_remove_security_group', context, instance, security_group_name) - def rule_exists(self, security_group, new_rule): - """Indicates whether the specified rule is already - defined in the given security group. - """ - for rule in security_group['rules']: - is_duplicate = True - keys = ('group_id', 'cidr', 'from_port', 'to_port', 'protocol') - for key in keys: - if rule.get(key) != new_rule.get(key): - is_duplicate = False - break - if is_duplicate: - return rule.get('id') or True - return False - def get_rule(self, context, id): self.ensure_default(context) try: @@ -3108,15 +3102,6 @@ class SecurityGroupAPI(base.Base, security_group_base.SecurityGroupBase): msg = _("Security group id should be integer") self.raise_invalid_property(msg) - def create_security_group_rule(self, context, security_group, new_rule): - if self.rule_exists(security_group, new_rule): - msg = (_('This rule already exists in group %s') % - new_rule['parent_group_id']) - self.raise_group_already_exists(msg) - return self.add_rules(context, new_rule['parent_group_id'], - security_group['name'], - [new_rule])[0] - def trigger_handler(self, event, *args): handle = getattr(self.sgh, 'trigger_%s_refresh' % event) handle(*args) @@ -3174,9 +3159,4 @@ class SecurityGroupAPI(base.Base, security_group_base.SecurityGroupBase): return [{'name': group['name']} for group in groups] def populate_security_groups(self, instance, security_groups): - # Use 'default' security_group if none specified. - if security_groups is None: - security_groups = ['default'] - elif not isinstance(security_groups, list): - security_groups = [security_groups] instance['security_groups'] = security_groups diff --git a/nova/compute/cells_api.py b/nova/compute/cells_api.py index 32f09ee90..d5a07490b 100644 --- a/nova/compute/cells_api.py +++ b/nova/compute/cells_api.py @@ -393,18 +393,6 @@ class ComputeCellsAPI(compute_api.API): super(ComputeCellsAPI, self).unpause(context, instance) self._cast_to_cells(context, instance, 'unpause') - def set_host_enabled(self, context, host, enabled): - """Sets the specified host's ability to accept new instances.""" - # FIXME(comstud): Since there's no instance here, we have no - # idea which cell should be the target. - pass - - def host_power_action(self, context, host, action): - """Reboots, shuts down or powers up the host.""" - # FIXME(comstud): Since there's no instance here, we have no - # idea which cell should be the target. - pass - def get_diagnostics(self, context, instance): """Retrieve diagnostics for the given instance.""" # FIXME(comstud): Cache this? diff --git a/nova/compute/claims.py b/nova/compute/claims.py index fc534fd23..51717ba18 100644 --- a/nova/compute/claims.py +++ b/nova/compute/claims.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/compute/instance_actions.py b/nova/compute/instance_actions.py index cbb517387..32d280128 100644 --- a/nova/compute/instance_actions.py +++ b/nova/compute/instance_actions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index 73105b33f..3060e0bc2 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -28,7 +28,7 @@ from oslo.config import cfg from nova import context from nova import db from nova import exception -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.openstack.common import log as logging from nova import utils @@ -134,7 +134,7 @@ def create(name, memory, vcpus, root_gb, ephemeral_gb=None, flavorid=None, try: return db.instance_type_create(context.get_admin_context(), kwargs) - except db_session.DBError, e: + except db_exc.DBError, e: LOG.exception(_('DB error: %s') % e) raise exception.InstanceTypeCreateFailed() diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 99b97e921..e172e6ad8 100755 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -68,6 +68,7 @@ from nova.openstack.common import rpc from nova.openstack.common import timeutils from nova import paths from nova import quota +from nova import safe_utils from nova.scheduler import rpcapi as scheduler_rpcapi from nova import utils from nova.virt import driver @@ -192,11 +193,11 @@ def reverts_task_state(function): try: return function(self, context, *args, **kwargs) except exception.UnexpectedTaskStateError: - LOG.exception(_("Possibly task preempted.")) # Note(maoy): unexpected task state means the current # task is preempted. Do not clear task state in this # case. - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_("Possibly task preempted.")) except Exception: with excutils.save_and_reraise_exception(): try: @@ -247,7 +248,7 @@ def wrap_instance_event(function): @functools.wraps(function) def decorated_function(self, context, *args, **kwargs): wrapped_func = utils.get_wrapped_function(function) - keyed_args = utils.getcallargs(wrapped_func, context, *args, + keyed_args = safe_utils.getcallargs(wrapped_func, context, *args, **kwargs) instance_uuid = keyed_args['instance']['uuid'] @@ -314,6 +315,10 @@ class ComputeVirtAPI(virtapi.VirtAPI): return self._compute.conductor_api.agent_build_get_by_triple( context, hypervisor, os, architecture) + def instance_type_get(self, context, instance_type_id): + return self._compute.conductor_api.instance_type_get(context, + instance_type_id) + class ComputeManager(manager.SchedulerDependentManager): """Manages the running instances from creation to destruction.""" @@ -384,21 +389,14 @@ class ComputeManager(manager.SchedulerDependentManager): """Return a list of instance records that match the instances found on the hypervisor. """ - local_instances = [] try: - # Try to find all local instances by uuid. - # FIXME(comstud): Would be nice to consolidate this into - # a single query to nova-conductor. - for uuid in self.driver.list_instance_uuids(): - try: - instance = self.conductor_api.instance_get_by_uuid( - context, uuid) - local_instances.append(instance) - except exception.InstanceNotFound as e: - LOG.error(_('Instance %(uuid)s found in the ' - 'hypervisor, but not in the database'), - locals()) - continue + driver_uuids = self.driver.list_instance_uuids() + local_instances = self.conductor_api.instance_get_all_by_filters( + context, {'uuid': driver_uuids}) + local_instance_uuids = [inst['uuid'] for inst in local_instances] + for uuid in set(driver_uuids) - set(local_instance_uuids): + LOG.error(_('Instance %(uuid)s found in the hypervisor, but ' + 'not in the database'), locals()) return local_instances except NotImplementedError: pass @@ -406,9 +404,9 @@ class ComputeManager(manager.SchedulerDependentManager): # The driver doesn't support uuids listing, so we'll have # to brute force. driver_instances = self.driver.list_instances() - all_instances = self.conductor_api.instance_get_all(context) - name_map = dict([(instance['name'], instance) - for instance in all_instances]) + instances = self.conductor_api.instance_get_all_by_host(context, + self.host) + name_map = dict((instance['name'], instance) for instance in instances) local_instances = [] for driver_instance in driver_instances: instance = name_map.get(driver_instance) @@ -448,8 +446,6 @@ class ComputeManager(manager.SchedulerDependentManager): def _init_instance(self, context, instance): '''Initialize this instance during service init.''' - db_state = instance['power_state'] - drv_state = self._get_power_state(context, instance) closing_vm_states = (vm_states.DELETED, vm_states.SOFT_DELETED) @@ -458,12 +454,6 @@ class ComputeManager(manager.SchedulerDependentManager): if instance['vm_state'] in closing_vm_states: return - expect_running = (db_state == power_state.RUNNING and - drv_state != db_state) - - LOG.debug(_('Current state is %(drv_state)s, state in DB is ' - '%(db_state)s.'), locals(), instance=instance) - net_info = compute_utils.get_nw_info_for_instance(instance) # We're calling plug_vifs to ensure bridge and iptables @@ -471,6 +461,31 @@ class ComputeManager(manager.SchedulerDependentManager): legacy_net_info = self._legacy_nw_info(net_info) self.driver.plug_vifs(instance, legacy_net_info) + if instance['task_state'] == task_states.RESIZE_MIGRATING: + # We crashed during resize/migration, so roll back for safety + try: + self.driver.finish_revert_migration( + instance, self._legacy_nw_info(net_info), + self._get_instance_volume_block_device_info(context, + instance)) + except Exception, e: + LOG.exception(_('Failed to revert crashed migration'), + instance=instance) + finally: + LOG.info(_('Instance found in migrating state during ' + 'startup. Resetting task_state'), + instance=instance) + instance = self._instance_update(context, instance['uuid'], + task_state=None) + + db_state = instance['power_state'] + drv_state = self._get_power_state(context, instance) + expect_running = (db_state == power_state.RUNNING and + drv_state != db_state) + + LOG.debug(_('Current state is %(drv_state)s, state in DB is ' + '%(db_state)s.'), locals(), instance=instance) + if expect_running and CONF.resume_guests_state_on_host_boot: LOG.info( _('Rebooting instance after nova-compute restart.'), @@ -769,17 +784,30 @@ class ComputeManager(manager.SchedulerDependentManager): block_device_info = self._prep_block_device( context, instance, bdms) + set_access_ip = (is_first_time and + not instance['access_ip_v4'] and + not instance['access_ip_v6']) + instance = self._spawn(context, instance, image_meta, network_info, block_device_info, - injected_files, admin_password) + injected_files, admin_password, + set_access_ip=set_access_ip) except exception.InstanceNotFound: # the instance got deleted during the spawn - try: - self._deallocate_network(context, instance) - except Exception: - msg = _('Failed to dealloc network for deleted instance') - LOG.exception(msg, instance=instance) - raise + with excutils.save_and_reraise_exception(): + try: + self._deallocate_network(context, instance) + except Exception: + msg = _('Failed to dealloc network ' + 'for deleted instance') + LOG.exception(msg, instance=instance) + except exception.UnexpectedTaskStateError as e: + actual_task_state = e.kwargs.get('actual', None) + if actual_task_state == 'deleting': + msg = _('Instance was deleted during spawn.') + LOG.debug(msg, instance=instance) + else: + raise except Exception: exc_info = sys.exc_info() # try to re-schedule instance: @@ -788,11 +816,6 @@ class ComputeManager(manager.SchedulerDependentManager): is_first_time, request_spec, filter_properties) else: # Spawn success: - if (is_first_time and not instance['access_ip_v4'] - and not instance['access_ip_v6']): - instance = self._update_access_ip(context, instance, - network_info) - self._notify_about_instance_usage(context, instance, "create.end", network_info=network_info, extra_usage_info=extra_usage_info) @@ -822,8 +845,8 @@ class ComputeManager(manager.SchedulerDependentManager): self._deallocate_network(context, instance) except Exception: # do not attempt retry if network de-allocation failed: - self._log_original_error(exc_info, instance_uuid) - raise + with excutils.save_and_reraise_exception(): + self._log_original_error(exc_info, instance_uuid) try: method_args = (request_spec, admin_password, injected_files, @@ -897,32 +920,6 @@ class ComputeManager(manager.SchedulerDependentManager): LOG.warn(_("Instance build timed out. Set to error state."), instance=instance) - def _update_access_ip(self, context, instance, nw_info): - """Update the access ip values for a given instance. - - If CONF.default_access_ip_network_name is set, this method will - grab the corresponding network and set the access ip values - accordingly. Note that when there are multiple ips to choose from, - an arbitrary one will be chosen. - """ - - network_name = CONF.default_access_ip_network_name - if not network_name: - return instance - - update_info = {} - for vif in nw_info: - if vif['network']['label'] == network_name: - for ip in vif.fixed_ips(): - if ip['version'] == 4: - update_info['access_ip_v4'] = ip['address'] - if ip['version'] == 6: - update_info['access_ip_v6'] = ip['address'] - if update_info: - instance = self._instance_update(context, instance['uuid'], - **update_info) - return instance - def _check_instance_exists(self, context, instance): """Ensure an instance with the same name is not already present.""" if self.driver.instance_exists(instance['name']): @@ -1011,9 +1008,9 @@ class ComputeManager(manager.SchedulerDependentManager): conductor_api=self.conductor_api, security_groups=security_groups) except Exception: - LOG.exception(_('Instance failed network setup'), - instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Instance failed network setup'), + instance=instance) LOG.debug(_('Instance network_info: |%s|'), network_info, instance=instance) @@ -1025,12 +1022,13 @@ class ComputeManager(manager.SchedulerDependentManager): try: return self._setup_block_device_mapping(context, instance, bdms) except Exception: - LOG.exception(_('Instance failed block device setup'), - instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Instance failed block device setup'), + instance=instance) def _spawn(self, context, instance, image_meta, network_info, - block_device_info, injected_files, admin_password): + block_device_info, injected_files, admin_password, + set_access_ip=False): """Spawn an instance with error logging and update its power state.""" instance = self._instance_update(context, instance['uuid'], vm_state=vm_states.BUILDING, @@ -1042,16 +1040,44 @@ class ComputeManager(manager.SchedulerDependentManager): self._legacy_nw_info(network_info), block_device_info) except Exception: - LOG.exception(_('Instance failed to spawn'), instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Instance failed to spawn'), instance=instance) current_power_state = self._get_power_state(context, instance) + + update_data = dict(power_state=current_power_state, + vm_state=vm_states.ACTIVE, + task_state=None, + expected_task_state=task_states.SPAWNING, + launched_at=timeutils.utcnow()) + + def _set_access_ip_values(): + """Add access ip values for a given instance. + + If CONF.default_access_ip_network_name is set, this method will + grab the corresponding network and set the access ip values + accordingly. Note that when there are multiple ips to choose + from, an arbitrary one will be chosen. + """ + + network_name = CONF.default_access_ip_network_name + if not network_name: + return + + for vif in network_info: + if vif['network']['label'] == network_name: + for ip in vif.fixed_ips(): + if ip['version'] == 4: + update_data['access_ip_v4'] = ip['address'] + if ip['version'] == 6: + update_data['access_ip_v6'] = ip['address'] + return + + if set_access_ip: + _set_access_ip_values() + return self._instance_update(context, instance['uuid'], - power_state=current_power_state, - vm_state=vm_states.ACTIVE, - task_state=None, - expected_task_state=task_states.SPAWNING, - launched_at=timeutils.utcnow()) + **update_data) def _notify_about_instance_usage(self, context, instance, event_suffix, network_info=None, system_metadata=None, @@ -1153,8 +1179,14 @@ class ComputeManager(manager.SchedulerDependentManager): except exception.NetworkNotFound: network_info = network_model.NetworkInfo() - # tear down allocated network structure - self._deallocate_network(context, instance) + try: + # tear down allocated network structure + self._deallocate_network(context, instance) + except Exception: + with excutils.save_and_reraise_exception(): + LOG.error(_('Failed to deallocate network for instance.'), + instance=instance) + self._set_instance_error_state(context, instance['uuid']) # NOTE(vish) get bdms before destroying the instance vol_bdms = self._get_volume_bdms(bdms) @@ -1556,10 +1588,14 @@ class ComputeManager(manager.SchedulerDependentManager): # Fall through and reset task_state to None current_power_state = self._get_power_state(context, instance) - instance = self._instance_update(context, instance['uuid'], - power_state=current_power_state, - vm_state=vm_states.ACTIVE, - task_state=None) + try: + instance = self._instance_update(context, instance['uuid'], + power_state=current_power_state, + vm_state=vm_states.ACTIVE, + task_state=None) + except exception.InstanceNotFound: + LOG.warn(_("Instance disappeared during reboot"), + context=context, instance=instance) self._notify_about_instance_usage(context, instance, "reboot.end") @@ -2324,6 +2360,10 @@ class ComputeManager(manager.SchedulerDependentManager): network_info = self._inject_network_info(context, instance=instance) self.reset_network(context, instance) + # NOTE(russellb) We just want to bump updated_at. See bug 1143466. + self._instance_update(context, instance['uuid'], + updated_at=timeutils.utcnow()) + self._notify_about_instance_usage( context, instance, "create_ip.end", network_info=network_info) @@ -2345,6 +2385,10 @@ class ComputeManager(manager.SchedulerDependentManager): instance=instance) self.reset_network(context, instance) + # NOTE(russellb) We just want to bump updated_at. See bug 1143466. + self._instance_update(context, instance['uuid'], + updated_at=timeutils.utcnow()) + self._notify_about_instance_usage( context, instance, "delete_ip.end", network_info=network_info) @@ -2763,13 +2807,15 @@ class ComputeManager(manager.SchedulerDependentManager): network_info = self.network_api.allocate_port_for_instance( context, instance, port_id, network_id, requested_ip, self.conductor_api) + if len(network_info) != 1: + LOG.error(_('allocate_port_for_instance returned %(port)s ports') % + dict(ports=len(network_info))) + raise exception.InterfaceAttachFailed(instance=instance) image_meta = _get_image_meta(context, instance['image_ref']) legacy_net_info = self._legacy_nw_info(network_info) - for (network, mapping) in legacy_net_info: - if mapping['vif_uuid'] == port_id: - self.driver.attach_interface(instance, image_meta, - [(network, mapping)]) - return (network, mapping) + (network, mapping) = legacy_net_info[0] + self.driver.attach_interface(instance, image_meta, legacy_net_info) + return legacy_net_info[0] def detach_interface(self, context, instance, port_id): """Detach an network adapter from an instance.""" @@ -3647,11 +3693,18 @@ class ComputeManager(manager.SchedulerDependentManager): :param context: security context """ new_resource_tracker_dict = {} - nodenames = self.driver.get_available_nodes() + nodenames = set(self.driver.get_available_nodes()) for nodename in nodenames: rt = self._get_resource_tracker(nodename) rt.update_available_resource(context) new_resource_tracker_dict[nodename] = rt + + # delete nodes that the driver no longer reports + known_nodes = set(self._resource_tracker_dict.keys()) + for nodename in known_nodes - nodenames: + rt = self._get_resource_tracker(nodename) + rt.update_available_resource(context, delete=True) + self._resource_tracker_dict = new_resource_tracker_dict @manager.periodic_task(spacing=CONF.running_deleted_instance_poll_interval) @@ -3710,22 +3763,20 @@ class ComputeManager(manager.SchedulerDependentManager): def _running_deleted_instances(self, context): """Returns a list of instances nova thinks is deleted, - but the hypervisor thinks is still running. This method - should be pushed down to the virt layer for efficiency. + but the hypervisor thinks is still running. """ + timeout = CONF.running_deleted_instance_timeout + def deleted_instance(instance): - timeout = CONF.running_deleted_instance_timeout - present = instance['name'] in present_name_labels - erroneously_running = instance['deleted'] and present + erroneously_running = instance['deleted'] old_enough = (not instance['deleted_at'] or timeutils.is_older_than(instance['deleted_at'], timeout)) if erroneously_running and old_enough: return True return False - present_name_labels = set(self.driver.list_instances()) - instances = self.conductor_api.instance_get_all_by_host(context, - self.host) + + instances = self._get_instances_on_driver(context) return [i for i in instances if deleted_instance(i)] @contextlib.contextmanager diff --git a/nova/compute/resource_tracker.py b/nova/compute/resource_tracker.py index efb95dd7b..fab64017d 100644 --- a/nova/compute/resource_tracker.py +++ b/nova/compute/resource_tracker.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -226,7 +226,7 @@ class ResourceTracker(object): return self.compute_node is None @lockutils.synchronized(COMPUTE_RESOURCE_SEMAPHORE, 'nova-') - def update_available_resource(self, context): + def update_available_resource(self, context, delete=False): """Override in-memory calculations of compute node resource usage based on data audited from the hypervisor layer. @@ -237,11 +237,15 @@ class ResourceTracker(object): LOG.audit(_("Auditing locally available compute resources")) resources = self.driver.get_available_resource(self.nodename) if not resources: - # The virt driver does not support this function - LOG.audit(_("Virt driver does not support " - "'get_available_resource' Compute tracking is disabled.")) - self.compute_node = None - return + if delete: + self._delete_compute_node(context) + return + else: + # The virt driver does not support this function + LOG.audit(_("Virt driver does not support " + "'get_available_resource' Compute tracking is disabled.")) + self.compute_node = None + return self._verify_resources(resources) @@ -270,6 +274,13 @@ class ResourceTracker(object): self._sync_compute_node(context, resources) + def _delete_compute_node(self, context): + """Delete a compute node DB record.""" + if self.compute_node: + LOG.audit(_("Deleting compute node %s") % self.compute_node['id']) + self.compute_node = self.conductor_api.compute_node_delete( + context, self.compute_node) + def _sync_compute_node(self, context, resources): """Create or update the compute node DB record.""" if not self.compute_node: diff --git a/nova/compute/rpcapi.py b/nova/compute/rpcapi.py index 67dfc6a6b..914c45471 100644 --- a/nova/compute/rpcapi.py +++ b/nova/compute/rpcapi.py @@ -50,9 +50,9 @@ def _compute_topic(topic, ctxt, host, instance): if not instance: raise exception.NovaException(_('No compute host specified')) host = instance['host'] - if not host: - raise exception.NovaException(_('Unable to find host for ' - 'Instance %s') % instance['uuid']) + if not host: + raise exception.NovaException(_('Unable to find host for ' + 'Instance %s') % instance['uuid']) return rpc.queue_get_for(ctxt, topic, host) diff --git a/nova/compute/stats.py b/nova/compute/stats.py index b6a30d38f..0d0c7b97c 100644 --- a/nova/compute/stats.py +++ b/nova/compute/stats.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/compute/task_states.py b/nova/compute/task_states.py index 8e2b8344a..6787761e9 100644 --- a/nova/compute/task_states.py +++ b/nova/compute/task_states.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/compute/utils.py b/nova/compute/utils.py index 8c1f1d577..bd4cd869e 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/compute/vm_mode.py b/nova/compute/vm_mode.py index cc1ca6978..71da62b45 100644 --- a/nova/compute/vm_mode.py +++ b/nova/compute/vm_mode.py @@ -29,7 +29,7 @@ choose what sort of VM to boot. from nova import exception -HVM = "hvm" # Fully virtualizated +HVM = "hvm" # Fully virtualized XEN = "xen" # Xen 3.0 paravirtualized UML = "uml" # User Mode Linux paravirtualized EXE = "exe" # Executables in containers diff --git a/nova/compute/vm_states.py b/nova/compute/vm_states.py index 94a566cce..249b693bc 100644 --- a/nova/compute/vm_states.py +++ b/nova/compute/vm_states.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/conductor/api.py b/nova/conductor/api.py index 6bc2d3f25..0b46c3d2f 100644 --- a/nova/conductor/api.py +++ b/nova/conductor/api.py @@ -276,6 +276,9 @@ class LocalAPI(object): return self._manager.compute_node_update(context, node, values, prune_stats) + def compute_node_delete(self, context, node): + return self._manager.compute_node_delete(context, node) + def service_update(self, context, service, values): return self._manager.service_update(context, service, values) @@ -364,7 +367,7 @@ class API(object): self.ping(context, '1.21 GigaWatts', timeout=timeout) break except rpc_common.Timeout as e: - LOG.exception(_('Timed out waiting for nova-conductor. ' + LOG.warning(_('Timed out waiting for nova-conductor. ' 'Is it running? Or did this service start ' 'before nova-conductor?')) @@ -605,6 +608,9 @@ class API(object): return self.conductor_rpcapi.compute_node_update(context, node, values, prune_stats) + def compute_node_delete(self, context, node): + return self.conductor_rpcapi.compute_node_delete(context, node) + def service_update(self, context, service, values): return self.conductor_rpcapi.service_update(context, service, values) diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py index 1c54b1f0b..2a0853491 100644 --- a/nova/conductor/manager.py +++ b/nova/conductor/manager.py @@ -39,17 +39,17 @@ allowed_updates = ['task_state', 'vm_state', 'expected_task_state', 'instance_type_id', 'root_device_name', 'launched_on', 'progress', 'vm_mode', 'default_ephemeral_device', 'default_swap_device', 'root_device_name', - 'system_metadata', + 'system_metadata', 'updated_at' ] # Fields that we want to convert back into a datetime object. -datetime_fields = ['launched_at', 'terminated_at'] +datetime_fields = ['launched_at', 'terminated_at', 'updated_at'] class ConductorManager(manager.SchedulerDependentManager): """Mission: TBD.""" - RPC_API_VERSION = '1.43' + RPC_API_VERSION = '1.44' def __init__(self, *args, **kwargs): super(ConductorManager, self).__init__(service_name='conductor', @@ -352,6 +352,10 @@ class ConductorManager(manager.SchedulerDependentManager): prune_stats) return jsonutils.to_primitive(result) + def compute_node_delete(self, context, node): + result = self.db.compute_node_delete(context, node['id']) + return jsonutils.to_primitive(result) + @rpc_common.client_exceptions(exception.ServiceNotFound) def service_update(self, context, service, values): svc = self.db.service_update(context, service['id'], values) diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py index f7b7a7814..6c0705e8b 100644 --- a/nova/conductor/rpcapi.py +++ b/nova/conductor/rpcapi.py @@ -81,6 +81,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): quota_rollback 1.42 - Added get_ec2_ids, aggregate_metadata_get_by_host 1.43 - Added compute_stop + 1.44 - Added compute_node_delete """ BASE_RPC_API_VERSION = '1.0' @@ -346,6 +347,11 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy): prune_stats=prune_stats) return self.call(context, msg, version='1.33') + def compute_node_delete(self, context, node): + node_p = jsonutils.to_primitive(node) + msg = self.make_msg('compute_node_delete', node=node_p) + return self.call(context, msg, version='1.44') + def service_update(self, context, service, values): service_p = jsonutils.to_primitive(service) msg = self.make_msg('service_update', service=service_p, values=values) diff --git a/nova/console/api.py b/nova/console/api.py index a2bc40ae0..91966a7ff 100644 --- a/nova/console/api.py +++ b/nova/console/api.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/console/fake.py b/nova/console/fake.py index e97d545ea..7e96f43f3 100644 --- a/nova/console/fake.py +++ b/nova/console/fake.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/console/manager.py b/nova/console/manager.py index 77be2ad4d..32fa75261 100644 --- a/nova/console/manager.py +++ b/nova/console/manager.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/console/vmrc.py b/nova/console/vmrc.py index d7c66a00d..ed3a2afb3 100644 --- a/nova/console/vmrc.py +++ b/nova/console/vmrc.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/console/vmrc_manager.py b/nova/console/vmrc_manager.py index f1ea41796..28d23ce9c 100644 --- a/nova/console/vmrc_manager.py +++ b/nova/console/vmrc_manager.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/console/websocketproxy.py b/nova/console/websocketproxy.py index ce9243d46..f7fdea173 100644 --- a/nova/console/websocketproxy.py +++ b/nova/console/websocketproxy.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/console/xvp.py b/nova/console/xvp.py index c090e84d4..1e9fbcb5d 100644 --- a/nova/console/xvp.py +++ b/nova/console/xvp.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -26,6 +26,7 @@ from oslo.config import cfg from nova import context from nova import db from nova import exception +from nova.openstack.common import excutils from nova.openstack.common import log as logging from nova import paths from nova import utils @@ -119,8 +120,8 @@ class XVPConsoleProxy(object): with open(CONF.console_xvp_conf, 'w') as cfile: cfile.write(config) except IOError: - LOG.exception(_("Failed to write configuration file")) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_("Failed to write configuration file")) def _xvp_stop(self): LOG.debug(_('Stopping xvp')) diff --git a/nova/consoleauth/__init__.py b/nova/consoleauth/__init__.py index 3100ee15c..0b231f56e 100644 --- a/nova/consoleauth/__init__.py +++ b/nova/consoleauth/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/consoleauth/manager.py b/nova/consoleauth/manager.py index 56e94dffd..fe5bfd861 100644 --- a/nova/consoleauth/manager.py +++ b/nova/consoleauth/manager.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,12 +22,12 @@ import time from oslo.config import cfg -from nova.common import memorycache from nova.compute import rpcapi as compute_rpcapi from nova.conductor import api as conductor_api from nova import manager from nova.openstack.common import jsonutils from nova.openstack.common import log as logging +from nova.openstack.common import memorycache LOG = logging.getLogger(__name__) diff --git a/nova/context.py b/nova/context.py index 831a91b11..714948e90 100644 --- a/nova/context.py +++ b/nova/context.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/nova/crypto.py b/nova/crypto.py index 4d72aa624..736e99961 100644 --- a/nova/crypto.py +++ b/nova/crypto.py @@ -38,6 +38,7 @@ from pyasn1.type import univ from nova import context from nova import db from nova import exception +from nova.openstack.common import excutils from nova.openstack.common import fileutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils @@ -387,8 +388,8 @@ def _sign_csr(csr_text, ca_folder): with open(inbound, 'w') as csrfile: csrfile.write(csr_text) except IOError: - LOG.exception(_('Failed to write inbound.csr')) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_('Failed to write inbound.csr')) LOG.debug(_('Flags path: %s'), ca_folder) start = os.getcwd() diff --git a/nova/db/api.py b/nova/db/api.py index d14999b45..fd932c9ef 100644 --- a/nova/db/api.py +++ b/nova/db/api.py @@ -195,11 +195,19 @@ def compute_node_create(context, values): def compute_node_update(context, compute_id, values, prune_stats=False): """Set the given properties on a computeNode and update it. - Raises NotFound if computeNode does not exist. + Raises ComputeHostNotFound if computeNode does not exist. """ return IMPL.compute_node_update(context, compute_id, values, prune_stats) +def compute_node_delete(context, compute_id): + """Delete a computeNode from the database. + + Raises ComputeHostNotFound if computeNode does not exist. + """ + return IMPL.compute_node_delete(context, compute_id) + + def compute_node_get_by_host(context, host): return IMPL.compute_node_get_by_host(context, host) @@ -627,11 +635,6 @@ def instance_get_all_by_host_and_not_type(context, host, type_id=None): return IMPL.instance_get_all_by_host_and_not_type(context, host, type_id) -def instance_get_all_by_reservation(context, reservation_id): - """Get all instances belonging to a reservation.""" - return IMPL.instance_get_all_by_reservation(context, reservation_id) - - def instance_get_floating_address(context, instance_id): """Get the first floating ip address of an instance.""" return IMPL.instance_get_floating_address(context, instance_id) @@ -872,25 +875,6 @@ def network_update(context, network_id, values): return IMPL.network_update(context, network_id, values) -################### - - -def iscsi_target_count_by_host(context, host): - """Return count of export devices.""" - return IMPL.iscsi_target_count_by_host(context, host) - - -def iscsi_target_create_safe(context, values): - """Create an iscsi_target from the values dictionary. - - The device is not returned. If the create violates the unique - constraints because the iscsi_target and host already exist, - no exception is raised. - - """ - return IMPL.iscsi_target_create_safe(context, values) - - ############### @@ -970,11 +954,6 @@ def reservation_get(context, uuid): return IMPL.reservation_get(context, uuid) -def reservation_destroy(context, uuid): - """Destroy the reservation or raise if it does not exist.""" - return IMPL.reservation_destroy(context, uuid) - - ################### @@ -1010,11 +989,6 @@ def reservation_expire(context): ################### -def volume_get_iscsi_target_num(context, volume_id): - """Get the target num (tid) allocated to the volume.""" - return IMPL.volume_get_iscsi_target_num(context, volume_id) - - def get_ec2_volume_id_by_uuid(context, volume_id): return IMPL.get_ec2_volume_id_by_uuid(context, volume_id) diff --git a/nova/db/sqlalchemy/api.py b/nova/db/sqlalchemy/api.py index 1baa192a3..96c77bce3 100644 --- a/nova/db/sqlalchemy/api.py +++ b/nova/db/sqlalchemy/api.py @@ -30,8 +30,7 @@ import uuid from oslo.config import cfg from sqlalchemy import and_ from sqlalchemy import Boolean -from sqlalchemy import exc as sqla_exc -from sqlalchemy.exc import IntegrityError +from sqlalchemy.exc import DataError from sqlalchemy.exc import NoSuchTableError from sqlalchemy import Integer from sqlalchemy import MetaData @@ -52,6 +51,7 @@ import nova.context from nova import db from nova.db.sqlalchemy import models from nova import exception +from nova.openstack.common.db import exception as db_exc from nova.openstack.common.db.sqlalchemy import session as db_session from nova.openstack.common.db.sqlalchemy import utils as sqlalchemyutils from nova.openstack.common import log as logging @@ -143,30 +143,15 @@ def require_aggregate_exists(f): def _retry_on_deadlock(f): """Decorator to retry a DB API call if Deadlock was received.""" - def _is_deadlock_exc(dberr_info): - deadlock_str = 'Deadlock found when trying to get lock' - try: - if not isinstance(dberr_info, sqla_exc.OperationalError): - return False - if deadlock_str in dberr_info.message: - LOG.warn(_("Deadlock detected when running " - "'%(func_name)s': Retrying..."), - dict(func_name=f.__name__)) - return True - except Exception: - pass - return False - @functools.wraps(f) def wrapped(*args, **kwargs): while True: try: return f(*args, **kwargs) - except db_session.DBError as db_err: - exc_info = sys.exc_info() - dberr_info = db_err.inner_exception - if not _is_deadlock_exc(dberr_info): - raise exc_info[0], exc_info[1], exc_info[2] + except db_exc.DBDeadlock: + LOG.warn(_("Deadlock detected when running " + "'%(func_name)s': Retrying..."), + dict(func_name=f.__name__)) # Retry! time.sleep(0.5) continue @@ -550,6 +535,17 @@ def compute_node_update(context, compute_id, values, prune_stats=False): return compute_ref +@require_admin_context +def compute_node_delete(context, compute_id): + """Delete a ComputeNode record.""" + result = model_query(context, models.ComputeNode).\ + filter_by(id=compute_id).\ + soft_delete() + + if not result: + raise exception.ComputeHostNotFound(host=compute_id) + + def compute_node_get_by_host(context, host): """Get all capacity entries for the given host.""" result = model_query(context, models.ComputeNode, read_deleted="no").\ @@ -759,6 +755,7 @@ def floating_ip_count_by_project(context, project_id, session=None): @require_context +@_retry_on_deadlock def floating_ip_fixed_ip_associate(context, floating_address, fixed_address, host): session = get_session() @@ -1264,7 +1261,7 @@ def virtual_interface_create(context, values): vif_ref = models.VirtualInterface() vif_ref.update(values) vif_ref.save() - except db_session.DBError: + except db_exc.DBError: raise exception.VirtualInterfaceCreateException() return vif_ref @@ -1373,17 +1370,19 @@ def _validate_unique_server_name(context, session, name): if not CONF.osapi_compute_unique_server_name_scope: return - search_opts = {'deleted': False} + lowername = name.lower() + base_query = model_query(context, models.Instance, session=session, + read_deleted=False).\ + filter(func.lower(models.Instance.hostname) == lowername) + if CONF.osapi_compute_unique_server_name_scope == 'project': - search_opts['project_id'] = context.project_id - instance_list = instance_get_all_by_filters(context, search_opts, - 'created_at', 'desc', - session=session) + instance_with_same_name = base_query.\ + filter_by(project_id=context.project_id).\ + count() + elif CONF.osapi_compute_unique_server_name_scope == 'global': - instance_list = instance_get_all_by_filters(context.elevated(), - search_opts, - 'created_at', 'desc', - session=session) + instance_with_same_name = base_query.count() + else: msg = _('Unknown osapi_compute_unique_server_name_scope value: %s' ' Flag must be empty, "global" or' @@ -1391,10 +1390,8 @@ def _validate_unique_server_name(context, session, name): LOG.warn(msg) return - lowername = name.lower() - for instance in instance_list: - if instance['hostname'].lower() == lowername: - raise exception.InstanceExists(name=instance['hostname']) + if instance_with_same_name > 0: + raise exception.InstanceExists(name=lowername) @require_context @@ -1511,14 +1508,19 @@ def _instance_get_by_uuid(context, uuid, session=None): @require_context def instance_get(context, instance_id): - result = _build_instance_get(context).\ - filter_by(id=instance_id).\ - first() + try: + result = _build_instance_get(context).filter_by(id=instance_id).first() - if not result: - raise exception.InstanceNotFound(instance_id=instance_id) + if not result: + raise exception.InstanceNotFound(instance_id=instance_id) - return result + return result + except DataError: + # NOTE(sdague): catch all in case the db engine chokes on the + # id because it's too long of an int to store. + msg = _("Invalid instance id %s in request") % instance_id + LOG.warn(msg) + raise exception.InvalidID(id=instance_id) @require_context @@ -1706,13 +1708,6 @@ def instance_get_all_by_host_and_not_type(context, host, type_id=None): filter(models.Instance.instance_type_id != type_id).all() -@require_context -def instance_get_all_by_reservation(context, reservation_id): - return _instance_get_all_query(context, project_only=True).\ - filter_by(reservation_id=reservation_id).\ - all() - - # NOTE(jkoelker) This is only being left here for compat with floating # ips. Currently the network_api doesn't return floaters # in network_info. Once it starts return the model. This @@ -1821,18 +1816,6 @@ def _instance_update(context, instance_uuid, values, copy_old_instance=False): with session.begin(): instance_ref = _instance_get_by_uuid(context, instance_uuid, session=session) - # TODO(deva): remove extra_specs from here after it is included - # in system_metadata. Until then, the baremetal driver - # needs extra_specs added to instance[] - inst_type_ref = _instance_type_get_query(context, session=session).\ - filter_by(id=instance_ref['instance_type_id']).\ - first() - if inst_type_ref: - instance_ref['extra_specs'] = \ - _dict_with_extra_specs(inst_type_ref).get('extra_specs', {}) - else: - instance_ref['extra_specs'] = {} - if "expected_task_state" in values: # it is not a db column so always pop out expected = values.pop("expected_task_state") @@ -1930,15 +1913,15 @@ def instance_info_cache_update(context, instance_uuid, values): session=session).\ filter_by(instance_uuid=instance_uuid).\ first() - - if info_cache and not info_cache['deleted']: - # NOTE(tr3buchet): let's leave it alone if it's already deleted - info_cache.update(values) - else: + if info_cache and info_cache['deleted']: + raise exception.InstanceInfoCacheNotFound( + instance_uuid=instance_uuid) + elif not info_cache: # NOTE(tr3buchet): just in case someone blows away an instance's - # cache entry + # cache entry, re-create it. info_cache = models.InstanceInfoCache() - info_cache.update({'instance_uuid': instance_uuid}) + values['instance_uuid'] = instance_uuid + info_cache.update(values) return info_cache @@ -2079,7 +2062,7 @@ def network_create_safe(context, values): try: network_ref.save() return network_ref - except db_session.DBDuplicateEntry: + except db_exc.DBDuplicateEntry: raise exception.DuplicateVlan(vlan=values['vlan']) @@ -2321,7 +2304,7 @@ def network_update(context, network_id, values): network_ref.update(values) try: network_ref.save(session=session) - except db_session.DBDuplicateEntry: + except db_exc.DBDuplicateEntry: raise exception.DuplicateVlan(vlan=values['vlan']) return network_ref @@ -2329,29 +2312,6 @@ def network_update(context, network_id, values): ################### -@require_admin_context -def iscsi_target_count_by_host(context, host): - return model_query(context, models.IscsiTarget).\ - filter_by(host=host).\ - count() - - -@require_admin_context -def iscsi_target_create_safe(context, values): - iscsi_target_ref = models.IscsiTarget() - - for (key, value) in values.iteritems(): - iscsi_target_ref[key] = value - try: - iscsi_target_ref.save() - return iscsi_target_ref - except IntegrityError: - return None - - -################### - - @require_context def quota_get(context, project_id, resource): result = model_query(context, models.Quota, read_deleted="no").\ @@ -2547,16 +2507,6 @@ def reservation_create(context, uuid, usage, project_id, resource, delta, return reservation_ref -@require_admin_context -def reservation_destroy(context, uuid): - result = model_query(context, models.Reservation, read_deleted="no").\ - filter_by(uuid=uuid).\ - delete() - - if not result: - raise exception.ReservationNotFound(uuid=uuid) - - ################### @@ -2804,18 +2754,6 @@ def _ec2_snapshot_get_query(context, session=None): session=session, read_deleted='yes') -@require_admin_context -def volume_get_iscsi_target_num(context, volume_id): - result = model_query(context, models.IscsiTarget, read_deleted="yes").\ - filter_by(volume_id=volume_id).\ - first() - - if not result: - raise exception.ISCSITargetNotFoundForVolume(volume_id=volume_id) - - return result.target_num - - @require_context def ec2_volume_create(context, volume_uuid, id=None): """Create ec2 compatible volume by provided uuid.""" @@ -3547,7 +3485,7 @@ def instance_type_create(context, values): instance_type_ref.update(values) instance_type_ref.save(session=session) except Exception, e: - raise db_session.DBError(e) + raise db_exc.DBError(e) return _dict_with_extra_specs(instance_type_ref) @@ -4209,7 +4147,7 @@ def s3_image_create(context, image_uuid): s3_image_ref.update({'uuid': image_uuid}) s3_image_ref.save() except Exception, e: - raise db_session.DBError(e) + raise db_exc.DBError(e) return s3_image_ref @@ -4242,7 +4180,7 @@ def aggregate_create(context, values, metadata=None): values['name'], session=session, read_deleted='no') - aggregate = query.options(joinedload('_metadata')).first() + aggregate = query.first() if not aggregate: aggregate = models.Aggregate() aggregate.update(values) @@ -4264,7 +4202,7 @@ def aggregate_get(context, aggregate_id): models.Aggregate, models.Aggregate.id, aggregate_id) - aggregate = query.options(joinedload('_metadata')).first() + aggregate = query.first() if not aggregate: raise exception.AggregateNotFound(aggregate_id=aggregate_id) @@ -4318,8 +4256,7 @@ def aggregate_update(context, aggregate_id, values): models.Aggregate, models.Aggregate.id, aggregate_id, - session=session). - options(joinedload('_metadata')).first()) + session=session).first()) if aggregate: if "availability_zone" in values: @@ -4614,6 +4551,10 @@ def action_event_finish(context, values): raise exception.InstanceActionEventNotFound(action_id=action['id'], event=values['event']) event_ref.update(values) + + if values['result'].lower() == 'error': + action.update({'message': 'Error'}) + return event_ref @@ -4729,7 +4670,7 @@ def task_log_begin_task(context, task_name, period_beginning, period_ending, task.task_items = task_items try: task.save() - except db_session.DBDuplicateEntry: + except db_exc.DBDuplicateEntry: raise exception.TaskAlreadyRunning(task_name=task_name, host=host) @@ -4767,15 +4708,13 @@ def _get_default_deleted_value(table): @require_admin_context -def archive_deleted_rows_for_table(context, tablename, max_rows=None): +def archive_deleted_rows_for_table(context, tablename, max_rows): """Move up to max_rows rows from one tables to the corresponding shadow table. :returns: number of rows archived """ # The context argument is only used for the decorator. - if max_rows is None: - max_rows = 5000 engine = get_engine() conn = engine.connect() metadata = MetaData() @@ -4826,8 +4765,6 @@ def archive_deleted_rows(context, max_rows=None): :returns: Number of rows archived. """ # The context argument is only used for the decorator. - if max_rows is None: - max_rows = 5000 tablenames = [] for model_class in models.__dict__.itervalues(): if hasattr(model_class, "__tablename__"): diff --git a/nova/db/sqlalchemy/migrate_repo/__init__.py b/nova/db/sqlalchemy/migrate_repo/__init__.py index 4cad9a01b..74704e5e6 100644 --- a/nova/db/sqlalchemy/migrate_repo/__init__.py +++ b/nova/db/sqlalchemy/migrate_repo/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/manage.py b/nova/db/sqlalchemy/migrate_repo/manage.py index f4b31bbe4..3ff394182 100644 --- a/nova/db/sqlalchemy/migrate_repo/manage.py +++ b/nova/db/sqlalchemy/migrate_repo/manage.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/133_folsom.py b/nova/db/sqlalchemy/migrate_repo/versions/133_folsom.py index 44eac3695..1b688a883 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/133_folsom.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/133_folsom.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -1222,4 +1222,4 @@ def upgrade(migrate_engine): def downgrade(migrate_engine): - LOG.exception(_('Downgrade from Folsom is unsupported.')) + raise NotImplementedError('Downgrade from Folsom is unsupported.') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/134_add_counters_to_bw_usage_cache.py b/nova/db/sqlalchemy/migrate_repo/versions/134_add_counters_to_bw_usage_cache.py index 985149e91..b4178e3c7 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/134_add_counters_to_bw_usage_cache.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/134_add_counters_to_bw_usage_cache.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/135_add_node_to_instances.py b/nova/db/sqlalchemy/migrate_repo/versions/135_add_node_to_instances.py index c30cdecdc..331183d3b 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/135_add_node_to_instances.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/135_add_node_to_instances.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/136_add_index_to_instances.py b/nova/db/sqlalchemy/migrate_repo/versions/136_add_index_to_instances.py index 397f8a62b..d3969a9c4 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/136_add_index_to_instances.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/136_add_index_to_instances.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py index 1499bd351..7dde6e83e 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/137_add_indexes_to_migrations.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/db/sqlalchemy/migrate_repo/versions/138_drop_server_name_from_instances.py b/nova/db/sqlalchemy/migrate_repo/versions/138_drop_server_name_from_instances.py index 2faae3a8e..d8d043b40 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/138_drop_server_name_from_instances.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/138_drop_server_name_from_instances.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/139_add_indexes_to_fixed_ips.py b/nova/db/sqlalchemy/migrate_repo/versions/139_add_indexes_to_fixed_ips.py index 8a471c057..af50fced5 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/139_add_indexes_to_fixed_ips.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/139_add_indexes_to_fixed_ips.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/db/sqlalchemy/migrate_repo/versions/144_add_node_to_migrations.py b/nova/db/sqlalchemy/migrate_repo/versions/144_add_node_to_migrations.py index 692f9599b..14ac0c5e6 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/144_add_node_to_migrations.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/144_add_node_to_migrations.py @@ -1,4 +1,4 @@ -# Copyright 2012 Openstack LLC. +# Copyright 2012 Openstack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/145_add_volume_usage_cache.py b/nova/db/sqlalchemy/migrate_repo/versions/145_add_volume_usage_cache.py index 7adbcb938..41c4b6097 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/145_add_volume_usage_cache.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/145_add_volume_usage_cache.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/146_aggregate_zones.py b/nova/db/sqlalchemy/migrate_repo/versions/146_aggregate_zones.py index f1cfaf5c6..0f39bf231 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/146_aggregate_zones.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/146_aggregate_zones.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py b/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py index d93cd1ead..a0ad90d4e 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/147_no_service_zones.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -58,8 +58,12 @@ def upgrade(migrate_engine): }) # add host to zone agg_hosts = Table('aggregate_hosts', meta, autoload=True) - row = agg_hosts.insert() - row.execute({'host': rec['host'], 'aggregate_id': agg_id}) + num_hosts = agg_hosts.count().where( + agg_hosts.c.host == rec['host']).where( + agg_hosts.c.aggregate_id == agg_id).execute().scalar() + if num_hosts == 0: + agg_hosts.insert().execute({'host': rec['host'], + 'aggregate_id': agg_id}) services.drop_column('availability_zone') diff --git a/nova/db/sqlalchemy/migrate_repo/versions/148_add_instance_actions.py b/nova/db/sqlalchemy/migrate_repo/versions/148_add_instance_actions.py index 6adfb1dc1..5e60d41cc 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/148_add_instance_actions.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/148_add_instance_actions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -68,14 +68,8 @@ def upgrade(migrate_engine): mysql_charset='utf8', ) - try: - instance_actions.create() - instance_actions_events.create() - except Exception: - LOG.exception("Exception while creating table 'instance_actions' or " - "'instance_actions_events'") - meta.drop_all(tables=[instance_actions, instance_actions_events]) - raise + instance_actions.create() + instance_actions_events.create() Index('instance_uuid_idx', instance_actions.c.instance_uuid).create(migrate_engine) @@ -87,15 +81,9 @@ def downgrade(migrate_engine): meta = MetaData() meta.bind = migrate_engine - try: - instance_actions = Table('instance_actions', meta, autoload=True) - instance_actions.drop() - except Exception: - LOG.exception("Exception dropping table 'instance_actions'") + instance_actions_events = Table('instance_actions_events', meta, + autoload=True) + instance_actions_events.drop() - try: - instance_actions_events = Table('instance_actions_events', meta, - autoload=True) - instance_actions_events.drop() - except Exception: - LOG.exception("Exception dropping table 'instance_actions_events") + instance_actions = Table('instance_actions', meta, autoload=True) + instance_actions.drop() diff --git a/nova/db/sqlalchemy/migrate_repo/versions/149_inet_datatype_for_postgres.py b/nova/db/sqlalchemy/migrate_repo/versions/149_inet_datatype_for_postgres.py index 3eb26ac7d..79ad6f014 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/149_inet_datatype_for_postgres.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/149_inet_datatype_for_postgres.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/db/sqlalchemy/migrate_repo/versions/150_add_host_to_instance_faults.py b/nova/db/sqlalchemy/migrate_repo/versions/150_add_host_to_instance_faults.py index 3fd87e1e1..99583c098 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/150_add_host_to_instance_faults.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/150_add_host_to_instance_faults.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/migrate_repo/versions/159_revert_ip_column_length.py b/nova/db/sqlalchemy/migrate_repo/versions/159_revert_ip_column_length.py new file mode 100644 index 000000000..65e11c42c --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/159_revert_ip_column_length.py @@ -0,0 +1,63 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 IBM Corp. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from sqlalchemy import MetaData, String, Table +from sqlalchemy.dialects import postgresql + +TABLE_COLUMNS = [ + # table name, column name + ('instances', 'access_ip_v4'), + ('instances', 'access_ip_v6'), + ('networks', 'gateway'), + ('networks', 'gateway_v6'), + ('networks', 'netmask'), + ('networks', 'netmask_v6'), + ('networks', 'broadcast'), + ('networks', 'dns1'), + ('networks', 'dns2'), + ('networks', 'vpn_public_address'), + ('networks', 'vpn_private_address'), + ('networks', 'dhcp_start'), + ('fixed_ips', 'address'), + ('floating_ips', 'address'), + ('console_pools', 'address')] + + +def upgrade(migrate_engine): + dialect = migrate_engine.url.get_dialect() + + # NOTE(maurosr): this just affects mysql; postgresql uses INET + # type and sqlite doesn't goes fine with alter tables, so it should be done + # manually. This way we'll be able to keep UCs like the one inserted on + # version 158 which would get lost cause sqlite is not migrated as mysql or + # pgsql, it copies the column and data instead of execute an alter table + # command. + if dialect is not postgresql.dialect: + meta = MetaData(bind=migrate_engine) + for table, column in TABLE_COLUMNS: + t = Table(table, meta, autoload=True) + getattr(t.c, column).alter(type=String(39)) + + +def downgrade(migrate_engine): + """Convert columns back to the larger String(43) defined in version 149.""" + dialect = migrate_engine.url.get_dialect() + if dialect is not postgresql.dialect: + meta = MetaData(bind=migrate_engine) + for table, column in TABLE_COLUMNS: + t = Table(table, meta, autoload=True) + getattr(t.c, column).alter(type=String(43)) diff --git a/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_downgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_downgrade.sql new file mode 100644 index 000000000..381d8f26b --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_downgrade.sql @@ -0,0 +1,81 @@ +BEGIN TRANSACTION; + /* create networks_backup table with the fields like networks was before + the upgrade */ + CREATE TABLE networks_backup( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted INTEGER, + id INTEGER NOT NULL, + injected BOOLEAN, + cidr VARCHAR(43), + netmask VARCHAR(43), + bridge VARCHAR(255), + gateway VARCHAR(43), + broadcast VARCHAR(43), + dns1 VARCHAR(43), + vlan INTEGER, + vpn_public_address VARCHAR(43), + vpn_public_port INTEGER, + vpn_private_address VARCHAR(43), + dhcp_start VARCHAR(43), + project_id VARCHAR(255), + host VARCHAR(255), + cidr_v6 VARCHAR(43), + gateway_v6 VARCHAR(43), + label VARCHAR(255), + netmask_v6 VARCHAR(43), + bridge_interface VARCHAR(255), + multi_host BOOLEAN, + dns2 VARCHAR(43), + uuid VARCHAR(36), + priority INTEGER, + rxtx_base INTEGER, + PRIMARY KEY (id) + ); + + /* copy data currently on networks to the backup table and drop networks + table */ + INSERT INTO networks_backup SELECT * FROM networks; + DROP TABLE networks; + + CREATE TABLE networks ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted INTEGER, + id INTEGER NOT NULL, + injected BOOLEAN, + cidr VARCHAR(43), + netmask VARCHAR(43), + bridge VARCHAR(255), + gateway VARCHAR(43), + broadcast VARCHAR(43), + dns1 VARCHAR(43), + vlan INTEGER, + vpn_public_address VARCHAR(43), + vpn_public_port INTEGER, + vpn_private_address VARCHAR(43), + dhcp_start VARCHAR(43), + project_id VARCHAR(255), + host VARCHAR(255), + cidr_v6 VARCHAR(43), + gateway_v6 VARCHAR(43), + label VARCHAR(255), + netmask_v6 VARCHAR(43), + bridge_interface VARCHAR(255), + multi_host BOOLEAN, + dns2 VARCHAR(43), + uuid VARCHAR(36), + priority INTEGER, + rxtx_base INTEGER, + PRIMARY KEY (id), + CHECK (injected IN (0, 1)), + CHECK (multi_host IN (0, 1)), + CONSTRAINT uniq_vlan_x_deleted UNIQUE (vlan, deleted) +); + + /* Get data from backup table and drop it next */ + INSERT INTO networks SELECT * FROM networks_backup; + DROP TABLE networks_backup; +COMMIT; diff --git a/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_upgrade.sql b/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_upgrade.sql new file mode 100644 index 000000000..206155baa --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/159_sqlite_upgrade.sql @@ -0,0 +1,79 @@ +BEGIN TRANSACTION; + /* Create a backup table with the new fields size */ + CREATE TABLE networks_backup( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted INTEGER, + id INTEGER NOT NULL, + injected BOOLEAN, + cidr VARCHAR(43), + netmask VARCHAR(39), + bridge VARCHAR(255), + gateway VARCHAR(39), + broadcast VARCHAR(39), + dns1 VARCHAR(39), + vlan INTEGER, + vpn_public_address VARCHAR(39), + vpn_public_port INTEGER, + vpn_private_address VARCHAR(39), + dhcp_start VARCHAR(39), + project_id VARCHAR(255), + host VARCHAR(255), + cidr_v6 VARCHAR(43), + gateway_v6 VARCHAR(39), + label VARCHAR(255), + netmask_v6 VARCHAR(39), + bridge_interface VARCHAR(255), + multi_host BOOLEAN, + dns2 VARCHAR(39), + uuid VARCHAR(36), + priority INTEGER, + rxtx_base INTEGER, + PRIMARY KEY (id) + ); + + /* get data from networks and the drop it */ + INSERT INTO networks_backup SELECT * FROM networks; + DROP TABLE networks; + + CREATE TABLE networks ( + created_at DATETIME, + updated_at DATETIME, + deleted_at DATETIME, + deleted INTEGER, + id INTEGER NOT NULL, + injected BOOLEAN, + cidr VARCHAR(43), + netmask VARCHAR(39), + bridge VARCHAR(255), + gateway VARCHAR(39), + broadcast VARCHAR(39), + dns1 VARCHAR(39), + vlan INTEGER, + vpn_public_address VARCHAR(39), + vpn_public_port INTEGER, + vpn_private_address VARCHAR(39), + dhcp_start VARCHAR(39), + project_id VARCHAR(255), + host VARCHAR(255), + cidr_v6 VARCHAR(43), + gateway_v6 VARCHAR(39), + label VARCHAR(255), + netmask_v6 VARCHAR(39), + bridge_interface VARCHAR(255), + multi_host BOOLEAN, + dns2 VARCHAR(39), + uuid VARCHAR(36), + priority INTEGER, + rxtx_base INTEGER, + PRIMARY KEY (id), + CHECK (injected IN (0, 1)), + CHECK (multi_host IN (0, 1)), + CONSTRAINT uniq_vlan_x_deleted UNIQUE (vlan, deleted) + ); + + /* get data from networks_backup back and drop it */ + INSERT INTO networks SELECT * FROM networks_backup; + DROP TABLE networks_backup; +COMMIT; diff --git a/nova/db/sqlalchemy/migrate_repo/versions/160_fix_system_metadata_deleted.py b/nova/db/sqlalchemy/migrate_repo/versions/160_fix_system_metadata_deleted.py new file mode 100644 index 000000000..d7909f897 --- /dev/null +++ b/nova/db/sqlalchemy/migrate_repo/versions/160_fix_system_metadata_deleted.py @@ -0,0 +1,33 @@ +# Copyright 2013 Rackspace Hosting +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import sqlalchemy + + +def upgrade(migrate_engine): + meta = sqlalchemy.MetaData() + meta.bind = migrate_engine + sys_meta = sqlalchemy.Table('instance_system_metadata', meta, + autoload=True) + # is None does not work here. + sys_meta.update().\ + where(sys_meta.c.deleted == None).\ + values(deleted=0).\ + execute() + + +def downgrade(migration_engine): + # This migration only corrects NULL to be 0. There's no action to + # revert this. + pass diff --git a/nova/db/sqlalchemy/migrate_repo/versions/__init__.py b/nova/db/sqlalchemy/migrate_repo/versions/__init__.py index 4cad9a01b..74704e5e6 100644 --- a/nova/db/sqlalchemy/migrate_repo/versions/__init__.py +++ b/nova/db/sqlalchemy/migrate_repo/versions/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/db/sqlalchemy/models.py b/nova/db/sqlalchemy/models.py index 95456bf98..a675357df 100644 --- a/nova/db/sqlalchemy/models.py +++ b/nova/db/sqlalchemy/models.py @@ -164,12 +164,6 @@ class Instance(BASE, NovaBase): ramdisk_id = Column(String(255)) hostname = Column(String(255)) -# image_ref = Column(Integer, ForeignKey('images.id'), nullable=True) -# kernel_id = Column(Integer, ForeignKey('images.id'), nullable=True) -# ramdisk_id = Column(Integer, ForeignKey('images.id'), nullable=True) -# ramdisk = relationship(Ramdisk, backref=backref('instances', order_by=id)) -# kernel = relationship(Kernel, backref=backref('instances', order_by=id)) - launch_index = Column(Integer) key_name = Column(String(255)) key_data = Column(Text) @@ -841,29 +835,16 @@ class Aggregate(BASE, NovaBase): id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String(255)) _hosts = relationship(AggregateHost, - lazy="joined", - secondary="aggregate_hosts", primaryjoin='and_(' - 'Aggregate.id == AggregateHost.aggregate_id,' - 'AggregateHost.deleted == 0,' - 'Aggregate.deleted == 0)', - secondaryjoin='and_(' - 'AggregateHost.aggregate_id == Aggregate.id, ' - 'AggregateHost.deleted == 0,' - 'Aggregate.deleted == 0)', - backref='aggregates') + 'Aggregate.id == AggregateHost.aggregate_id,' + 'AggregateHost.deleted == 0,' + 'Aggregate.deleted == 0)') _metadata = relationship(AggregateMetadata, - secondary="aggregate_metadata", - primaryjoin='and_(' + primaryjoin='and_(' 'Aggregate.id == AggregateMetadata.aggregate_id,' 'AggregateMetadata.deleted == 0,' - 'Aggregate.deleted == 0)', - secondaryjoin='and_(' - 'AggregateMetadata.aggregate_id == Aggregate.id, ' - 'AggregateMetadata.deleted == 0,' - 'Aggregate.deleted == 0)', - backref='aggregates') + 'Aggregate.deleted == 0)') def _extra_keys(self): return ['hosts', 'metadetails', 'availability_zone'] diff --git a/nova/db/sqlalchemy/types.py b/nova/db/sqlalchemy/types.py index 5a04a0253..ef9113413 100644 --- a/nova/db/sqlalchemy/types.py +++ b/nova/db/sqlalchemy/types.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/exception.py b/nova/exception.py index cad1c5c02..0e6c004d6 100644 --- a/nova/exception.py +++ b/nova/exception.py @@ -31,6 +31,7 @@ import webob.exc from nova.openstack.common import excutils from nova.openstack.common import log as logging +from nova import safe_utils LOG = logging.getLogger(__name__) @@ -71,6 +72,11 @@ class ProcessExecutionError(IOError): IOError.__init__(self, message) +def _cleanse_dict(original): + """Strip all admin_password, new_pass, rescue_pass keys from a dict.""" + return dict((k, v) for k, v in original.iteritems() if not "_pass" in k) + + def wrap_exception(notifier=None, publisher_id=None, event_type=None, level=None): """This decorator wraps a method to catch any exceptions that may @@ -89,8 +95,10 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None, except Exception, e: with excutils.save_and_reraise_exception(): if notifier: - payload = dict(args=args, exception=e) - payload.update(kw) + payload = dict(exception=e) + call_dict = safe_utils.getcallargs(f, *args, **kw) + cleansed = _cleanse_dict(call_dict) + payload.update({'args': cleansed}) # Use a temp vars so we don't shadow # our outer definitions. @@ -423,6 +431,10 @@ class InvalidUUID(Invalid): message = _("Expected a uuid but received %(uuid)s.") +class InvalidID(Invalid): + message = _("Invalid ID received %(id)s.") + + class InvalidPeriodicTaskArg(Invalid): message = _("Unexpected argument for periodic task creation: %(arg)s.") @@ -1060,6 +1072,11 @@ class InstanceNotFound(NotFound): message = _("Instance %(instance_id)s could not be found.") +class InstanceInfoCacheNotFound(NotFound): + message = _("Info cache for instance %(instance_uuid)s could not be " + "found.") + + class NodeNotFound(NotFound): message = _("Node %(node_id)s could not be found.") @@ -1080,6 +1097,10 @@ class CouldNotFetchImage(NovaException): message = _("Could not fetch image %(image_id)s") +class CouldNotUploadImage(NovaException): + message = _("Could not upload image %(image_id)s") + + class TaskAlreadyRunning(NovaException): message = _("Task %(task_name)s is already running on host %(host)s") diff --git a/nova/filters.py b/nova/filters.py index a3339eff8..59028a542 100644 --- a/nova/filters.py +++ b/nova/filters.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/hooks.py b/nova/hooks.py index 8a9c77e73..c6fede8a8 100644 --- a/nova/hooks.py +++ b/nova/hooks.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/image/glance.py b/nova/image/glance.py index 79614d6a7..eb0d72b81 100644 --- a/nova/image/glance.py +++ b/nova/image/glance.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/ipv6/__init__.py b/nova/ipv6/__init__.py index 99ff05356..7abdae5e4 100644 --- a/nova/ipv6/__init__.py +++ b/nova/ipv6/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/ipv6/api.py b/nova/ipv6/api.py index 7f94abcfb..06a0891d9 100644 --- a/nova/ipv6/api.py +++ b/nova/ipv6/api.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/loadables.py b/nova/loadables.py index 964845184..96da88d0a 100644 --- a/nova/loadables.py +++ b/nova/loadables.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/locale/nova.pot b/nova/locale/nova.pot index 1b3d0474c..4fcebf25e 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.169\n" +"Project-Id-Version: nova jenkins.nova.propose.translation.update.177\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2013-02-25 00:04+0000\n" +"POT-Creation-Date: 2013-03-05 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" @@ -175,7 +175,7 @@ msgid "Volume %(volume_id)s is not attached to anything" msgstr "" #: nova/exception.py:234 nova/api/ec2/cloud.py:463 -#: nova/api/openstack/compute/contrib/keypairs.py:98 nova/compute/api.py:2691 +#: nova/api/openstack/compute/contrib/keypairs.py:98 nova/compute/api.py:2708 msgid "Keypair data is invalid" msgstr "" @@ -205,7 +205,7 @@ msgstr "" msgid "Invalid port range %(from_port)s:%(to_port)s. %(msg)s" msgstr "" -#: nova/exception.py:262 nova/api/ec2/cloud.py:617 +#: nova/exception.py:262 nova/api/ec2/cloud.py:625 #, python-format msgid "Invalid IP protocol %(protocol)s." msgstr "" @@ -220,7 +220,7 @@ msgstr "" msgid "Invalid cidr %(cidr)s." msgstr "" -#: nova/exception.py:274 nova/openstack/common/db/sqlalchemy/session.py:345 +#: nova/exception.py:274 nova/openstack/common/db/exception.py:44 msgid "Invalid Parameter: Unicode is not supported by the current database." msgstr "" @@ -397,58 +397,63 @@ msgstr "" #: nova/exception.py:427 #, python-format -msgid "Unexpected argument for periodic task creation: %(arg)s." +msgid "Invalid ID received %(id)s." msgstr "" #: nova/exception.py:431 +#, python-format +msgid "Unexpected argument for periodic task creation: %(arg)s." +msgstr "" + +#: nova/exception.py:435 msgid "Constraint not met." msgstr "" -#: nova/exception.py:436 +#: nova/exception.py:440 msgid "Resource could not be found." msgstr "" -#: nova/exception.py:441 +#: nova/exception.py:445 #, python-format msgid "No agent-build associated with id %(id)s." msgstr "" -#: nova/exception.py:445 +#: nova/exception.py:449 #, python-format msgid "Volume %(volume_id)s could not be found." msgstr "" -#: nova/exception.py:449 +#: nova/exception.py:453 #, python-format msgid "Snapshot %(snapshot_id)s could not be found." msgstr "" -#: nova/exception.py:453 +#: nova/exception.py:457 #, python-format msgid "No target id found for volume %(volume_id)s." msgstr "" -#: nova/exception.py:457 +#: nova/exception.py:461 #, python-format msgid "No disk at %(location)s" msgstr "" -#: nova/exception.py:461 +#: nova/exception.py:465 #, python-format msgid "Could not find a handler for %(driver_type)s volume." msgstr "" -#: nova/exception.py:465 +#: nova/exception.py:469 #, python-format msgid "Invalid image href %(image_href)s." msgstr "" -#: nova/exception.py:469 +#: nova/exception.py:473 #, python-format msgid "Image %(image_id)s could not be found." msgstr "" -#: nova/exception.py:473 +#: nova/exception.py:477 #, python-format msgid "" "Image %(image_id)s could not be found. The nova EC2 API assigns image ids" @@ -456,802 +461,812 @@ msgid "" "image ids since adding this image?" msgstr "" -#: nova/exception.py:480 +#: nova/exception.py:484 #, python-format msgid "Project %(project_id)s could not be found." msgstr "" -#: nova/exception.py:484 +#: nova/exception.py:488 msgid "Cannot find SR to read/write VDI." msgstr "" -#: nova/exception.py:488 +#: nova/exception.py:492 #, python-format msgid "Network %(network_id)s is duplicated." msgstr "" -#: nova/exception.py:492 +#: nova/exception.py:496 #, python-format msgid "Network %(network_id)s is still in use." msgstr "" -#: nova/exception.py:496 +#: nova/exception.py:500 #, python-format msgid "%(req)s is required to create a network." msgstr "" -#: nova/exception.py:500 +#: nova/exception.py:504 #, python-format msgid "Network %(network_id)s could not be found." msgstr "" -#: nova/exception.py:504 +#: nova/exception.py:508 #, python-format msgid "Port id %(port_id)s could not be found." msgstr "" -#: nova/exception.py:508 +#: nova/exception.py:512 #, python-format msgid "Network could not be found for bridge %(bridge)s" msgstr "" -#: nova/exception.py:512 +#: nova/exception.py:516 #, python-format msgid "Network could not be found for uuid %(uuid)s" msgstr "" -#: nova/exception.py:516 +#: nova/exception.py:520 #, python-format msgid "Network could not be found with cidr %(cidr)s." msgstr "" -#: nova/exception.py:520 +#: nova/exception.py:524 #, python-format msgid "Network could not be found for instance %(instance_id)s." msgstr "" -#: nova/exception.py:524 +#: nova/exception.py:528 msgid "No networks defined." msgstr "" -#: nova/exception.py:528 +#: nova/exception.py:532 #, python-format msgid "" "Either Network uuid %(network_uuid)s is not present or is not assigned to" " the project %(project_id)s." msgstr "" -#: nova/exception.py:533 +#: nova/exception.py:537 msgid "Could not find the datastore reference(s) which the VM uses." msgstr "" -#: nova/exception.py:537 +#: nova/exception.py:541 #, python-format msgid "Port %(port_id)s is still in use." msgstr "" -#: nova/exception.py:541 +#: nova/exception.py:545 #, python-format msgid "Port %(port_id)s not usable for instance %(instance)s." msgstr "" -#: nova/exception.py:545 +#: nova/exception.py:549 #, python-format msgid "No free port available for instance %(instance)s." msgstr "" -#: nova/exception.py:549 +#: nova/exception.py:553 #, python-format msgid "No fixed IP associated with id %(id)s." msgstr "" -#: nova/exception.py:553 +#: nova/exception.py:557 #, python-format msgid "Fixed ip not found for address %(address)s." msgstr "" -#: nova/exception.py:557 +#: nova/exception.py:561 #, python-format msgid "Instance %(instance_uuid)s has zero fixed ips." msgstr "" -#: nova/exception.py:561 +#: nova/exception.py:565 #, python-format msgid "Network host %(host)s has zero fixed ips in network %(network_id)s." msgstr "" -#: nova/exception.py:566 +#: nova/exception.py:570 #, python-format msgid "Instance %(instance_uuid)s doesn't have fixed ip '%(ip)s'." msgstr "" -#: nova/exception.py:570 +#: nova/exception.py:574 #, python-format msgid "" "Fixed IP address (%(address)s) does not exist in network " "(%(network_uuid)s)." msgstr "" -#: nova/exception.py:575 +#: nova/exception.py:579 #, python-format msgid "" "Fixed IP address %(address)s is already in use on instance " "%(instance_uuid)s." msgstr "" -#: nova/exception.py:580 +#: nova/exception.py:584 #, python-format msgid "More than one instance is associated with fixed ip address '%(address)s'." msgstr "" -#: nova/exception.py:585 +#: nova/exception.py:589 #, python-format msgid "Fixed IP address %(address)s is invalid." msgstr "" -#: nova/exception.py:589 +#: nova/exception.py:593 msgid "Zero fixed ips available." msgstr "" -#: nova/exception.py:593 +#: nova/exception.py:597 msgid "Zero fixed ips could be found." msgstr "" -#: nova/exception.py:602 +#: nova/exception.py:606 #, python-format msgid "Floating ip %(address)s already exists." msgstr "" -#: nova/exception.py:606 +#: nova/exception.py:610 #, python-format msgid "Floating ip not found for id %(id)s." msgstr "" -#: nova/exception.py:610 +#: nova/exception.py:614 #, python-format msgid "The DNS entry %(name)s already exists in domain %(domain)s." msgstr "" -#: nova/exception.py:614 +#: nova/exception.py:618 #, python-format msgid "Floating ip not found for address %(address)s." msgstr "" -#: nova/exception.py:618 +#: nova/exception.py:622 #, python-format msgid "Floating ip not found for host %(host)s." msgstr "" -#: nova/exception.py:622 +#: nova/exception.py:626 #, python-format msgid "Multiple floating ips are found for address %(address)s." msgstr "" -#: nova/exception.py:626 +#: nova/exception.py:630 msgid "Floating ip pool not found." msgstr "" -#: nova/exception.py:631 +#: nova/exception.py:635 msgid "Zero floating ips available." msgstr "" -#: nova/exception.py:636 +#: nova/exception.py:640 #, python-format msgid "Floating ip %(address)s is associated." msgstr "" -#: nova/exception.py:640 +#: nova/exception.py:644 #, python-format msgid "Floating ip %(address)s is not associated." msgstr "" -#: nova/exception.py:644 +#: nova/exception.py:648 msgid "Zero floating ips exist." msgstr "" -#: nova/exception.py:648 +#: nova/exception.py:652 #, python-format msgid "Interface %(interface)s not found." msgstr "" -#: nova/exception.py:652 +#: nova/exception.py:656 msgid "Cannot disassociate auto assigined floating ip" msgstr "" -#: nova/exception.py:656 +#: nova/exception.py:660 #, python-format msgid "Keypair %(name)s not found for user %(user_id)s" msgstr "" -#: nova/exception.py:660 +#: nova/exception.py:664 #, python-format msgid "Certificate %(certificate_id)s not found." msgstr "" -#: nova/exception.py:664 +#: nova/exception.py:668 #, python-format msgid "Service %(service_id)s could not be found." msgstr "" -#: nova/exception.py:668 +#: nova/exception.py:672 #, python-format msgid "Host %(host)s could not be found." msgstr "" -#: nova/exception.py:672 +#: nova/exception.py:676 #, python-format msgid "Compute host %(host)s could not be found." msgstr "" -#: nova/exception.py:676 +#: nova/exception.py:680 #, python-format msgid "Could not find binary %(binary)s on host %(host)s." msgstr "" -#: nova/exception.py:680 +#: nova/exception.py:684 #, python-format msgid "Invalid reservation expiration %(expire)s." msgstr "" -#: nova/exception.py:684 +#: nova/exception.py:688 #, python-format msgid "" "Change would make usage less than 0 for the following resources: " "%(unders)s" msgstr "" -#: nova/exception.py:689 +#: nova/exception.py:693 msgid "Quota could not be found" msgstr "" -#: nova/exception.py:693 +#: nova/exception.py:697 #, python-format msgid "Unknown quota resources %(unknown)s." msgstr "" -#: nova/exception.py:697 +#: nova/exception.py:701 #, python-format msgid "Quota for project %(project_id)s could not be found." msgstr "" -#: nova/exception.py:701 +#: nova/exception.py:705 #, python-format msgid "Quota class %(class_name)s could not be found." msgstr "" -#: nova/exception.py:705 +#: nova/exception.py:709 #, python-format msgid "Quota usage for project %(project_id)s could not be found." msgstr "" -#: nova/exception.py:709 +#: nova/exception.py:713 #, python-format msgid "Quota reservation %(uuid)s could not be found." msgstr "" -#: nova/exception.py:713 +#: nova/exception.py:717 #, python-format msgid "Quota exceeded for resources: %(overs)s" msgstr "" -#: nova/exception.py:717 +#: nova/exception.py:721 #, python-format msgid "Security group %(security_group_id)s not found." msgstr "" -#: nova/exception.py:721 +#: nova/exception.py:725 #, python-format msgid "Security group %(security_group_id)s not found for project %(project_id)s." msgstr "" -#: nova/exception.py:726 +#: nova/exception.py:730 #, python-format msgid "Security group with rule %(rule_id)s not found." msgstr "" -#: nova/exception.py:730 +#: nova/exception.py:734 #, python-format msgid "" "Security group %(security_group_id)s is already associated with the " "instance %(instance_id)s" msgstr "" -#: nova/exception.py:735 +#: nova/exception.py:739 #, python-format msgid "" "Security group %(security_group_id)s is not associated with the instance " "%(instance_id)s" msgstr "" -#: nova/exception.py:740 +#: nova/exception.py:744 #, python-format msgid "Security group default rule (%rule_id)s not found." msgstr "" -#: nova/exception.py:744 +#: nova/exception.py:748 msgid "" "Network requires port_security_enabled and subnet associated in order to " "apply security groups." msgstr "" -#: nova/exception.py:749 +#: nova/exception.py:753 msgid "No Unique Match Found." msgstr "" -#: nova/exception.py:754 +#: nova/exception.py:758 #, python-format msgid "Migration %(migration_id)s could not be found." msgstr "" -#: nova/exception.py:758 +#: nova/exception.py:762 #, python-format msgid "Migration not found for instance %(instance_id)s with status %(status)s." msgstr "" -#: nova/exception.py:763 +#: nova/exception.py:767 #, python-format msgid "Console pool %(pool_id)s could not be found." msgstr "" -#: nova/exception.py:767 +#: nova/exception.py:771 #, python-format msgid "" "Console pool of type %(console_type)s for compute host %(compute_host)s " "on proxy host %(host)s not found." msgstr "" -#: nova/exception.py:773 +#: nova/exception.py:777 #, python-format msgid "Console %(console_id)s could not be found." msgstr "" -#: nova/exception.py:777 +#: nova/exception.py:781 #, python-format msgid "Console for instance %(instance_uuid)s could not be found." msgstr "" -#: nova/exception.py:781 +#: nova/exception.py:785 #, python-format msgid "" "Console for instance %(instance_uuid)s in pool %(pool_id)s could not be " "found." msgstr "" -#: nova/exception.py:786 +#: nova/exception.py:790 #, python-format msgid "Invalid console type %(console_type)s" msgstr "" -#: nova/exception.py:790 +#: nova/exception.py:794 #, python-format msgid "Instance type %(instance_type_id)s could not be found." msgstr "" -#: nova/exception.py:794 +#: nova/exception.py:798 #, python-format msgid "Instance type with name %(instance_type_name)s could not be found." msgstr "" -#: nova/exception.py:799 +#: nova/exception.py:803 #, python-format msgid "Flavor %(flavor_id)s could not be found." msgstr "" -#: nova/exception.py:803 +#: nova/exception.py:807 #, python-format msgid "Flavor access not found for %(flavor_id)s / %(project_id)s combination." msgstr "" -#: nova/exception.py:808 +#: nova/exception.py:812 #, python-format msgid "Cell %(cell_name)s doesn't exist." msgstr "" -#: nova/exception.py:812 +#: nova/exception.py:816 #, python-format msgid "Inconsistency in cell routing: %(reason)s" msgstr "" -#: nova/exception.py:816 +#: nova/exception.py:820 #, python-format msgid "Service API method not found: %(detail)s" msgstr "" -#: nova/exception.py:820 +#: nova/exception.py:824 msgid "Timeout waiting for response from cell" msgstr "" -#: nova/exception.py:824 +#: nova/exception.py:828 #, python-format msgid "Cell message has reached maximum hop count: %(hop_count)s" msgstr "" -#: nova/exception.py:828 +#: nova/exception.py:832 msgid "No cells available matching scheduling criteria." msgstr "" -#: nova/exception.py:832 +#: nova/exception.py:836 #, python-format msgid "Exception received during cell processing: %(exc_name)s." msgstr "" -#: nova/exception.py:836 +#: nova/exception.py:840 #, python-format msgid "Cell is not known for instance %(instance_uuid)s" msgstr "" -#: nova/exception.py:840 +#: nova/exception.py:844 #, python-format msgid "Scheduler Host Filter %(filter_name)s could not be found." msgstr "" -#: nova/exception.py:844 +#: nova/exception.py:848 #, python-format msgid "Scheduler cost function %(cost_fn_str)s could not be found." msgstr "" -#: nova/exception.py:849 +#: nova/exception.py:853 #, python-format msgid "Scheduler weight flag not found: %(flag_name)s" msgstr "" -#: nova/exception.py:853 +#: nova/exception.py:857 #, python-format msgid "Instance %(instance_uuid)s has no metadata with key %(metadata_key)s." msgstr "" -#: nova/exception.py:858 +#: nova/exception.py:862 #, python-format msgid "" "Instance %(instance_uuid)s has no system metadata with key " "%(metadata_key)s." msgstr "" -#: nova/exception.py:863 +#: nova/exception.py:867 #, python-format msgid "" "Instance Type %(instance_type_id)s has no extra specs with key " "%(extra_specs_key)s." msgstr "" -#: nova/exception.py:868 +#: nova/exception.py:872 #, python-format msgid "File %(file_path)s could not be found." msgstr "" -#: nova/exception.py:872 +#: nova/exception.py:876 msgid "Zero files could be found." msgstr "" -#: nova/exception.py:876 +#: nova/exception.py:880 #, python-format msgid "Virtual switch associated with the network adapter %(adapter)s not found." msgstr "" -#: nova/exception.py:881 +#: nova/exception.py:885 #, python-format msgid "Network adapter %(adapter)s could not be found." msgstr "" -#: nova/exception.py:885 +#: nova/exception.py:889 #, python-format msgid "Class %(class_name)s could not be found: %(exception)s" msgstr "" -#: nova/exception.py:889 +#: nova/exception.py:893 msgid "Action not allowed." msgstr "" -#: nova/exception.py:893 +#: nova/exception.py:897 msgid "Rotation is not allowed for snapshots" msgstr "" -#: nova/exception.py:897 +#: nova/exception.py:901 msgid "Rotation param is required for backup image_type" msgstr "" -#: nova/exception.py:901 +#: nova/exception.py:905 #, python-format msgid "Key pair %(key_name)s already exists." msgstr "" -#: nova/exception.py:905 +#: nova/exception.py:909 #, python-format msgid "Instance %(name)s already exists." msgstr "" -#: nova/exception.py:909 +#: nova/exception.py:913 #, python-format msgid "Instance Type with name %(name)s already exists." msgstr "" -#: nova/exception.py:913 +#: nova/exception.py:917 #, python-format msgid "Instance Type with ID %(flavor_id)s already exists." msgstr "" -#: nova/exception.py:917 +#: nova/exception.py:921 #, python-format msgid "" "Flavor access alreay exists for flavor %(flavor_id)s and project " "%(project_id)s combination." msgstr "" -#: nova/exception.py:922 +#: nova/exception.py:926 #, python-format msgid "%(path)s is not on shared storage: %(reason)s" msgstr "" -#: nova/exception.py:926 +#: nova/exception.py:930 #, python-format msgid "%(path)s is not on local storage: %(reason)s" msgstr "" -#: nova/exception.py:930 +#: nova/exception.py:934 msgid "Migration error" msgstr "" -#: nova/exception.py:934 +#: nova/exception.py:938 #, python-format msgid "Malformed message body: %(reason)s" msgstr "" -#: nova/exception.py:940 +#: nova/exception.py:944 #, python-format msgid "Could not find config at %(path)s" msgstr "" -#: nova/exception.py:944 +#: nova/exception.py:948 #, python-format msgid "Could not load paste app '%(name)s' from %(path)s" msgstr "" -#: nova/exception.py:948 +#: nova/exception.py:952 msgid "When resizing, instances must change flavor!" msgstr "" -#: nova/exception.py:952 +#: nova/exception.py:956 #, python-format msgid "Resize error: %(reason)s" msgstr "" -#: nova/exception.py:956 +#: nova/exception.py:960 msgid "Image is larger than instance type allows" msgstr "" -#: nova/exception.py:960 +#: nova/exception.py:964 msgid "Instance type's memory is too small for requested image." msgstr "" -#: nova/exception.py:964 +#: nova/exception.py:968 msgid "Instance type's disk is too small for requested image." msgstr "" -#: nova/exception.py:968 +#: nova/exception.py:972 #, python-format msgid "Insufficient free memory on compute node to start %(uuid)s." msgstr "" -#: nova/exception.py:972 +#: nova/exception.py:976 msgid "Could not fetch bandwidth/cpu/disk metrics for this host." msgstr "" -#: nova/exception.py:976 +#: nova/exception.py:980 #, python-format msgid "No valid host was found. %(reason)s" msgstr "" -#: nova/exception.py:980 +#: nova/exception.py:984 msgid "Quota exceeded" msgstr "" -#: nova/exception.py:987 +#: nova/exception.py:991 #, python-format msgid "" "Quota exceeded for %(overs)s: Requested %(req)s, but already used " "%(used)d of %(allowed)d %(resource)s" msgstr "" -#: nova/exception.py:992 +#: nova/exception.py:996 msgid "Maximum number of floating ips exceeded" msgstr "" -#: nova/exception.py:996 +#: nova/exception.py:1000 #, python-format msgid "Maximum number of metadata items exceeds %(allowed)d" msgstr "" -#: nova/exception.py:1000 +#: nova/exception.py:1004 msgid "Personality file limit exceeded" msgstr "" -#: nova/exception.py:1004 +#: nova/exception.py:1008 msgid "Personality file path too long" msgstr "" -#: nova/exception.py:1008 +#: nova/exception.py:1012 msgid "Personality file content too long" msgstr "" -#: nova/exception.py:1012 +#: nova/exception.py:1016 msgid "Maximum number of key pairs exceeded" msgstr "" -#: nova/exception.py:1016 +#: nova/exception.py:1020 msgid "Maximum number of security groups or rules exceeded" msgstr "" -#: nova/exception.py:1020 +#: nova/exception.py:1024 #, python-format msgid "" "Aggregate %(aggregate_id)s: action '%(action)s' caused an error: " "%(reason)s." msgstr "" -#: nova/exception.py:1025 +#: nova/exception.py:1029 #, python-format msgid "Aggregate %(aggregate_id)s could not be found." msgstr "" -#: nova/exception.py:1029 +#: nova/exception.py:1033 #, python-format msgid "Aggregate %(aggregate_name)s already exists." msgstr "" -#: nova/exception.py:1033 +#: nova/exception.py:1037 #, python-format msgid "Aggregate %(aggregate_id)s has no host %(host)s." msgstr "" -#: nova/exception.py:1037 +#: nova/exception.py:1041 #, python-format msgid "Aggregate %(aggregate_id)s has no metadata with key %(metadata_key)s." msgstr "" -#: nova/exception.py:1042 +#: nova/exception.py:1046 #, python-format msgid "Aggregate %(aggregate_id)s already has host %(host)s." msgstr "" -#: nova/exception.py:1046 +#: nova/exception.py:1050 msgid "Unable to create instance type" msgstr "" -#: nova/exception.py:1050 +#: nova/exception.py:1054 #, python-format msgid "Failed to set admin password on %(instance)s because %(reason)s" msgstr "" -#: nova/exception.py:1056 +#: nova/exception.py:1060 #, python-format msgid "Detected existing vlan with id %(vlan)d" msgstr "" -#: nova/exception.py:1060 +#: nova/exception.py:1064 #, python-format msgid "Instance %(instance_id)s could not be found." msgstr "" -#: nova/exception.py:1064 +#: nova/exception.py:1068 +#, python-format +msgid "Info cache for instance %(instance_uuid)s could not be found." +msgstr "" + +#: nova/exception.py:1073 #, python-format msgid "Node %(node_id)s could not be found." msgstr "" -#: nova/exception.py:1068 +#: nova/exception.py:1077 #, python-format msgid "Node with UUID %(node_uuid)s could not be found." msgstr "" -#: nova/exception.py:1072 +#: nova/exception.py:1081 #, python-format msgid "Marker %(marker)s could not be found." msgstr "" -#: nova/exception.py:1076 +#: nova/exception.py:1085 #, python-format msgid "Invalid id: %(val)s (expecting \"i-...\")." msgstr "" -#: nova/exception.py:1080 +#: nova/exception.py:1089 #, python-format msgid "Could not fetch image %(image_id)s" msgstr "" -#: nova/exception.py:1084 +#: nova/exception.py:1093 +#, python-format +msgid "Could not upload image %(image_id)s" +msgstr "" + +#: nova/exception.py:1097 #, python-format msgid "Task %(task_name)s is already running on host %(host)s" msgstr "" -#: nova/exception.py:1088 +#: nova/exception.py:1101 #, python-format msgid "Task %(task_name)s is not running on host %(host)s" msgstr "" -#: nova/exception.py:1092 +#: nova/exception.py:1105 #, python-format msgid "Instance %(instance_uuid)s is locked" msgstr "" -#: nova/exception.py:1096 +#: nova/exception.py:1109 #, python-format msgid "Could not mount vfat config drive. %(operation)s failed. Error: %(error)s" msgstr "" -#: nova/exception.py:1101 +#: nova/exception.py:1114 #, python-format msgid "Unknown config drive format %(format)s. Select one of iso9660 or vfat." msgstr "" -#: nova/exception.py:1106 +#: nova/exception.py:1119 #, python-format msgid "Failed to attach network adapter device to %(instance)s" msgstr "" -#: nova/exception.py:1110 +#: nova/exception.py:1123 #, python-format msgid "Failed to detach network adapter device from %(instance)s" msgstr "" -#: nova/exception.py:1114 +#: nova/exception.py:1127 #, python-format msgid "" "User data too large. User data must be no larger than %(maxsize)s bytes " "once base64 encoded. Your data is %(length)d bytes" msgstr "" -#: nova/exception.py:1120 +#: nova/exception.py:1133 msgid "User data needs to be valid base 64." msgstr "" -#: nova/exception.py:1124 +#: nova/exception.py:1137 #, python-format msgid "" "unexpected task state: expecting %(expected)s but the actual state is " "%(actual)s" msgstr "" -#: nova/exception.py:1129 +#: nova/exception.py:1142 #, python-format msgid "" "Action for request_id %(request_id)s on instance %(instance_uuid)s not " "found" msgstr "" -#: nova/exception.py:1134 +#: nova/exception.py:1147 #, python-format msgid "Event %(event)s not found for action id %(action_id)s" msgstr "" -#: nova/exception.py:1138 +#: nova/exception.py:1151 #, python-format msgid "The CA file for %(project)s could not be found" msgstr "" -#: nova/exception.py:1142 +#: nova/exception.py:1155 #, python-format msgid "The CRL file for %(project)s could not be found" msgstr "" -#: nova/exception.py:1146 +#: nova/exception.py:1159 msgid "Instance recreate is not implemented by this virt driver." msgstr "" -#: nova/exception.py:1150 +#: nova/exception.py:1163 #, python-format msgid "The service from servicegroup driver %(driver) is temporarily unavailable." msgstr "" -#: nova/exception.py:1155 +#: nova/exception.py:1168 #, python-format msgid "%(binary)s attempted direct database access which is not allowed by policy" msgstr "" -#: nova/exception.py:1160 +#: nova/exception.py:1173 #, python-format msgid "Virtualization type '%(virt)s' is not supported by this compute driver" msgstr "" -#: nova/exception.py:1165 +#: nova/exception.py:1178 #, python-format msgid "" "Requested hardware '%(model)s' is not supported by the '%(virt)s' virt " @@ -1433,7 +1448,7 @@ msgid "Running cmd (subprocess): %s" msgstr "" #: nova/utils.py:236 nova/utils.py:314 -#: nova/openstack/common/processutils.py:114 nova/virt/powervm/common.py:86 +#: nova/openstack/common/processutils.py:114 nova/virt/powervm/common.py:88 #, python-format msgid "Result was %s" msgstr "" @@ -1489,47 +1504,47 @@ msgstr "" msgid "in dynamic looping call" msgstr "" -#: nova/utils.py:742 +#: nova/utils.py:756 #, python-format msgid "Unknown byte multiplier: %s" msgstr "" -#: nova/utils.py:871 +#: nova/utils.py:885 #, python-format msgid "Expected object of type: %s" msgstr "" -#: nova/utils.py:900 +#: nova/utils.py:914 #, python-format msgid "Invalid server_string: %s" msgstr "" -#: nova/utils.py:1054 +#: nova/utils.py:1068 #, python-format msgid "timefunc: '%(name)s' took %(total_time).2f secs" msgstr "" -#: nova/utils.py:1120 +#: nova/utils.py:1134 #, python-format msgid "Reloading cached file %s" msgstr "" -#: nova/utils.py:1252 nova/virt/configdrive.py:177 +#: nova/utils.py:1266 nova/virt/configdrive.py:177 #, python-format msgid "Could not remove tmpdir: %s" msgstr "" -#: nova/utils.py:1430 +#: nova/utils.py:1444 #, python-format msgid "%s is not a string or unicode" msgstr "" -#: nova/utils.py:1434 +#: nova/utils.py:1448 #, python-format msgid "%(name)s has less than %(min_length)s characters." msgstr "" -#: nova/utils.py:1439 +#: nova/utils.py:1453 #, python-format msgid "%(name)s has more than %(max_length)s characters." msgstr "" @@ -1772,205 +1787,205 @@ msgstr "" msgid "Delete key pair %s" msgstr "" -#: nova/api/ec2/cloud.py:604 nova/api/ec2/cloud.py:725 +#: nova/api/ec2/cloud.py:612 nova/api/ec2/cloud.py:733 msgid "Not enough parameters, need group_name or group_id" msgstr "" -#: nova/api/ec2/cloud.py:609 +#: nova/api/ec2/cloud.py:617 #, python-format msgid "%s Not enough parameters to build a valid rule" msgstr "" -#: nova/api/ec2/cloud.py:647 nova/api/ec2/cloud.py:679 +#: nova/api/ec2/cloud.py:655 nova/api/ec2/cloud.py:687 msgid "No rule for the specified parameters." msgstr "" -#: nova/api/ec2/cloud.py:670 +#: nova/api/ec2/cloud.py:678 #, python-format msgid "%s - This rule already exists in group" msgstr "" -#: nova/api/ec2/cloud.py:753 +#: nova/api/ec2/cloud.py:761 #, python-format msgid "Get console output for instance %s" msgstr "" -#: nova/api/ec2/cloud.py:829 +#: nova/api/ec2/cloud.py:837 #, python-format msgid "Create volume from snapshot %s" msgstr "" -#: nova/api/ec2/cloud.py:833 nova/api/openstack/compute/contrib/volumes.py:243 +#: nova/api/ec2/cloud.py:841 nova/api/openstack/compute/contrib/volumes.py:243 #, python-format msgid "Create volume of %s GB" msgstr "" -#: nova/api/ec2/cloud.py:861 +#: nova/api/ec2/cloud.py:869 msgid "Delete Failed" msgstr "" -#: nova/api/ec2/cloud.py:874 +#: nova/api/ec2/cloud.py:882 #, python-format msgid "Attach volume %(volume_id)s to instance %(instance_id)s at %(device)s" msgstr "" -#: nova/api/ec2/cloud.py:882 +#: nova/api/ec2/cloud.py:890 msgid "Attach Failed." msgstr "" -#: nova/api/ec2/cloud.py:895 nova/api/openstack/compute/contrib/volumes.py:435 +#: nova/api/ec2/cloud.py:903 nova/api/openstack/compute/contrib/volumes.py:435 #, python-format msgid "Detach volume %s" msgstr "" -#: nova/api/ec2/cloud.py:901 +#: nova/api/ec2/cloud.py:909 msgid "Detach Volume Failed." msgstr "" -#: nova/api/ec2/cloud.py:927 nova/api/ec2/cloud.py:984 -#: nova/api/ec2/cloud.py:1537 nova/api/ec2/cloud.py:1552 +#: nova/api/ec2/cloud.py:935 nova/api/ec2/cloud.py:992 +#: nova/api/ec2/cloud.py:1545 nova/api/ec2/cloud.py:1560 #, python-format msgid "attribute not supported: %s" msgstr "" -#: nova/api/ec2/cloud.py:1058 +#: nova/api/ec2/cloud.py:1066 #, python-format msgid "vol = %s\n" msgstr "" -#: nova/api/ec2/cloud.py:1217 +#: nova/api/ec2/cloud.py:1225 msgid "Allocate address" msgstr "" -#: nova/api/ec2/cloud.py:1221 +#: nova/api/ec2/cloud.py:1229 msgid "No more floating IPs available" msgstr "" -#: nova/api/ec2/cloud.py:1225 +#: nova/api/ec2/cloud.py:1233 #, python-format msgid "Release address %s" msgstr "" -#: nova/api/ec2/cloud.py:1230 +#: nova/api/ec2/cloud.py:1238 msgid "Unable to release IP Address." msgstr "" -#: nova/api/ec2/cloud.py:1233 +#: nova/api/ec2/cloud.py:1241 #, python-format msgid "Associate address %(public_ip)s to instance %(instance_id)s" msgstr "" -#: nova/api/ec2/cloud.py:1241 +#: nova/api/ec2/cloud.py:1249 msgid "Unable to associate IP Address, no fixed_ips." msgstr "" -#: nova/api/ec2/cloud.py:1249 +#: nova/api/ec2/cloud.py:1257 #: nova/api/openstack/compute/contrib/floating_ips.py:238 #, python-format msgid "multiple fixed_ips exist, using the first: %s" msgstr "" -#: nova/api/ec2/cloud.py:1258 +#: nova/api/ec2/cloud.py:1266 msgid "Floating ip is already associated." msgstr "" -#: nova/api/ec2/cloud.py:1261 +#: nova/api/ec2/cloud.py:1269 msgid "l3driver call to add floating ip failed." msgstr "" -#: nova/api/ec2/cloud.py:1264 +#: nova/api/ec2/cloud.py:1272 msgid "Error, unable to associate floating ip." msgstr "" -#: nova/api/ec2/cloud.py:1272 +#: nova/api/ec2/cloud.py:1280 #, python-format msgid "Disassociate address %s" msgstr "" -#: nova/api/ec2/cloud.py:1277 +#: nova/api/ec2/cloud.py:1285 msgid "Floating ip is not associated." msgstr "" -#: nova/api/ec2/cloud.py:1280 +#: nova/api/ec2/cloud.py:1288 #: nova/api/openstack/compute/contrib/floating_ips.py:100 msgid "Cannot disassociate auto assigned floating ip" msgstr "" -#: nova/api/ec2/cloud.py:1307 +#: nova/api/ec2/cloud.py:1315 msgid "Image must be available" msgstr "" -#: nova/api/ec2/cloud.py:1339 +#: nova/api/ec2/cloud.py:1347 msgid "Going to start terminating instances" msgstr "" -#: nova/api/ec2/cloud.py:1349 +#: nova/api/ec2/cloud.py:1357 #, python-format msgid "Reboot instance %r" msgstr "" -#: nova/api/ec2/cloud.py:1358 +#: nova/api/ec2/cloud.py:1366 msgid "Going to stop instances" msgstr "" -#: nova/api/ec2/cloud.py:1367 +#: nova/api/ec2/cloud.py:1375 msgid "Going to start instances" msgstr "" -#: nova/api/ec2/cloud.py:1458 +#: nova/api/ec2/cloud.py:1466 #, python-format msgid "De-registering image %s" msgstr "" -#: nova/api/ec2/cloud.py:1474 +#: nova/api/ec2/cloud.py:1482 msgid "imageLocation is required" msgstr "" -#: nova/api/ec2/cloud.py:1493 +#: nova/api/ec2/cloud.py:1501 #, python-format msgid "Registered image %(image_location)s with id %(image_id)s" msgstr "" -#: nova/api/ec2/cloud.py:1555 +#: nova/api/ec2/cloud.py:1563 msgid "user or group not specified" msgstr "" -#: nova/api/ec2/cloud.py:1557 +#: nova/api/ec2/cloud.py:1565 msgid "only group \"all\" is supported" msgstr "" -#: nova/api/ec2/cloud.py:1559 +#: nova/api/ec2/cloud.py:1567 msgid "operation_type must be add or remove" msgstr "" -#: nova/api/ec2/cloud.py:1561 +#: nova/api/ec2/cloud.py:1569 #, python-format msgid "Updating image %s publicity" msgstr "" -#: nova/api/ec2/cloud.py:1574 +#: nova/api/ec2/cloud.py:1582 #, python-format msgid "Not allowed to modify attributes for image %s" msgstr "" -#: nova/api/ec2/cloud.py:1603 +#: nova/api/ec2/cloud.py:1611 #, python-format msgid "" "Invalid value '%(ec2_instance_id)s' for instanceId. Instance does not " "have a volume attached at root (%(root)s)" msgstr "" -#: nova/api/ec2/cloud.py:1633 +#: nova/api/ec2/cloud.py:1641 #, python-format msgid "Couldn't stop instance with in %d sec" msgstr "" -#: nova/api/ec2/cloud.py:1651 +#: nova/api/ec2/cloud.py:1659 #, python-format msgid "image of %(instance)s at %(now)s" msgstr "" -#: nova/api/ec2/cloud.py:1684 +#: nova/api/ec2/cloud.py:1692 msgid "Invalid CIDR" msgstr "" @@ -2568,7 +2583,7 @@ msgstr "" #: nova/api/openstack/compute/servers.py:1220 #: nova/api/openstack/compute/contrib/aggregates.py:143 -#: nova/api/openstack/compute/contrib/coverage_ext.py:256 +#: nova/api/openstack/compute/contrib/coverage_ext.py:277 #: nova/api/openstack/compute/contrib/keypairs.py:78 msgid "Invalid request body" msgstr "" @@ -2791,7 +2806,7 @@ msgid "" "again in a few minutes" msgstr "" -#: nova/api/openstack/compute/contrib/cloudpipe_update.py:44 +#: nova/api/openstack/compute/contrib/cloudpipe_update.py:43 #, python-format msgid "Unknown action %s" msgstr "" @@ -2808,46 +2823,46 @@ msgstr "" msgid "Unable to get console" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:105 +#: nova/api/openstack/compute/contrib/coverage_ext.py:114 #, python-format msgid "Can't connect to service: %s, no portspecified\n" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:108 +#: nova/api/openstack/compute/contrib/coverage_ext.py:117 #, python-format msgid "No backdoor API command for service: %s\n" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:127 +#: nova/api/openstack/compute/contrib/coverage_ext.py:135 msgid "Coverage begin" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:161 +#: nova/api/openstack/compute/contrib/coverage_ext.py:182 msgid "Coverage not running" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:190 +#: nova/api/openstack/compute/contrib/coverage_ext.py:211 msgid "Invalid path" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:194 +#: nova/api/openstack/compute/contrib/coverage_ext.py:215 msgid "No path given for report file" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:201 +#: nova/api/openstack/compute/contrib/coverage_ext.py:222 msgid "You can't use html reports without combining" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:211 +#: nova/api/openstack/compute/contrib/coverage_ext.py:232 #, python-format msgid "Directory conflict: %s already exists" msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:246 +#: nova/api/openstack/compute/contrib/coverage_ext.py:267 msgid "Python coverage module is not installed." msgstr "" -#: nova/api/openstack/compute/contrib/coverage_ext.py:254 +#: nova/api/openstack/compute/contrib/coverage_ext.py:275 #, python-format msgid "Coverage doesn't have %s action" msgstr "" @@ -2874,12 +2889,12 @@ msgstr "" msgid "Error in evacuate, %s" msgstr "" -#: nova/api/openstack/compute/contrib/fixed_ips.py:42 +#: nova/api/openstack/compute/contrib/fixed_ips.py:41 #, python-format msgid "Fixed IP %s has been deleted" msgstr "" -#: nova/api/openstack/compute/contrib/fixed_ips.py:74 +#: nova/api/openstack/compute/contrib/fixed_ips.py:73 #, python-format msgid "Fixed IP %s not found" msgstr "" @@ -2960,7 +2975,7 @@ msgstr "" msgid "Error. Unable to associate floating ip" msgstr "" -#: nova/api/openstack/compute/contrib/floating_ips_bulk.py:147 +#: nova/api/openstack/compute/contrib/floating_ips_bulk.py:146 #, python-format msgid "/%s should be specified as single address(es) not in cidr format" msgstr "" @@ -3312,34 +3327,34 @@ msgstr "" msgid "Got update for instance %(instance_uuid)s: %(instance)s" msgstr "" -#: nova/cells/messaging.py:782 +#: nova/cells/messaging.py:787 #, python-format msgid "Got update to delete instance %(instance_uuid)s" msgstr "" -#: nova/cells/messaging.py:797 +#: nova/cells/messaging.py:802 #, python-format msgid "Got broadcast to %(delete_type)s delete instance" msgstr "" -#: nova/cells/messaging.py:811 +#: nova/cells/messaging.py:816 #, python-format msgid "Got message to create instance fault: %(instance_fault)s" msgstr "" -#: nova/cells/messaging.py:832 +#: nova/cells/messaging.py:837 #, python-format msgid "" "Forcing a sync of instances, project_id=%(projid_str)s, " "updated_since=%(since_str)s" msgstr "" -#: nova/cells/messaging.py:1009 +#: nova/cells/messaging.py:1014 #, python-format msgid "Updating parents with our capabilities: %(capabs)s" msgstr "" -#: nova/cells/messaging.py:1029 +#: nova/cells/messaging.py:1034 #, python-format msgid "Updating parents with our capacities: %(capacities)s" msgstr "" @@ -3431,207 +3446,202 @@ msgstr "" msgid "Metadata property value greater than 255 characters" msgstr "" -#: nova/compute/api.py:436 +#: nova/compute/api.py:449 msgid "Failed to set instance name using multi_instance_display_name_template." msgstr "" -#: nova/compute/api.py:476 +#: nova/compute/api.py:489 msgid "Cannot attach one or more volumes to multiple instances" msgstr "" -#: nova/compute/api.py:589 +#: nova/compute/api.py:603 #, python-format msgid "Going to run %s instances..." msgstr "" -#: nova/compute/api.py:701 +#: nova/compute/api.py:716 #, python-format msgid "bdm %s" msgstr "" -#: nova/compute/api.py:728 +#: nova/compute/api.py:743 #, python-format msgid "block_device_mapping %s" msgstr "" -#: nova/compute/api.py:1001 +#: nova/compute/api.py:1015 msgid "instance termination disabled" msgstr "" -#: nova/compute/api.py:1135 +#: nova/compute/api.py:1149 #, python-format msgid "instance type %(old_inst_type_id)d not found" msgstr "" -#: nova/compute/api.py:1141 +#: nova/compute/api.py:1155 msgid "going to delete a resizing instance" msgstr "" -#: nova/compute/api.py:1151 +#: nova/compute/api.py:1165 #, python-format msgid "instance's host %s is down, deleting from database" msgstr "" -#: nova/compute/api.py:1195 +#: nova/compute/api.py:1209 msgid "Going to try to soft delete instance" msgstr "" -#: nova/compute/api.py:1217 +#: nova/compute/api.py:1231 msgid "Going to try to terminate instance" msgstr "" -#: nova/compute/api.py:1267 +#: nova/compute/api.py:1281 msgid "Going to try to stop instance" msgstr "" -#: nova/compute/api.py:1284 +#: nova/compute/api.py:1298 msgid "Going to try to start instance" msgstr "" -#: nova/compute/api.py:1354 +#: nova/compute/api.py:1371 #, python-format msgid "Searching by: %s" msgstr "" -#: nova/compute/api.py:1598 +#: nova/compute/api.py:1615 #, python-format msgid "snapshot for %s" msgstr "" -#: nova/compute/api.py:1954 +#: nova/compute/api.py:1971 msgid "flavor_id is None. Assuming migration." msgstr "" -#: nova/compute/api.py:1963 +#: nova/compute/api.py:1980 #, python-format msgid "" "Old instance type %(current_instance_type_name)s, new instance type " "%(new_instance_type_name)s" msgstr "" -#: nova/compute/api.py:2005 +#: nova/compute/api.py:2022 #, python-format msgid "%(overs)s quota exceeded for %(pid)s, tried to resize instance." msgstr "" -#: nova/compute/api.py:2238 +#: nova/compute/api.py:2255 msgid "Locking" msgstr "" -#: nova/compute/api.py:2246 +#: nova/compute/api.py:2263 msgid "Unlocking" msgstr "" -#: nova/compute/api.py:2314 +#: nova/compute/api.py:2331 msgid "Volume must be attached in order to detach." msgstr "" -#: nova/compute/api.py:2421 +#: nova/compute/api.py:2438 #, python-format msgid "Going to try to live migrate instance to %s" msgstr "" -#: nova/compute/api.py:2440 +#: nova/compute/api.py:2457 msgid "vm evacuation scheduled" msgstr "" -#: nova/compute/api.py:2444 +#: nova/compute/api.py:2461 #, python-format msgid "" -"Instance compute service state on %(host)s expected to be down, but it " -"was up." +"Instance compute service state on %(inst_host)s expected to be down, but " +"it was up." msgstr "" -#: nova/compute/api.py:2664 +#: nova/compute/api.py:2681 msgid "Keypair name contains unsafe characters" msgstr "" -#: nova/compute/api.py:2668 +#: nova/compute/api.py:2685 msgid "Keypair name must be between 1 and 255 characters long" msgstr "" -#: nova/compute/api.py:2773 +#: nova/compute/api.py:2790 #, python-format msgid "Security group %s is not a string or unicode" msgstr "" -#: nova/compute/api.py:2776 +#: nova/compute/api.py:2793 #, python-format msgid "Security group %s cannot be empty." msgstr "" -#: nova/compute/api.py:2784 +#: nova/compute/api.py:2801 #, python-format msgid "" "Value (%(value)s) for parameter Group%(property)s is invalid. Content " "limited to '%(allowed)'." msgstr "" -#: nova/compute/api.py:2790 +#: nova/compute/api.py:2807 #, python-format msgid "Security group %s should not be greater than 255 characters." msgstr "" -#: nova/compute/api.py:2810 +#: nova/compute/api.py:2827 msgid "Quota exceeded, too many security groups." msgstr "" -#: nova/compute/api.py:2813 +#: nova/compute/api.py:2830 #, python-format msgid "Create Security Group %s" msgstr "" -#: nova/compute/api.py:2820 +#: nova/compute/api.py:2837 #, python-format msgid "Security group %s already exists" msgstr "" -#: nova/compute/api.py:2885 +#: nova/compute/api.py:2902 #, python-format msgid "Unable to delete system group '%s'" msgstr "" -#: nova/compute/api.py:2890 +#: nova/compute/api.py:2907 msgid "Security group is still in use" msgstr "" -#: nova/compute/api.py:2898 +#: nova/compute/api.py:2915 msgid "Failed to update usages deallocating security group" msgstr "" -#: nova/compute/api.py:2901 +#: nova/compute/api.py:2918 #, python-format msgid "Delete security group %s" msgstr "" -#: nova/compute/api.py:3010 nova/compute/api.py:3087 +#: nova/compute/api.py:3012 nova/compute/api.py:3089 #, python-format msgid "Rule (%s) not found" msgstr "" -#: nova/compute/api.py:3026 +#: nova/compute/api.py:3028 msgid "Quota exceeded, too many security group rules." msgstr "" -#: nova/compute/api.py:3029 +#: nova/compute/api.py:3031 #, python-format msgid "Authorize security group ingress %s" msgstr "" -#: nova/compute/api.py:3040 +#: nova/compute/api.py:3042 #, python-format msgid "Revoke security group ingress %s" msgstr "" -#: nova/compute/api.py:3094 +#: nova/compute/api.py:3096 msgid "Security group id should be integer" msgstr "" -#: nova/compute/api.py:3099 -#, python-format -msgid "This rule already exists in group %s" -msgstr "" - #: nova/compute/claims.py:94 nova/compute/claims.py:218 #, python-format msgid "Aborting claim: %s" @@ -3722,569 +3732,590 @@ msgstr "" msgid "Possibly task preempted." msgstr "" -#: nova/compute/manager.py:350 +#: nova/compute/manager.py:354 #, python-format msgid "%(nodename)s is not a valid node managed by this compute host." msgstr "" -#: nova/compute/manager.py:379 +#: nova/compute/manager.py:383 msgid "Instance has been destroyed from under us while trying to set it to ERROR" msgstr "" -#: nova/compute/manager.py:398 +#: nova/compute/manager.py:397 #, python-format msgid "Instance %(uuid)s found in the hypervisor, but not in the database" msgstr "" -#: nova/compute/manager.py:416 +#: nova/compute/manager.py:413 #, python-format msgid "" "Instance %(driver_instance)s found in the hypervisor, but not in the " "database" msgstr "" -#: nova/compute/manager.py:437 +#: nova/compute/manager.py:434 #, python-format msgid "" "Deleting instance as its host (%(instance_host)s) is not equal to our " "host (%(our_host)s)." msgstr "" -#: nova/compute/manager.py:464 +#: nova/compute/manager.py:471 +msgid "Failed to revert crashed migration" +msgstr "" + +#: nova/compute/manager.py:474 +msgid "Instance found in migrating state during startup. Resetting task_state" +msgstr "" + +#: nova/compute/manager.py:485 #, python-format msgid "Current state is %(drv_state)s, state in DB is %(db_state)s." msgstr "" -#: nova/compute/manager.py:476 +#: nova/compute/manager.py:490 msgid "Rebooting instance after nova-compute restart." msgstr "" -#: nova/compute/manager.py:490 +#: nova/compute/manager.py:504 msgid "Hypervisor driver does not support resume guests" msgstr "" -#: nova/compute/manager.py:495 +#: nova/compute/manager.py:509 msgid "Failed to resume instance" msgstr "" -#: nova/compute/manager.py:505 +#: nova/compute/manager.py:519 msgid "Hypervisor driver does not support firewall rules" msgstr "" -#: nova/compute/manager.py:509 +#: nova/compute/manager.py:523 #, python-format msgid "Lifecycle event %(state)d on VM %(uuid)s" msgstr "" -#: nova/compute/manager.py:525 +#: nova/compute/manager.py:539 #, python-format msgid "Unexpected power state %d" msgstr "" -#: nova/compute/manager.py:537 +#: nova/compute/manager.py:551 #, python-format msgid "Ignoring event %s" msgstr "" -#: nova/compute/manager.py:575 +#: nova/compute/manager.py:589 msgid "Checking state" msgstr "" -#: nova/compute/manager.py:655 +#: nova/compute/manager.py:669 #, python-format msgid "Setting up bdm %s" msgstr "" -#: nova/compute/manager.py:737 nova/compute/manager.py:2077 +#: nova/compute/manager.py:751 nova/compute/manager.py:2104 #, python-format msgid "No node specified, defaulting to %(node)s" msgstr "" -#: nova/compute/manager.py:780 +#: nova/compute/manager.py:794 msgid "Failed to dealloc network for deleted instance" msgstr "" -#: nova/compute/manager.py:805 +#: nova/compute/manager.py:800 +msgid "Instance was deleted during spawn." +msgstr "" + +#: nova/compute/manager.py:826 #, python-format msgid "Error: %s" msgstr "" -#: nova/compute/manager.py:840 nova/compute/manager.py:2131 +#: nova/compute/manager.py:861 nova/compute/manager.py:2158 msgid "Error trying to reschedule" msgstr "" -#: nova/compute/manager.py:858 +#: nova/compute/manager.py:879 msgid "Retry info not present, will not reschedule" msgstr "" -#: nova/compute/manager.py:863 +#: nova/compute/manager.py:884 msgid "No request spec, will not reschedule" msgstr "" -#: nova/compute/manager.py:869 +#: nova/compute/manager.py:890 #, python-format msgid "Re-scheduling %(method)s: attempt %(num)d" msgstr "" -#: nova/compute/manager.py:897 +#: nova/compute/manager.py:918 msgid "Instance build timed out. Set to error state." msgstr "" -#: nova/compute/manager.py:973 +#: nova/compute/manager.py:994 #, python-format msgid "" "image_id=%(image_id)s, image_size_bytes=%(size_bytes)d, " "allowed_size_bytes=%(allowed_size_bytes)d" msgstr "" -#: nova/compute/manager.py:979 +#: nova/compute/manager.py:1000 #, python-format msgid "" "Image '%(image_id)s' size %(size_bytes)d exceeded instance_type allowed " "size %(allowed_size_bytes)d" msgstr "" -#: nova/compute/manager.py:989 +#: nova/compute/manager.py:1010 msgid "Starting instance..." msgstr "" -#: nova/compute/manager.py:1014 +#: nova/compute/manager.py:1035 msgid "Instance failed network setup" msgstr "" -#: nova/compute/manager.py:1018 +#: nova/compute/manager.py:1039 #, python-format msgid "Instance network_info: |%s|" msgstr "" -#: nova/compute/manager.py:1028 +#: nova/compute/manager.py:1049 msgid "Instance failed block device setup" msgstr "" -#: nova/compute/manager.py:1045 +#: nova/compute/manager.py:1066 msgid "Instance failed to spawn" msgstr "" -#: nova/compute/manager.py:1069 +#: nova/compute/manager.py:1090 msgid "Deallocating network for instance" msgstr "" -#: nova/compute/manager.py:1145 +#: nova/compute/manager.py:1166 #, python-format msgid "%(action_str)s instance" msgstr "" -#: nova/compute/manager.py:1176 +#: nova/compute/manager.py:1182 +msgid "Failed to deallocate network for instance." +msgstr "" + +#: nova/compute/manager.py:1203 #, python-format msgid "Ignoring DiskNotFound: %s" msgstr "" -#: nova/compute/manager.py:1179 +#: nova/compute/manager.py:1206 #, python-format msgid "Ignoring VolumeNotFound: %s" msgstr "" -#: nova/compute/manager.py:1186 +#: nova/compute/manager.py:1213 #, python-format msgid "terminating bdm %s" msgstr "" -#: nova/compute/manager.py:1211 +#: nova/compute/manager.py:1238 #, python-format msgid "Ignoring volume cleanup failure due to %s" msgstr "" -#: nova/compute/manager.py:1254 nova/compute/manager.py:2306 -#: nova/compute/manager.py:3739 +#: nova/compute/manager.py:1281 nova/compute/manager.py:2333 +#: nova/compute/manager.py:3773 #, python-format msgid "%s. Setting instance vm_state to ERROR" msgstr "" -#: nova/compute/manager.py:1394 +#: nova/compute/manager.py:1421 msgid "Rebuilding instance" msgstr "" -#: nova/compute/manager.py:1407 +#: nova/compute/manager.py:1434 msgid "Invalid state of instance files on shared storage" msgstr "" -#: nova/compute/manager.py:1411 +#: nova/compute/manager.py:1438 msgid "disk on shared storage, recreating using existing disk" msgstr "" -#: nova/compute/manager.py:1415 +#: nova/compute/manager.py:1442 #, python-format msgid "disk not on shared storagerebuilding from: '%s'" msgstr "" -#: nova/compute/manager.py:1499 +#: nova/compute/manager.py:1526 #, python-format msgid "bringing vm to original state: '%s'" msgstr "" -#: nova/compute/manager.py:1523 +#: nova/compute/manager.py:1550 msgid "Rebooting instance" msgstr "" -#: nova/compute/manager.py:1542 +#: nova/compute/manager.py:1569 #, python-format msgid "" "trying to reboot a non-running instance: (state: %(state)s expected: " "%(running)s)" msgstr "" -#: nova/compute/manager.py:1552 +#: nova/compute/manager.py:1579 #, python-format msgid "Cannot reboot instance: %(exc)s" msgstr "" -#: nova/compute/manager.py:1588 +#: nova/compute/manager.py:1615 msgid "instance snapshotting" msgstr "" -#: nova/compute/manager.py:1594 +#: nova/compute/manager.py:1621 #, python-format msgid "" "trying to snapshot a non-running instance: (state: %(state)s expected: " "%(running)s)" msgstr "" -#: nova/compute/manager.py:1655 +#: nova/compute/manager.py:1682 #, python-format msgid "Found %(num_images)d images (rotation: %(rotation)d)" msgstr "" -#: nova/compute/manager.py:1662 +#: nova/compute/manager.py:1689 #, python-format msgid "Rotating out %d backups" msgstr "" -#: nova/compute/manager.py:1667 +#: nova/compute/manager.py:1694 #, python-format msgid "Deleting image %s" msgstr "" -#: nova/compute/manager.py:1695 +#: nova/compute/manager.py:1722 #, python-format msgid "Failed to set admin password. Instance %s is not running" msgstr "" -#: nova/compute/manager.py:1702 +#: nova/compute/manager.py:1729 msgid "Root password set" msgstr "" -#: nova/compute/manager.py:1709 +#: nova/compute/manager.py:1736 msgid "set_admin_password is not implemented by this driver or guest instance." msgstr "" -#: nova/compute/manager.py:1724 +#: nova/compute/manager.py:1751 #, python-format msgid "set_admin_password failed: %s" msgstr "" -#: nova/compute/manager.py:1731 +#: nova/compute/manager.py:1758 msgid "error setting admin password" msgstr "" -#: nova/compute/manager.py:1744 +#: nova/compute/manager.py:1771 #, python-format msgid "" "trying to inject a file into a non-running (state: " "%(current_power_state)s expected: %(expected_state)s)" msgstr "" -#: nova/compute/manager.py:1748 +#: nova/compute/manager.py:1775 #, python-format msgid "injecting file to %(path)s" msgstr "" -#: nova/compute/manager.py:1768 +#: nova/compute/manager.py:1795 msgid "" "Unable to find a different image to use for rescue VM, using instance's " "current image" msgstr "" -#: nova/compute/manager.py:1782 +#: nova/compute/manager.py:1809 msgid "Rescuing" msgstr "" -#: nova/compute/manager.py:1817 +#: nova/compute/manager.py:1844 msgid "Unrescuing" msgstr "" -#: nova/compute/manager.py:1838 +#: nova/compute/manager.py:1865 #, python-format msgid "Changing instance metadata according to %(diff)r" msgstr "" -#: nova/compute/manager.py:2035 +#: nova/compute/manager.py:2062 msgid "Instance has no source host" msgstr "" -#: nova/compute/manager.py:2041 +#: nova/compute/manager.py:2068 msgid "destination same as source!" msgstr "" -#: nova/compute/manager.py:2058 +#: nova/compute/manager.py:2085 msgid "Migrating" msgstr "" -#: nova/compute/manager.py:2303 +#: nova/compute/manager.py:2330 #, python-format msgid "Failed to rollback quota for failed finish_resize: %(qr_error)s" msgstr "" -#: nova/compute/manager.py:2358 +#: nova/compute/manager.py:2385 msgid "Pausing" msgstr "" -#: nova/compute/manager.py:2376 +#: nova/compute/manager.py:2403 msgid "Unpausing" msgstr "" -#: nova/compute/manager.py:2414 +#: nova/compute/manager.py:2441 msgid "Retrieving diagnostics" msgstr "" -#: nova/compute/manager.py:2445 +#: nova/compute/manager.py:2472 msgid "Resuming" msgstr "" -#: nova/compute/manager.py:2465 +#: nova/compute/manager.py:2492 msgid "Reset network" msgstr "" -#: nova/compute/manager.py:2470 +#: nova/compute/manager.py:2497 msgid "Inject network info" msgstr "" -#: nova/compute/manager.py:2473 +#: nova/compute/manager.py:2500 #, python-format msgid "network_info to inject: |%s|" msgstr "" -#: nova/compute/manager.py:2490 +#: nova/compute/manager.py:2517 msgid "Get console output" msgstr "" -#: nova/compute/manager.py:2515 +#: nova/compute/manager.py:2542 msgid "Getting vnc console" msgstr "" -#: nova/compute/manager.py:2543 +#: nova/compute/manager.py:2570 msgid "Getting spice console" msgstr "" -#: nova/compute/manager.py:2583 +#: nova/compute/manager.py:2610 #, python-format msgid "Booting with volume %(volume_id)s at %(mountpoint)s" msgstr "" -#: nova/compute/manager.py:2634 +#: nova/compute/manager.py:2661 #, python-format msgid "Attaching volume %(volume_id)s to %(mountpoint)s" msgstr "" -#: nova/compute/manager.py:2643 +#: nova/compute/manager.py:2670 #, python-format msgid "" "Failed to connect to volume %(volume_id)s while attaching at " "%(mountpoint)s" msgstr "" -#: nova/compute/manager.py:2658 +#: nova/compute/manager.py:2685 #, python-format msgid "Failed to attach volume %(volume_id)s at %(mountpoint)s" msgstr "" -#: nova/compute/manager.py:2688 +#: nova/compute/manager.py:2715 #, python-format msgid "Detach volume %(volume_id)s from mountpoint %(mp)s" msgstr "" -#: nova/compute/manager.py:2698 +#: nova/compute/manager.py:2725 msgid "Detaching volume from unknown instance" msgstr "" -#: nova/compute/manager.py:2705 +#: nova/compute/manager.py:2732 #, python-format msgid "Failed to detach volume %(volume_id)s from %(mp)s" msgstr "" -#: nova/compute/manager.py:2729 +#: nova/compute/manager.py:2756 msgid "Updating volume usage cache with totals" msgstr "" -#: nova/compute/manager.py:2785 +#: nova/compute/manager.py:2794 +#, python-format +msgid "allocate_port_for_instance returned %(port)s ports" +msgstr "" + +#: nova/compute/manager.py:2814 #, python-format msgid "Port %(port_id)s is not attached" msgstr "" -#: nova/compute/manager.py:2799 +#: nova/compute/manager.py:2828 #, python-format msgid "Host %(host)s not found" msgstr "" -#: nova/compute/manager.py:2928 +#: nova/compute/manager.py:2957 #, python-format msgid "Pre live migration failed at %(dest)s" msgstr "" -#: nova/compute/manager.py:2956 +#: nova/compute/manager.py:2985 msgid "_post_live_migration() is started.." msgstr "" -#: nova/compute/manager.py:3011 +#: nova/compute/manager.py:3040 #, python-format msgid "Migrating instance to %(dest)s finished successfully." msgstr "" -#: nova/compute/manager.py:3013 +#: nova/compute/manager.py:3042 msgid "" "You may see the error \"libvirt: QEMU error: Domain not found: no domain " "with matching name.\" This error can be safely ignored." msgstr "" -#: nova/compute/manager.py:3027 +#: nova/compute/manager.py:3056 msgid "Post operation of migration started" msgstr "" -#: nova/compute/manager.py:3167 +#: nova/compute/manager.py:3196 msgid "Updated the info_cache for instance" msgstr "" -#: nova/compute/manager.py:3212 +#: nova/compute/manager.py:3241 #, python-format msgid "" "Found %(migration_count)d unconfirmed migrations older than " "%(confirm_window)d seconds" msgstr "" -#: nova/compute/manager.py:3218 +#: nova/compute/manager.py:3247 #, python-format msgid "Setting migration %(migration_id)s to error: %(reason)s" msgstr "" -#: nova/compute/manager.py:3227 +#: nova/compute/manager.py:3256 #, python-format msgid "" "Automatically confirming migration %(migration_id)s for instance " "%(instance_uuid)s" msgstr "" -#: nova/compute/manager.py:3234 +#: nova/compute/manager.py:3263 #, python-format msgid "Instance %(instance_uuid)s not found" msgstr "" -#: nova/compute/manager.py:3238 +#: nova/compute/manager.py:3267 msgid "In ERROR state" msgstr "" -#: nova/compute/manager.py:3245 +#: nova/compute/manager.py:3274 #, python-format msgid "In states %(vm_state)s/%(task_state)s, not RESIZED/None" msgstr "" -#: nova/compute/manager.py:3253 +#: nova/compute/manager.py:3282 #, python-format msgid "Error auto-confirming resize: %(e)s. Will retry later." msgstr "" -#: nova/compute/manager.py:3270 +#: nova/compute/manager.py:3299 #, python-format msgid "" "Running instance usage audit for host %(host)s from %(begin_time)s to " "%(end_time)s. %(number_instances)s instances." msgstr "" -#: nova/compute/manager.py:3289 +#: nova/compute/manager.py:3318 #, python-format msgid "Failed to generate usage audit for instance on host %s" msgstr "" -#: nova/compute/manager.py:3313 +#: nova/compute/manager.py:3342 msgid "Updating bandwidth usage cache" msgstr "" -#: nova/compute/manager.py:3431 +#: nova/compute/manager.py:3460 msgid "Updating volume usage cache" msgstr "" -#: nova/compute/manager.py:3449 +#: nova/compute/manager.py:3478 msgid "Updating host status" msgstr "" -#: nova/compute/manager.py:3475 +#: nova/compute/manager.py:3504 #, python-format msgid "" "Found %(num_db_instances)s in the database and %(num_vm_instances)s on " "the hypervisor." msgstr "" -#: nova/compute/manager.py:3480 nova/compute/manager.py:3529 +#: nova/compute/manager.py:3509 nova/compute/manager.py:3558 msgid "During sync_power_state the instance has a pending task. Skip." msgstr "" -#: nova/compute/manager.py:3516 +#: nova/compute/manager.py:3545 #, python-format msgid "" "During the sync_power process the instance has moved from host %(src)s to" " host %(dst)s" msgstr "" -#: nova/compute/manager.py:3554 +#: nova/compute/manager.py:3583 msgid "Instance shutdown by itself. Calling the stop API." msgstr "" -#: nova/compute/manager.py:3566 nova/compute/manager.py:3575 -#: nova/compute/manager.py:3605 +#: nova/compute/manager.py:3595 nova/compute/manager.py:3604 +#: nova/compute/manager.py:3634 msgid "error during stop() in sync_power_state." msgstr "" -#: nova/compute/manager.py:3570 +#: nova/compute/manager.py:3599 msgid "Instance is suspended unexpectedly. Calling the stop API." msgstr "" -#: nova/compute/manager.py:3586 +#: nova/compute/manager.py:3615 msgid "Instance is paused unexpectedly. Ignore." msgstr "" -#: nova/compute/manager.py:3592 +#: nova/compute/manager.py:3621 msgid "Instance is unexpectedly not found. Ignore." msgstr "" -#: nova/compute/manager.py:3598 +#: nova/compute/manager.py:3627 msgid "Instance is not stopped. Calling the stop API." msgstr "" -#: nova/compute/manager.py:3614 +#: nova/compute/manager.py:3643 msgid "Instance is not (soft-)deleted." msgstr "" -#: nova/compute/manager.py:3622 +#: nova/compute/manager.py:3651 msgid "CONF.reclaim_instance_interval <= 0, skipping..." msgstr "" -#: nova/compute/manager.py:3637 +#: nova/compute/manager.py:3666 msgid "Reclaiming deleted instance" msgstr "" -#: nova/compute/manager.py:3692 +#: nova/compute/manager.py:3728 #, python-format msgid "" "Detected instance with name label '%(name)s' which is marked as DELETED " "but still present on host." msgstr "" -#: nova/compute/manager.py:3699 +#: nova/compute/manager.py:3735 #, python-format msgid "" "Destroying instance with name label '%(name)s' which is marked as DELETED" " but still present on host." msgstr "" -#: nova/compute/manager.py:3706 +#: nova/compute/manager.py:3742 #, python-format msgid "Unrecognized value '%(action)s' for CONF.running_deleted_instance_action" msgstr "" @@ -4305,86 +4336,91 @@ msgstr "" msgid "Auditing locally available compute resources" msgstr "" -#: nova/compute/resource_tracker.py:241 +#: nova/compute/resource_tracker.py:245 msgid "" "Virt driver does not support 'get_available_resource' Compute tracking " "is disabled." msgstr "" -#: nova/compute/resource_tracker.py:293 +#: nova/compute/resource_tracker.py:280 +#, python-format +msgid "Deleting compute node %s" +msgstr "" + +#: nova/compute/resource_tracker.py:304 #, python-format msgid "Compute_service record created for %(host)s:%(node)s" msgstr "" -#: nova/compute/resource_tracker.py:299 +#: nova/compute/resource_tracker.py:310 #, python-format msgid "Compute_service record updated for %(host)s:%(node)s" msgstr "" -#: nova/compute/resource_tracker.py:313 +#: nova/compute/resource_tracker.py:324 #, python-format msgid "No service record for host %s" msgstr "" -#: nova/compute/resource_tracker.py:323 +#: nova/compute/resource_tracker.py:334 #, python-format msgid "Hypervisor: free ram (MB): %s" msgstr "" -#: nova/compute/resource_tracker.py:324 +#: nova/compute/resource_tracker.py:335 #, python-format msgid "Hypervisor: free disk (GB): %s" msgstr "" -#: nova/compute/resource_tracker.py:329 +#: nova/compute/resource_tracker.py:340 #, python-format msgid "Hypervisor: free VCPUs: %s" msgstr "" -#: nova/compute/resource_tracker.py:331 +#: nova/compute/resource_tracker.py:342 msgid "Hypervisor: VCPU information unavailable" msgstr "" -#: nova/compute/resource_tracker.py:338 +#: nova/compute/resource_tracker.py:349 #, python-format msgid "Free ram (MB): %s" msgstr "" -#: nova/compute/resource_tracker.py:339 +#: nova/compute/resource_tracker.py:350 #, python-format msgid "Free disk (GB): %s" msgstr "" -#: nova/compute/resource_tracker.py:344 +#: nova/compute/resource_tracker.py:355 #, python-format msgid "Free VCPUS: %s" msgstr "" -#: nova/compute/resource_tracker.py:346 +#: nova/compute/resource_tracker.py:357 msgid "Free VCPU information unavailable" msgstr "" -#: nova/compute/resource_tracker.py:384 +#: nova/compute/resource_tracker.py:395 #, python-format msgid "Updating from migration %s" msgstr "" -#: nova/compute/resource_tracker.py:440 +#: nova/compute/resource_tracker.py:451 msgid "Instance not resizing, skipping migration." msgstr "" -#: nova/compute/resource_tracker.py:454 +#: nova/compute/resource_tracker.py:465 msgid "InstanceType could not be found, skipping migration." msgstr "" -#: nova/compute/resource_tracker.py:538 +#: nova/compute/resource_tracker.py:549 #, python-format msgid "" "Detected running orphan instance: %(uuid)s (consuming %(memory_mb)s MB " "memory" msgstr "" -#: nova/compute/resource_tracker.py:551 +#: nova/compute/resource_tracker.py:562 #, python-format msgid "Missing keys: %s" msgstr "" @@ -4403,7 +4439,7 @@ msgstr "" msgid "Using %(prefix)s instead of %(req_prefix)s" msgstr "" -#: nova/conductor/api.py:367 +#: nova/conductor/api.py:370 msgid "" "Timed out waiting for nova-conductor. Is it running? Or did this service " "start before nova-conductor?" @@ -4488,23 +4524,23 @@ msgstr "" msgid "Checking Token: %(token)s, %(token_valid)s)" msgstr "" -#: nova/db/api.py:577 +#: nova/db/api.py:585 msgid "Failed to notify cells of instance destroy" msgstr "" -#: nova/db/api.py:670 nova/db/api.py:691 +#: nova/db/api.py:673 nova/db/api.py:694 msgid "Failed to notify cells of instance update" msgstr "" -#: nova/db/api.py:731 +#: nova/db/api.py:734 msgid "Failed to notify cells of instance info cache update" msgstr "" -#: nova/db/api.py:1454 +#: nova/db/api.py:1428 msgid "Failed to notify cells of bw_usage update" msgstr "" -#: nova/db/api.py:1608 +#: nova/db/api.py:1582 msgid "Failed to notify cells of instance fault" msgstr "" @@ -4513,23 +4549,28 @@ msgstr "" msgid "Deadlock detected when running '%(func_name)s': Retrying..." msgstr "" -#: nova/db/sqlalchemy/api.py:202 +#: nova/db/sqlalchemy/api.py:187 msgid "model or base_model parameter should be subclass of NovaBase" msgstr "" -#: nova/db/sqlalchemy/api.py:215 nova/virt/baremetal/db/sqlalchemy/api.py:63 +#: nova/db/sqlalchemy/api.py:200 nova/virt/baremetal/db/sqlalchemy/api.py:64 #, python-format msgid "Unrecognized read_deleted value '%s'" msgstr "" -#: nova/db/sqlalchemy/api.py:1388 +#: nova/db/sqlalchemy/api.py:1385 #, python-format msgid "" "Unknown osapi_compute_unique_server_name_scope value: %s Flag must be " "empty, \"global\" or \"project\"" msgstr "" -#: nova/db/sqlalchemy/api.py:2704 +#: nova/db/sqlalchemy/api.py:1521 +#, python-format +msgid "Invalid instance id %s in request" +msgstr "" + +#: nova/db/sqlalchemy/api.py:2654 #, python-format msgid "Change will make usage less than 0 for the following resources: %(unders)s" msgstr "" @@ -4572,10 +4613,6 @@ msgstr "" msgid "Exception while creating table." msgstr "" -#: nova/db/sqlalchemy/migrate_repo/versions/133_folsom.py:1225 -msgid "Downgrade from Folsom is unsupported." -msgstr "" - #: nova/db/sqlalchemy/migrate_repo/versions/145_add_volume_usage_cache.py:68 msgid "volume_usage_cache table not dropped" msgstr "" @@ -4651,15 +4688,15 @@ msgstr "" msgid "Bad project_id for to_global_ipv6: %s" msgstr "" -#: nova/network/api.py:54 nova/network/api_deprecated.py:56 +#: nova/network/api.py:54 msgid "instance is a required argument to use @refresh_cache" msgstr "" -#: nova/network/api.py:79 nova/network/api_deprecated.py:79 +#: nova/network/api.py:79 msgid "Failed storing info cache" msgstr "" -#: nova/network/api.py:227 nova/network/api_deprecated.py:216 +#: nova/network/api.py:227 nova/network/api_deprecated.py:156 #, python-format msgid "re-assign floating IP %(address)s from instance %(instance_id)s" msgstr "" @@ -4773,118 +4810,123 @@ msgstr "" msgid "This shouldn't be getting called except during testing." msgstr "" -#: nova/network/linux_net.py:213 +#: nova/network/linux_net.py:214 #, python-format msgid "Attempted to remove chain %s which does not exist" msgstr "" -#: nova/network/linux_net.py:248 +#: nova/network/linux_net.py:249 #, python-format msgid "Unknown chain: %r" msgstr "" -#: nova/network/linux_net.py:273 +#: nova/network/linux_net.py:274 #, 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:410 +#: nova/network/linux_net.py:419 msgid "IPTablesManager.apply completed with success" msgstr "" -#: nova/network/linux_net.py:667 +#: nova/network/linux_net.py:676 #, python-format msgid "arping error for ip %s" msgstr "" -#: nova/network/linux_net.py:947 +#: nova/network/linux_net.py:726 +#, python-format +msgid "Removed %(num)d duplicate rules for floating ip %(float)s" +msgstr "" + +#: nova/network/linux_net.py:962 #, python-format msgid "Pid %d is stale, skip killing dnsmasq" msgstr "" -#: nova/network/linux_net.py:992 +#: nova/network/linux_net.py:1007 #, python-format msgid "Hupping dnsmasq threw %s" msgstr "" -#: nova/network/linux_net.py:994 +#: nova/network/linux_net.py:1009 #, python-format msgid "Pid %d is stale, relaunching dnsmasq" msgstr "" -#: nova/network/linux_net.py:1069 +#: nova/network/linux_net.py:1084 #, python-format msgid "killing radvd threw %s" msgstr "" -#: nova/network/linux_net.py:1071 +#: nova/network/linux_net.py:1086 #, python-format msgid "Pid %d is stale, relaunching radvd" msgstr "" -#: nova/network/linux_net.py:1203 +#: nova/network/linux_net.py:1218 #, python-format msgid "Error clearing stale veth %s" msgstr "" -#: nova/network/linux_net.py:1362 +#: nova/network/linux_net.py:1377 #, python-format msgid "Starting VLAN interface %s" msgstr "" -#: nova/network/linux_net.py:1393 +#: nova/network/linux_net.py:1408 #, python-format msgid "Failed unplugging VLAN interface '%s'" msgstr "" -#: nova/network/linux_net.py:1396 +#: nova/network/linux_net.py:1411 #, python-format msgid "Unplugged VLAN interface '%s'" msgstr "" -#: nova/network/linux_net.py:1418 +#: nova/network/linux_net.py:1433 #, python-format msgid "Starting Bridge %s" msgstr "" -#: nova/network/linux_net.py:1430 +#: nova/network/linux_net.py:1445 #, python-format msgid "Adding interface %(interface)s to bridge %(bridge)s" msgstr "" -#: nova/network/linux_net.py:1463 +#: nova/network/linux_net.py:1478 #, python-format msgid "Failed to add interface: %s" msgstr "" -#: nova/network/linux_net.py:1499 +#: nova/network/linux_net.py:1514 #, python-format msgid "Failed unplugging bridge interface '%s'" msgstr "" -#: nova/network/linux_net.py:1502 +#: nova/network/linux_net.py:1517 #, python-format msgid "Unplugged bridge interface '%s'" msgstr "" -#: nova/network/linux_net.py:1671 +#: nova/network/linux_net.py:1686 #, python-format msgid "Starting bridge %s " msgstr "" -#: nova/network/linux_net.py:1679 +#: nova/network/linux_net.py:1694 #, python-format msgid "Done starting bridge %s" msgstr "" -#: nova/network/linux_net.py:1698 +#: nova/network/linux_net.py:1713 #, python-format msgid "Failed unplugging gateway interface '%s'" msgstr "" -#: nova/network/linux_net.py:1700 +#: nova/network/linux_net.py:1715 #, python-format msgid "Unplugged gateway interface '%s'" msgstr "" @@ -5049,138 +5091,143 @@ msgstr "" msgid "empty project id for instance %s" msgstr "" -#: nova/network/quantumv2/api.py:197 +#: nova/network/quantumv2/api.py:198 #, python-format msgid "" "Multiple security groups found matching '%s'. Use an ID to be more " "specific." msgstr "" -#: nova/network/quantumv2/api.py:265 +#: nova/network/quantumv2/api.py:266 msgid "Port not found" msgstr "" -#: nova/network/quantumv2/api.py:273 +#: nova/network/quantumv2/api.py:274 #, python-format msgid "Fail to delete port %(portid)s with failure: %(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:303 +#: nova/network/quantumv2/api.py:311 #, python-format msgid "deallocate_for_instance() for %s" msgstr "" -#: nova/network/quantumv2/api.py:312 +#: nova/network/quantumv2/api.py:320 #, python-format msgid "Failed to delete quantum port %(portid)s " msgstr "" -#: nova/network/quantumv2/api.py:329 +#: nova/network/quantumv2/api.py:337 #, python-format msgid "Failed to delete quantum port %(port_id)s " msgstr "" -#: nova/network/quantumv2/api.py:352 +#: nova/network/quantumv2/api.py:360 #, python-format msgid "get_instance_nw_info() for %s" msgstr "" -#: nova/network/quantumv2/api.py:382 +#: nova/network/quantumv2/api.py:390 #, python-format msgid "" "Unable to update port %(portid)s on subnet %(subnet_id)s with failure: " "%(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:411 +#: nova/network/quantumv2/api.py:419 #, python-format msgid "Unable to update port %(portid)s with failure: %(exception)s" msgstr "" -#: nova/network/quantumv2/api.py:421 +#: nova/network/quantumv2/api.py:429 #, python-format msgid "validate_networks() for %s" msgstr "" -#: nova/network/quantumv2/api.py:678 +#: nova/network/quantumv2/api.py:686 #, python-format msgid "Multiple floating IP pools matches found for name '%s'" msgstr "" +#: nova/network/quantumv2/api.py:786 +#, python-format +msgid "Network %(net)s for port %(port_id)s not found!" +msgstr "" + #: nova/network/security_group/quantum_driver.py:55 #, python-format msgid "Quantum Error creating security group %s" msgstr "" -#: nova/network/security_group/quantum_driver.py:103 -#: nova/network/security_group/quantum_driver.py:164 +#: nova/network/security_group/quantum_driver.py:106 +#: nova/network/security_group/quantum_driver.py:172 #, python-format msgid "Quantum Error getting security group %s" msgstr "" -#: nova/network/security_group/quantum_driver.py:107 -#: nova/network/security_group/quantum_driver.py:146 -#: nova/network/security_group/quantum_driver.py:240 +#: nova/network/security_group/quantum_driver.py:110 +#: nova/network/security_group/quantum_driver.py:154 +#: nova/network/security_group/quantum_driver.py:244 #, python-format msgid "Quantum Error: %s" msgstr "" -#: nova/network/security_group/quantum_driver.py:120 +#: nova/network/security_group/quantum_driver.py:128 msgid "Quantum Error getting security groups" msgstr "" -#: nova/network/security_group/quantum_driver.py:130 +#: nova/network/security_group/quantum_driver.py:138 msgid "Security group id should be uuid" msgstr "" -#: nova/network/security_group/quantum_driver.py:168 -#: nova/network/security_group/quantum_driver.py:299 -#: nova/network/security_group/quantum_driver.py:305 -#: nova/network/security_group/quantum_driver.py:331 -#: nova/network/security_group/quantum_driver.py:347 -#: nova/network/security_group/quantum_driver.py:353 -#: nova/network/security_group/quantum_driver.py:382 +#: nova/network/security_group/quantum_driver.py:176 +#: nova/network/security_group/quantum_driver.py:303 +#: nova/network/security_group/quantum_driver.py:309 +#: nova/network/security_group/quantum_driver.py:335 +#: nova/network/security_group/quantum_driver.py:351 +#: nova/network/security_group/quantum_driver.py:357 +#: nova/network/security_group/quantum_driver.py:386 msgid "Quantum Error:" msgstr "" -#: nova/network/security_group/quantum_driver.py:225 +#: nova/network/security_group/quantum_driver.py:229 #, python-format msgid "Quantum Error unable to delete %s" msgstr "" -#: nova/network/security_group/quantum_driver.py:236 +#: nova/network/security_group/quantum_driver.py:240 #, python-format msgid "Quantum Error getting security group rule %s." msgstr "" -#: nova/network/security_group/quantum_driver.py:315 +#: nova/network/security_group/quantum_driver.py:319 #, python-format msgid "" "Cannot add security group %(name)s to %(instance)s since the port " "%(port_id)s does not meet security requirements" msgstr "" -#: nova/network/security_group/quantum_driver.py:325 -#: nova/network/security_group/quantum_driver.py:375 +#: nova/network/security_group/quantum_driver.py:329 +#: nova/network/security_group/quantum_driver.py:379 #, python-format msgid "Adding security group %(security_group_id)s to port %(port_id)s" msgstr "" -#: nova/network/security_group/quantum_driver.py:385 +#: nova/network/security_group/quantum_driver.py:389 #, python-format msgid "" "Security group %(security_group_name)s not assocaited with the instance " "%(instance)s" msgstr "" -#: nova/openstack/common/excutils.py:48 +#: nova/network/security_group/security_group_base.py:137 #, python-format -msgid "Original exception being dropped: %s" +msgid "This rule already exists in group %s" msgstr "" -#: nova/openstack/common/jsonutils.py:88 +#: nova/openstack/common/excutils.py:48 #, python-format -msgid "Max serialization depth exceeded on object: %d %s" +msgid "Original exception being dropped: %s" msgstr "" #: nova/openstack/common/lockutils.py:97 @@ -5213,12 +5260,12 @@ msgstr "" msgid "Deprecated: %s" msgstr "" -#: nova/openstack/common/log.py:363 +#: nova/openstack/common/log.py:358 #, python-format msgid "syslog facility must be one of: %s" msgstr "" -#: nova/openstack/common/log.py:523 +#: nova/openstack/common/log.py:518 #, python-format msgid "Fatal call to deprecated config: %(msg)s" msgstr "" @@ -5238,16 +5285,16 @@ msgstr "" msgid "Failed to understand rule %(rule)r" msgstr "" -#: nova/openstack/common/db/sqlalchemy/session.py:423 +#: nova/openstack/common/db/sqlalchemy/session.py:435 msgid "DB exception wrapped." msgstr "" -#: nova/openstack/common/db/sqlalchemy/session.py:473 +#: nova/openstack/common/db/sqlalchemy/session.py:485 #, python-format msgid "Got mysql server has gone away: %s" msgstr "" -#: nova/openstack/common/db/sqlalchemy/session.py:543 +#: nova/openstack/common/db/sqlalchemy/session.py:555 #, python-format msgid "SQL connection failed. %s attempts left." msgstr "" @@ -5704,7 +5751,7 @@ msgstr "" msgid "Driver must implement select_hosts" msgstr "" -#: nova/scheduler/driver.py:333 +#: nova/scheduler/driver.py:335 #, python-format msgid "" "Unable to migrate %(instance_uuid)s to %(dest)s: Lack of " @@ -5900,109 +5947,109 @@ msgstr "" msgid "least_cost has been deprecated in favor of the RAM Weigher." msgstr "" -#: nova/servicegroup/api.py:61 +#: nova/servicegroup/api.py:60 #, python-format msgid "ServiceGroup driver defined as an instance of %s" msgstr "" -#: nova/servicegroup/api.py:67 +#: nova/servicegroup/api.py:66 #, python-format msgid "unknown ServiceGroup driver name: %s" msgstr "" -#: nova/servicegroup/api.py:84 +#: nova/servicegroup/api.py:83 #, python-format msgid "" "Join new ServiceGroup member %(member_id)s to the %(group_id)s group, " "service = %(service)s" msgstr "" -#: nova/servicegroup/api.py:91 +#: nova/servicegroup/api.py:90 #, python-format msgid "Check if the given member [%s] is part of the ServiceGroup, is up" msgstr "" -#: nova/servicegroup/api.py:100 +#: nova/servicegroup/api.py:99 #, python-format msgid "" "Explicitly remove the given member %(member_id)s from the%(group_id)s " "group monitoring" msgstr "" -#: nova/servicegroup/api.py:107 +#: nova/servicegroup/api.py:106 #, python-format msgid "Returns ALL members of the [%s] ServiceGroup" msgstr "" -#: nova/servicegroup/api.py:115 +#: nova/servicegroup/api.py:114 #, python-format msgid "Returns one member of the [%s] group" msgstr "" -#: nova/servicegroup/drivers/db.py:42 +#: nova/servicegroup/drivers/db.py:41 #, python-format msgid "" "DB_Driver: join new ServiceGroup member %(member_id)s to the %(group_id)s" " group, service = %(service)s" msgstr "" -#: nova/servicegroup/drivers/db.py:46 +#: nova/servicegroup/drivers/db.py:45 msgid "service is a mandatory argument for DB based ServiceGroup driver" msgstr "" -#: nova/servicegroup/drivers/db.py:75 +#: nova/servicegroup/drivers/db.py:74 #, python-format msgid "DB_Driver: get_all members of the %s group" msgstr "" -#: nova/servicegroup/drivers/db.py:98 nova/servicegroup/drivers/mc.py:103 +#: nova/servicegroup/drivers/db.py:97 nova/servicegroup/drivers/mc.py:102 msgid "Recovered model server connection!" msgstr "" -#: nova/servicegroup/drivers/db.py:104 nova/servicegroup/drivers/mc.py:109 +#: nova/servicegroup/drivers/db.py:103 nova/servicegroup/drivers/mc.py:108 msgid "model server went away" msgstr "" -#: nova/servicegroup/drivers/mc.py:45 +#: nova/servicegroup/drivers/mc.py:44 msgid "memcached_servers not defined" msgstr "" -#: nova/servicegroup/drivers/mc.py:53 +#: nova/servicegroup/drivers/mc.py:52 #, python-format msgid "" "Memcached_Driver: join new ServiceGroup member %(member_id)s to the " "%(group_id)s group, service = %(service)s" msgstr "" -#: nova/servicegroup/drivers/mc.py:58 +#: nova/servicegroup/drivers/mc.py:57 msgid "service is a mandatory argument for Memcached based ServiceGroup driver" msgstr "" -#: nova/servicegroup/drivers/mc.py:78 +#: nova/servicegroup/drivers/mc.py:77 #, python-format msgid "Memcached_Driver: get_all members of the %s group" msgstr "" -#: nova/servicegroup/drivers/zk.py:79 +#: nova/servicegroup/drivers/zk.py:80 #, python-format msgid "" "ZooKeeperDriver: join new member %(id)s to the %(gr)s group, " "service=%(sr)s" msgstr "" -#: nova/servicegroup/drivers/zk.py:89 +#: nova/servicegroup/drivers/zk.py:90 msgid "" "Unable to join. It is possible that either another node exists with the " "same name, or this node just restarted. We will try again in a short " "while to make sure." msgstr "" -#: nova/servicegroup/drivers/zk.py:100 +#: nova/servicegroup/drivers/zk.py:101 #, python-format msgid "ZooKeeperDriver.leave: %(member)s from group %(group)s" msgstr "" -#: nova/servicegroup/drivers/zk.py:108 +#: nova/servicegroup/drivers/zk.py:109 #, python-format msgid "ZooKeeperDriver.leave: %(id)s has not joined to the %(gr)s group" msgstr "" @@ -6067,19 +6114,19 @@ msgstr "" msgid "already detached" msgstr "" -#: nova/tests/fakelibvirt.py:891 +#: nova/tests/fakelibvirt.py:892 msgid "Please extend mock libvirt module to support flags" msgstr "" -#: nova/tests/fakelibvirt.py:895 +#: nova/tests/fakelibvirt.py:896 msgid "Expected a list for 'auth' parameter" msgstr "" -#: nova/tests/fakelibvirt.py:899 +#: nova/tests/fakelibvirt.py:900 msgid "Expected a function in 'auth[0]' parameter" msgstr "" -#: nova/tests/fakelibvirt.py:903 +#: nova/tests/fakelibvirt.py:904 msgid "Expected a function in 'auth[1]' parameter" msgstr "" @@ -6152,17 +6199,17 @@ msgstr "" msgid "unexpected role header" msgstr "" -#: nova/tests/api/openstack/compute/test_servers.py:3218 +#: nova/tests/api/openstack/compute/test_servers.py:3212 msgid "" "Quota exceeded for instances: Requested 1, but already used 10 of 10 " "instances" msgstr "" -#: nova/tests/api/openstack/compute/test_servers.py:3223 +#: nova/tests/api/openstack/compute/test_servers.py:3217 msgid "Quota exceeded for ram: Requested 4096, but already used 8192 of 10240 ram" msgstr "" -#: nova/tests/api/openstack/compute/test_servers.py:3228 +#: nova/tests/api/openstack/compute/test_servers.py:3222 msgid "Quota exceeded for cores: Requested 2, but already used 9 of 10 cores" msgstr "" @@ -6170,7 +6217,8 @@ msgstr "" #: nova/tests/compute/test_compute.py:735 #: nova/tests/compute/test_compute.py:786 #: nova/tests/compute/test_compute.py:813 -#: nova/tests/compute/test_compute.py:2979 +#: nova/tests/compute/test_compute.py:859 +#: nova/tests/compute/test_compute.py:3002 #, python-format msgid "Running instances: %s" msgstr "" @@ -6183,52 +6231,54 @@ msgstr "" msgid "After terminating instances: %s" msgstr "" -#: nova/tests/compute/test_compute.py:1264 +#: nova/tests/compute/test_compute.py:1287 msgid "Internal error" msgstr "" -#: nova/tests/compute/test_compute.py:2990 +#: nova/tests/compute/test_compute.py:3013 #, python-format msgid "After force-killing instances: %s" msgstr "" -#: nova/tests/compute/test_compute.py:3488 +#: nova/tests/compute/test_compute.py:3503 msgid "wrong host/node" msgstr "" -#: nova/tests/integrated/test_api_samples.py:172 +#: nova/tests/integrated/test_api_samples.py:175 #, python-format msgid "Result: %(result)s is not a dict." msgstr "" -#: nova/tests/integrated/test_api_samples.py:176 +#: nova/tests/integrated/test_api_samples.py:187 #, python-format msgid "" -"Key mismatch:\n" -"%(ex_keys)s\n" -"%(res_keys)s" +"Dictionary key mismatch:\n" +"Extra key(s) in template:\n" +"%(ex_delta)s\n" +"Extra key(s) in response:\n" +"%(res_delta)s\n" msgstr "" -#: nova/tests/integrated/test_api_samples.py:184 +#: nova/tests/integrated/test_api_samples.py:197 #, python-format msgid "Result: %(result)s is not a list." msgstr "" -#: nova/tests/integrated/test_api_samples.py:202 -msgid "Extra items in expected:" +#: nova/tests/integrated/test_api_samples.py:215 +msgid "Extra list items in template:" msgstr "" -#: nova/tests/integrated/test_api_samples.py:206 -msgid "Extra items in result:" +#: nova/tests/integrated/test_api_samples.py:219 +msgid "Extra list items in response:" msgstr "" -#: nova/tests/integrated/test_api_samples.py:225 #: nova/tests/integrated/test_api_samples.py:238 +#: nova/tests/integrated/test_api_samples.py:252 #, python-format msgid "" "Values do not match:\n" -"%(expected)s\n" -"%(result)s" +"Template: %(expected)s\n" +"Response: %(result)s" msgstr "" #: nova/tests/integrated/test_login.py:31 @@ -6318,24 +6368,24 @@ msgstr "" msgid "Key '%(key)s' not in instances '%(inst)s'" msgstr "" -#: nova/virt/firewall.py:180 nova/virt/libvirt/firewall.py:305 +#: nova/virt/firewall.py:184 nova/virt/libvirt/firewall.py:305 msgid "Attempted to unfilter instance which is not filtered" msgstr "" -#: nova/virt/firewall.py:191 +#: nova/virt/firewall.py:195 msgid "Filters added to instance" msgstr "" -#: nova/virt/firewall.py:193 +#: nova/virt/firewall.py:197 msgid "Provider Firewall Rules refreshed" msgstr "" -#: nova/virt/firewall.py:361 +#: nova/virt/firewall.py:373 #, python-format msgid "Adding security group rule: %r" msgstr "" -#: nova/virt/firewall.py:494 nova/virt/xenapi/firewall.py:74 +#: nova/virt/firewall.py:506 nova/virt/xenapi/firewall.py:74 #, python-format msgid "Adding provider rule: %s" msgstr "" @@ -6477,32 +6527,32 @@ msgstr "" msgid "Injecting files into image for instance %(name)s" msgstr "" -#: nova/virt/baremetal/pxe.py:450 +#: nova/virt/baremetal/pxe.py:459 #, python-format msgid "Node associated with another instance while waiting for deploy of %s" msgstr "" -#: nova/virt/baremetal/pxe.py:457 +#: nova/virt/baremetal/pxe.py:466 #, python-format msgid "PXE deploy started for instance %s" msgstr "" -#: nova/virt/baremetal/pxe.py:462 +#: nova/virt/baremetal/pxe.py:471 #, python-format msgid "PXE deploy completed for instance %s" msgstr "" -#: nova/virt/baremetal/pxe.py:466 +#: nova/virt/baremetal/pxe.py:475 #, python-format msgid "PXE deploy failed for instance %s" msgstr "" -#: nova/virt/baremetal/pxe.py:468 +#: nova/virt/baremetal/pxe.py:477 #, python-format msgid "Baremetal node deleted while waiting for deployment of instance %s" msgstr "" -#: nova/virt/baremetal/pxe.py:473 +#: nova/virt/baremetal/pxe.py:482 #, python-format msgid "Timeout reached while waiting for PXE deploy of instance %s" msgstr "" @@ -6559,16 +6609,16 @@ msgstr "" msgid "no pif for vif_uuid=%s" msgstr "" -#: nova/virt/baremetal/virtual_power_driver.py:97 +#: nova/virt/baremetal/virtual_power_driver.py:104 msgid "virtual_power_ssh_host not defined. Can not Start" msgstr "" -#: nova/virt/baremetal/virtual_power_driver.py:101 +#: nova/virt/baremetal/virtual_power_driver.py:108 msgid "virtual_power_host_user not defined. Can not Start" msgstr "" -#: nova/virt/baremetal/virtual_power_driver.py:105 -msgid "virtual_power_host_pass not defined. Can not Start" +#: nova/virt/baremetal/virtual_power_driver.py:114 +msgid "virtual_power_host_pass/key not set. Can not Start" msgstr "" #: nova/virt/baremetal/volume_driver.py:121 @@ -6591,31 +6641,31 @@ msgstr "" msgid "detach volume could not find tid for %s" msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:201 +#: nova/virt/baremetal/db/sqlalchemy/api.py:202 msgid "instance_uuid must be supplied to bm_node_associate_and_update" msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:213 +#: nova/virt/baremetal/db/sqlalchemy/api.py:214 #, python-format msgid "Failed to associate instance %(i_uuid)s to baremetal node %(n_uuid)s." msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:331 +#: nova/virt/baremetal/db/sqlalchemy/api.py:332 msgid "No more PXE IPs available" msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:353 -#: nova/virt/baremetal/db/sqlalchemy/api.py:395 +#: nova/virt/baremetal/db/sqlalchemy/api.py:354 +#: nova/virt/baremetal/db/sqlalchemy/api.py:396 #, python-format msgid "Baremetal interface %s not found" msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:405 +#: nova/virt/baremetal/db/sqlalchemy/api.py:406 #, python-format msgid "Baremetal interface %s already in use" msgstr "" -#: nova/virt/baremetal/db/sqlalchemy/api.py:419 +#: nova/virt/baremetal/db/sqlalchemy/api.py:420 #, python-format msgid "Baremetal virtual interface %s not found" msgstr "" @@ -6877,111 +6927,111 @@ msgstr "" msgid "Falling back to VFSLocalFS" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:54 +#: nova/virt/disk/vfs/guestfs.py:55 #, python-format msgid "Mount guest OS image %(imgfile)s partition %(part)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:63 +#: nova/virt/disk/vfs/guestfs.py:64 #, python-format msgid "Inspecting guest OS image %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:67 +#: nova/virt/disk/vfs/guestfs.py:68 #, python-format msgid "No operating system found in %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:71 +#: nova/virt/disk/vfs/guestfs.py:72 #, python-format msgid "Multi-boot OS %(roots)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:73 +#: nova/virt/disk/vfs/guestfs.py:74 #, python-format msgid "Multi-boot operating system found in %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:79 +#: nova/virt/disk/vfs/guestfs.py:80 #, python-format msgid "Inspecting guest OS root filesystem %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:84 +#: nova/virt/disk/vfs/guestfs.py:85 #, python-format msgid "No mount points found in %(root)s of %(imgfile)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:89 +#: nova/virt/disk/vfs/guestfs.py:90 #, python-format msgid "Mounting %(dev)s at %(dir)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:94 +#: nova/virt/disk/vfs/guestfs.py:95 #, python-format msgid "Setting up appliance for %(imgfile)s %(imgfmt)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:112 +#: nova/virt/disk/vfs/guestfs.py:113 #, python-format msgid "Error mounting %(imgfile)s with libguestfs (%(e)s)" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:119 +#: nova/virt/disk/vfs/guestfs.py:120 msgid "Tearing down appliance" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:125 +#: nova/virt/disk/vfs/guestfs.py:126 #, python-format msgid "Failed to close augeas %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:133 +#: nova/virt/disk/vfs/guestfs.py:134 #, python-format msgid "Failed to shutdown appliance %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:141 +#: nova/virt/disk/vfs/guestfs.py:142 #, python-format msgid "Failed to close guest handle %s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:153 nova/virt/disk/vfs/localfs.py:102 +#: nova/virt/disk/vfs/guestfs.py:154 nova/virt/disk/vfs/localfs.py:102 #, python-format msgid "Make directory path=%(path)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:158 nova/virt/disk/vfs/localfs.py:107 +#: nova/virt/disk/vfs/guestfs.py:159 nova/virt/disk/vfs/localfs.py:107 #, python-format msgid "Append file path=%(path)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:163 nova/virt/disk/vfs/localfs.py:116 +#: nova/virt/disk/vfs/guestfs.py:164 nova/virt/disk/vfs/localfs.py:116 #, python-format msgid "Replace file path=%(path)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:168 nova/virt/disk/vfs/localfs.py:125 +#: nova/virt/disk/vfs/guestfs.py:169 nova/virt/disk/vfs/localfs.py:125 #, python-format msgid "Read file path=%(path)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:173 nova/virt/disk/vfs/localfs.py:131 +#: nova/virt/disk/vfs/guestfs.py:174 nova/virt/disk/vfs/localfs.py:131 #, python-format msgid "Has file path=%(path)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:182 +#: nova/virt/disk/vfs/guestfs.py:183 #, python-format msgid "Set permissions path=%(path)s mode=%(mode)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:187 +#: nova/virt/disk/vfs/guestfs.py:188 #, python-format msgid "Set ownership path=%(path)s user=%(user)s group=%(group)s" msgstr "" -#: nova/virt/disk/vfs/guestfs.py:200 +#: nova/virt/disk/vfs/guestfs.py:201 #, python-format msgid "chown uid=%(uid)d gid=%(gid)s" msgstr "" @@ -7020,23 +7070,23 @@ msgstr "" msgid "The ISCSI initiator name can't be found. Choosing the default one" msgstr "" -#: nova/virt/hyperv/driver.py:147 +#: nova/virt/hyperv/driver.py:150 msgid "plug_vifs called" msgstr "" -#: nova/virt/hyperv/driver.py:150 +#: nova/virt/hyperv/driver.py:153 msgid "unplug_vifs called" msgstr "" -#: nova/virt/hyperv/driver.py:153 +#: nova/virt/hyperv/driver.py:156 msgid "ensure_filtering_rules_for_instance called" msgstr "" -#: nova/virt/hyperv/driver.py:157 +#: nova/virt/hyperv/driver.py:160 msgid "unfilter_instance called" msgstr "" -#: nova/virt/hyperv/driver.py:188 +#: nova/virt/hyperv/driver.py:191 msgid "get_console_output called" msgstr "" @@ -7049,7 +7099,7 @@ msgstr "" msgid "get_available_resource called" msgstr "" -#: nova/virt/hyperv/hostops.py:135 nova/virt/libvirt/driver.py:3642 +#: nova/virt/hyperv/hostops.py:135 nova/virt/libvirt/driver.py:3663 #: nova/virt/xenapi/host.py:148 msgid "Updating host stats" msgstr "" @@ -7090,9 +7140,16 @@ msgstr "" msgid "post_live_migration_at_destination called" msgstr "" -#: nova/virt/hyperv/livemigrationops.py:80 -#, python-format -msgid "compare_cpu called %s" +#: nova/virt/hyperv/livemigrationops.py:83 +msgid "check_can_live_migrate_destination called" +msgstr "" + +#: nova/virt/hyperv/livemigrationops.py:88 +msgid "check_can_live_migrate_destination_cleanup called" +msgstr "" + +#: nova/virt/hyperv/livemigrationops.py:92 +msgid "check_can_live_migrate_source called" msgstr "" #: nova/virt/hyperv/livemigrationutils.py:40 @@ -7337,12 +7394,12 @@ msgstr "" msgid "Using config drive for instance: %s" msgstr "" -#: nova/virt/hyperv/vmops.py:203 nova/virt/libvirt/driver.py:1848 +#: nova/virt/hyperv/vmops.py:203 nova/virt/libvirt/driver.py:1847 #, python-format msgid "Creating config drive at %(path)s" msgstr "" -#: nova/virt/hyperv/vmops.py:211 nova/virt/libvirt/driver.py:1854 +#: nova/virt/hyperv/vmops.py:211 nova/virt/libvirt/driver.py:1853 #, python-format msgid "Creating config drive failed with error: %s" msgstr "" @@ -7481,7 +7538,7 @@ msgstr "" msgid "Detaching physical disk from instance: %s" msgstr "" -#: nova/virt/hyperv/volumeops.py:157 nova/virt/libvirt/driver.py:893 +#: nova/virt/hyperv/volumeops.py:157 nova/virt/libvirt/driver.py:892 msgid "Could not determine iscsi initiator name" msgstr "" @@ -7515,235 +7572,235 @@ msgstr "" msgid "Unable to determine disk bus for '%s'" msgstr "" -#: nova/virt/libvirt/driver.py:339 +#: nova/virt/libvirt/driver.py:338 #, python-format msgid "Invalid cachemode %(cache_mode)s specified for disk type %(disk_type)s." msgstr "" -#: nova/virt/libvirt/driver.py:545 +#: nova/virt/libvirt/driver.py:544 #, python-format msgid "Nova requires libvirt version %(major)i.%(minor)i.%(micro)i or greater." msgstr "" -#: nova/virt/libvirt/driver.py:553 +#: nova/virt/libvirt/driver.py:552 #, python-format msgid "Connecting to libvirt: %s" msgstr "" -#: nova/virt/libvirt/driver.py:570 +#: nova/virt/libvirt/driver.py:569 #, python-format msgid "URI %s does not support events" msgstr "" -#: nova/virt/libvirt/driver.py:585 +#: nova/virt/libvirt/driver.py:584 msgid "Connection to libvirt broke" msgstr "" -#: nova/virt/libvirt/driver.py:607 nova/virt/libvirt/driver.py:610 +#: nova/virt/libvirt/driver.py:606 nova/virt/libvirt/driver.py:609 #, python-format msgid "Can not handle authentication request for %d credentials" msgstr "" -#: nova/virt/libvirt/driver.py:628 +#: nova/virt/libvirt/driver.py:627 #, python-format msgid "Connection to libvirt failed: %s" msgstr "" -#: nova/virt/libvirt/driver.py:718 +#: nova/virt/libvirt/driver.py:717 #, python-format msgid "Error from libvirt during destroy. Code=%(errcode)s Error=%(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:734 +#: nova/virt/libvirt/driver.py:733 msgid "During wait destroy, instance disappeared." msgstr "" -#: nova/virt/libvirt/driver.py:739 +#: nova/virt/libvirt/driver.py:738 msgid "Instance destroyed successfully." msgstr "" -#: nova/virt/libvirt/driver.py:749 +#: nova/virt/libvirt/driver.py:748 msgid "Instance may be started again." msgstr "" -#: nova/virt/libvirt/driver.py:758 +#: nova/virt/libvirt/driver.py:757 msgid "Going to destroy instance again." msgstr "" -#: nova/virt/libvirt/driver.py:777 +#: nova/virt/libvirt/driver.py:776 msgid "Error from libvirt during undefineFlags. Retrying with undefine" msgstr "" -#: nova/virt/libvirt/driver.py:792 +#: nova/virt/libvirt/driver.py:791 #, python-format msgid "Error from libvirt during undefine. Code=%(errcode)s Error=%(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:813 +#: nova/virt/libvirt/driver.py:812 msgid "Instance may be still running, destroy it again." msgstr "" -#: nova/virt/libvirt/driver.py:819 +#: nova/virt/libvirt/driver.py:818 #, python-format msgid "Error from libvirt during unfilter. Code=%(errcode)s Error=%(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:847 +#: nova/virt/libvirt/driver.py:846 #, python-format msgid "Deleting instance files %(target)s" msgstr "" -#: nova/virt/libvirt/driver.py:856 +#: nova/virt/libvirt/driver.py:855 #, python-format msgid "Failed to cleanup directory %(target)s: %(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:899 +#: nova/virt/libvirt/driver.py:898 msgid "Could not determine fibre channel world wide node names" msgstr "" -#: nova/virt/libvirt/driver.py:906 +#: nova/virt/libvirt/driver.py:905 msgid "Could not determine fibre channel world wide port names" msgstr "" -#: nova/virt/libvirt/driver.py:911 +#: nova/virt/libvirt/driver.py:910 msgid "No Volume Connector found." msgstr "" -#: nova/virt/libvirt/driver.py:1033 +#: nova/virt/libvirt/driver.py:1032 msgid "During detach_volume, instance disappeared." msgstr "" -#: nova/virt/libvirt/driver.py:1057 +#: nova/virt/libvirt/driver.py:1056 msgid "attaching network adapter failed." msgstr "" -#: nova/virt/libvirt/driver.py:1077 +#: nova/virt/libvirt/driver.py:1076 msgid "During detach_interface, instance disappeared." msgstr "" -#: nova/virt/libvirt/driver.py:1081 +#: nova/virt/libvirt/driver.py:1080 msgid "detaching network adapter failed." msgstr "" -#: nova/virt/libvirt/driver.py:1170 +#: nova/virt/libvirt/driver.py:1169 msgid "Beginning live snapshot process" msgstr "" -#: nova/virt/libvirt/driver.py:1173 +#: nova/virt/libvirt/driver.py:1172 msgid "Beginning cold snapshot process" msgstr "" -#: nova/virt/libvirt/driver.py:1202 +#: nova/virt/libvirt/driver.py:1201 msgid "Snapshot extracted, beginning image upload" msgstr "" -#: nova/virt/libvirt/driver.py:1214 +#: nova/virt/libvirt/driver.py:1213 msgid "Snapshot image upload complete" msgstr "" -#: nova/virt/libvirt/driver.py:1287 +#: nova/virt/libvirt/driver.py:1286 msgid "Instance soft rebooted successfully." msgstr "" -#: nova/virt/libvirt/driver.py:1291 +#: nova/virt/libvirt/driver.py:1290 msgid "Failed to soft reboot instance." msgstr "" -#: nova/virt/libvirt/driver.py:1326 +#: nova/virt/libvirt/driver.py:1325 msgid "Instance shutdown successfully." msgstr "" -#: nova/virt/libvirt/driver.py:1334 +#: nova/virt/libvirt/driver.py:1333 msgid "Instance may have been rebooted during soft reboot, so return now." msgstr "" -#: nova/virt/libvirt/driver.py:1376 +#: nova/virt/libvirt/driver.py:1375 msgid "Instance rebooted successfully." msgstr "" -#: nova/virt/libvirt/driver.py:1519 +#: nova/virt/libvirt/driver.py:1518 msgid "Instance is running" msgstr "" -#: nova/virt/libvirt/driver.py:1526 nova/virt/powervm/operator.py:219 +#: nova/virt/libvirt/driver.py:1525 nova/virt/powervm/operator.py:219 msgid "Instance spawned successfully." msgstr "" -#: nova/virt/libvirt/driver.py:1542 +#: nova/virt/libvirt/driver.py:1541 #, python-format msgid "data: %(data)r, fpath: %(fpath)r" msgstr "" -#: nova/virt/libvirt/driver.py:1579 nova/virt/libvirt/driver.py:1605 +#: nova/virt/libvirt/driver.py:1578 nova/virt/libvirt/driver.py:1604 #, python-format msgid "Truncated console log returned, %d bytes ignored" msgstr "" -#: nova/virt/libvirt/driver.py:1594 +#: nova/virt/libvirt/driver.py:1593 msgid "Guest does not have a console available" msgstr "" -#: nova/virt/libvirt/driver.py:1663 +#: nova/virt/libvirt/driver.py:1662 #, python-format msgid "Path '%(path)s' supports direct I/O" msgstr "" -#: nova/virt/libvirt/driver.py:1667 +#: nova/virt/libvirt/driver.py:1666 #, python-format msgid "Path '%(path)s' does not support direct I/O: '%(ex)s'" msgstr "" -#: nova/virt/libvirt/driver.py:1671 nova/virt/libvirt/driver.py:1675 +#: nova/virt/libvirt/driver.py:1670 nova/virt/libvirt/driver.py:1674 #, python-format msgid "Error on '%(path)s' while checking direct I/O: '%(ex)s'" msgstr "" -#: nova/virt/libvirt/driver.py:1741 +#: nova/virt/libvirt/driver.py:1740 msgid "Creating image" msgstr "" -#: nova/virt/libvirt/driver.py:1839 +#: nova/virt/libvirt/driver.py:1838 msgid "Using config drive" msgstr "" -#: nova/virt/libvirt/driver.py:1887 +#: nova/virt/libvirt/driver.py:1886 #, python-format msgid "Injecting %(inj)s into image %(img_id)s" msgstr "" -#: nova/virt/libvirt/driver.py:1896 +#: nova/virt/libvirt/driver.py:1895 #, python-format msgid "Error injecting data into image %(img_id)s (%(e)s)" msgstr "" -#: nova/virt/libvirt/driver.py:1954 +#: nova/virt/libvirt/driver.py:1953 #, python-format msgid "" "Config requested an explicit CPU model, but the current libvirt " "hypervisor '%s' does not support selecting CPU models" msgstr "" -#: nova/virt/libvirt/driver.py:1960 +#: nova/virt/libvirt/driver.py:1959 msgid "Config requested a custom CPU model, but no model name was provided" msgstr "" -#: nova/virt/libvirt/driver.py:1964 +#: nova/virt/libvirt/driver.py:1963 msgid "A CPU model name should not be set when a host CPU model is requested" msgstr "" -#: nova/virt/libvirt/driver.py:1968 +#: nova/virt/libvirt/driver.py:1967 #, python-format msgid "CPU mode '%(mode)s' model '%(model)s' was chosen" msgstr "" -#: nova/virt/libvirt/driver.py:1984 +#: nova/virt/libvirt/driver.py:1983 msgid "" "Passthrough of the host CPU was requested but this libvirt version does " "not support this feature" msgstr "" -#: nova/virt/libvirt/driver.py:2294 +#: nova/virt/libvirt/driver.py:2302 #, python-format msgid "" "Start to_xml instance=%(instance)s network_info=%(network_info)s " @@ -7751,80 +7808,80 @@ msgid "" "rescue=%(rescue)sblock_device_info=%(block_device_info)s" msgstr "" -#: nova/virt/libvirt/driver.py:2309 +#: nova/virt/libvirt/driver.py:2317 #, python-format msgid "End to_xml instance=%(instance)s xml=%(xml)s" msgstr "" -#: nova/virt/libvirt/driver.py:2326 +#: nova/virt/libvirt/driver.py:2334 #, python-format msgid "" "Error from libvirt while looking up %(instance_name)s: [Error Code " "%(error_code)s] %(ex)s" msgstr "" -#: nova/virt/libvirt/driver.py:2494 +#: nova/virt/libvirt/driver.py:2502 msgid "" "Cannot get the number of cpu, because this function is not implemented " "for this platform. " msgstr "" -#: nova/virt/libvirt/driver.py:2547 +#: nova/virt/libvirt/driver.py:2555 #, python-format msgid "List of domains returned by libVirt: %s" msgstr "" -#: nova/virt/libvirt/driver.py:2549 +#: nova/virt/libvirt/driver.py:2557 #, python-format msgid "libVirt can't find a domain with id: %s" msgstr "" -#: nova/virt/libvirt/driver.py:2613 +#: nova/virt/libvirt/driver.py:2621 msgid "libvirt version is too old (does not support getVersion)" msgstr "" -#: nova/virt/libvirt/driver.py:2696 +#: nova/virt/libvirt/driver.py:2704 #, python-format msgid "Trying to get stats for the volume %s" msgstr "" -#: nova/virt/libvirt/driver.py:2720 +#: nova/virt/libvirt/driver.py:2728 #, python-format msgid "" "Getting block stats failed, device might have been detached. " "Code=%(errcode)s Error=%(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:2724 +#: nova/virt/libvirt/driver.py:2732 #, python-format msgid "" "Could not find domain in libvirt for instance %s. Cannot get block stats " "for device" msgstr "" -#: nova/virt/libvirt/driver.py:2858 +#: nova/virt/libvirt/driver.py:2866 msgid "Block migration can not be used with shared storage." msgstr "" -#: nova/virt/libvirt/driver.py:2866 +#: nova/virt/libvirt/driver.py:2874 msgid "Live migration can not be used without shared storage." msgstr "" -#: nova/virt/libvirt/driver.py:2903 +#: nova/virt/libvirt/driver.py:2911 #, python-format msgid "" "Unable to migrate %(instance_uuid)s: Disk of instance is too " "large(available on destination host:%(available)s < need:%(necessary)s)" msgstr "" -#: nova/virt/libvirt/driver.py:2928 +#: nova/virt/libvirt/driver.py:2936 #, python-format msgid "" "Instance launched has CPU info:\n" "%s" msgstr "" -#: nova/virt/libvirt/driver.py:2940 +#: nova/virt/libvirt/driver.py:2948 #, python-format msgid "" "CPU doesn't have compatibility.\n" @@ -7834,62 +7891,62 @@ msgid "" "Refer to %(u)s" msgstr "" -#: nova/virt/libvirt/driver.py:2957 +#: nova/virt/libvirt/driver.py:2965 #, python-format msgid "" "Creating tmpfile %s to notify to other compute nodes that they should " "mount the same storage." msgstr "" -#: nova/virt/libvirt/driver.py:3005 +#: nova/virt/libvirt/driver.py:3013 #, python-format msgid "The firewall filter for %s does not exist" msgstr "" -#: nova/virt/libvirt/driver.py:3077 +#: nova/virt/libvirt/driver.py:3085 #, python-format msgid "Live Migration failure: %(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:3170 +#: nova/virt/libvirt/driver.py:3178 #, python-format msgid "plug_vifs() failed %(cnt)d.Retry up to %(max_retry)d for %(hostname)s." msgstr "" -#: nova/virt/libvirt/driver.py:3280 +#: nova/virt/libvirt/driver.py:3288 #, python-format msgid "" "Error from libvirt while getting description of %(instance_name)s: [Error" " Code %(error_code)s] %(ex)s" msgstr "" -#: nova/virt/libvirt/driver.py:3297 +#: nova/virt/libvirt/driver.py:3305 #, python-format msgid "skipping %(path)s since it looks like volume" msgstr "" -#: nova/virt/libvirt/driver.py:3335 +#: nova/virt/libvirt/driver.py:3343 #, python-format msgid "Getting disk size of %(i_name)s: %(e)s" msgstr "" -#: nova/virt/libvirt/driver.py:3381 +#: nova/virt/libvirt/driver.py:3389 msgid "Starting migrate_disk_and_power_off" msgstr "" -#: nova/virt/libvirt/driver.py:3440 +#: nova/virt/libvirt/driver.py:3448 msgid "Instance running successfully." msgstr "" -#: nova/virt/libvirt/driver.py:3446 +#: nova/virt/libvirt/driver.py:3454 msgid "Starting finish_migration" msgstr "" -#: nova/virt/libvirt/driver.py:3502 +#: nova/virt/libvirt/driver.py:3515 msgid "Starting finish_revert_migration" msgstr "" -#: nova/virt/libvirt/driver.py:3615 +#: nova/virt/libvirt/driver.py:3636 #, python-format msgid "Checking instance files accessability%(instance_path)s" msgstr "" @@ -7931,144 +7988,144 @@ msgstr "" msgid "Unknown image_type=%s" msgstr "" -#: nova/virt/libvirt/imagecache.py:111 +#: nova/virt/libvirt/imagecache.py:140 #, python-format msgid "Error reading image info file %(filename)s: %(error)s" msgstr "" -#: nova/virt/libvirt/imagecache.py:151 +#: nova/virt/libvirt/imagecache.py:180 #, python-format msgid "Reading image info file: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:173 +#: nova/virt/libvirt/imagecache.py:202 #, python-format msgid "Writing stored info to %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:299 +#: nova/virt/libvirt/imagecache.py:332 #, python-format msgid "%s is a valid instance name" msgstr "" -#: nova/virt/libvirt/imagecache.py:302 +#: nova/virt/libvirt/imagecache.py:335 #, python-format msgid "%s has a disk file" msgstr "" -#: nova/virt/libvirt/imagecache.py:304 +#: nova/virt/libvirt/imagecache.py:337 #, python-format msgid "Instance %(instance)s is backed by %(backing)s" msgstr "" -#: nova/virt/libvirt/imagecache.py:317 +#: nova/virt/libvirt/imagecache.py:350 #, python-format msgid "" "Instance %(instance)s is using a backing file %(backing)s which does not " "appear in the image service" msgstr "" -#: nova/virt/libvirt/imagecache.py:393 +#: nova/virt/libvirt/imagecache.py:426 #, python-format msgid "image %(id)s at (%(base_file)s): image verification failed" msgstr "" -#: nova/virt/libvirt/imagecache.py:403 +#: nova/virt/libvirt/imagecache.py:436 #, python-format msgid "" "image %(id)s at (%(base_file)s): image verification skipped, no hash " "stored" msgstr "" -#: nova/virt/libvirt/imagecache.py:412 +#: nova/virt/libvirt/imagecache.py:445 #, python-format msgid "%(id)s (%(base_file)s): generating checksum" msgstr "" -#: nova/virt/libvirt/imagecache.py:427 +#: nova/virt/libvirt/imagecache.py:460 #, python-format msgid "Cannot remove %(base_file)s, it does not exist" msgstr "" -#: nova/virt/libvirt/imagecache.py:439 +#: nova/virt/libvirt/imagecache.py:472 #, python-format msgid "Base file too young to remove: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:442 +#: nova/virt/libvirt/imagecache.py:475 #, python-format msgid "Removing base file: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:449 +#: nova/virt/libvirt/imagecache.py:482 #, python-format msgid "Failed to remove %(base_file)s, error was %(error)s" msgstr "" -#: nova/virt/libvirt/imagecache.py:460 +#: nova/virt/libvirt/imagecache.py:493 #, python-format msgid "image %(id)s at (%(base_file)s): checking" msgstr "" -#: nova/virt/libvirt/imagecache.py:484 +#: nova/virt/libvirt/imagecache.py:517 #, python-format msgid "" "image %(id)s at (%(base_file)s): in use: on this node %(local)d local, " "%(remote)d on other nodes sharing this instance storage" msgstr "" -#: nova/virt/libvirt/imagecache.py:496 +#: nova/virt/libvirt/imagecache.py:529 #, python-format msgid "" "image %(id)s at (%(base_file)s): warning -- an absent base file is in " "use! instances: %(instance_list)s" msgstr "" -#: nova/virt/libvirt/imagecache.py:508 +#: nova/virt/libvirt/imagecache.py:541 #, python-format msgid "image %(id)s at (%(base_file)s): image is not in use" msgstr "" -#: nova/virt/libvirt/imagecache.py:515 +#: nova/virt/libvirt/imagecache.py:548 #, python-format msgid "image %(id)s at (%(base_file)s): image is in use" msgstr "" -#: nova/virt/libvirt/imagecache.py:539 +#: nova/virt/libvirt/imagecache.py:572 #, python-format msgid "Skipping verification, no base directory at %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:543 +#: nova/virt/libvirt/imagecache.py:576 msgid "Verify base images" msgstr "" -#: nova/virt/libvirt/imagecache.py:550 +#: nova/virt/libvirt/imagecache.py:583 #, python-format msgid "Image id %(id)s yields fingerprint %(fingerprint)s" msgstr "" -#: nova/virt/libvirt/imagecache.py:568 +#: nova/virt/libvirt/imagecache.py:601 #, python-format msgid "Unknown base file: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:573 +#: nova/virt/libvirt/imagecache.py:606 #, python-format msgid "Active base files: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:576 +#: nova/virt/libvirt/imagecache.py:609 #, python-format msgid "Corrupt base files: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:580 +#: nova/virt/libvirt/imagecache.py:613 #, python-format msgid "Removable base files: %s" msgstr "" -#: nova/virt/libvirt/imagecache.py:588 +#: nova/virt/libvirt/imagecache.py:621 msgid "Verification complete" msgstr "" @@ -8109,36 +8166,36 @@ msgstr "" msgid "Can't retrieve root device path from instance libvirt configuration" msgstr "" -#: nova/virt/libvirt/vif.py:263 nova/virt/libvirt/vif.py:382 -#: nova/virt/libvirt/vif.py:469 +#: nova/virt/libvirt/vif.py:264 nova/virt/libvirt/vif.py:383 +#: nova/virt/libvirt/vif.py:470 #, python-format msgid "" "vif_type=%(vif_type)s instance=%(instance)s network=%(network)s " "mapping=%(mapping)s" msgstr "" -#: nova/virt/libvirt/vif.py:269 nova/virt/libvirt/vif.py:388 -#: nova/virt/libvirt/vif.py:475 +#: nova/virt/libvirt/vif.py:270 nova/virt/libvirt/vif.py:389 +#: nova/virt/libvirt/vif.py:476 msgid "vif_type parameter must be present for this vif_driver implementation" msgstr "" -#: nova/virt/libvirt/vif.py:290 nova/virt/libvirt/vif.py:401 -#: nova/virt/libvirt/vif.py:488 +#: nova/virt/libvirt/vif.py:291 nova/virt/libvirt/vif.py:402 +#: nova/virt/libvirt/vif.py:489 #, python-format msgid "Unexpected vif_type=%s" msgstr "" -#: nova/virt/libvirt/vif.py:302 +#: nova/virt/libvirt/vif.py:303 #, python-format msgid "Ensuring vlan %(vlan)s and bridge %(bridge)s" msgstr "" -#: nova/virt/libvirt/vif.py:312 +#: nova/virt/libvirt/vif.py:313 #, python-format msgid "Ensuring bridge %s" msgstr "" -#: nova/virt/libvirt/vif.py:418 nova/virt/libvirt/vif.py:447 +#: nova/virt/libvirt/vif.py:419 nova/virt/libvirt/vif.py:448 msgid "Failed while unplugging vif" msgstr "" @@ -8302,48 +8359,48 @@ msgstr "" msgid "Uncompressed image file not found" msgstr "" -#: nova/virt/powervm/common.py:57 +#: nova/virt/powervm/common.py:59 msgid "Connection error connecting PowerVM manager" msgstr "" -#: nova/virt/powervm/common.py:69 +#: nova/virt/powervm/common.py:71 #, python-format msgid "Running cmd (SSH-as-root): %s" msgstr "" -#: nova/virt/powervm/common.py:115 +#: nova/virt/powervm/common.py:117 msgid "File transfer to PowerVM manager failed" msgstr "" -#: nova/virt/powervm/common.py:134 +#: nova/virt/powervm/common.py:136 #, python-format msgid "ftp GET %(remote_path)s to: %(local_path)s" msgstr "" -#: nova/virt/powervm/common.py:140 +#: nova/virt/powervm/common.py:142 msgid "File transfer from PowerVM manager failed" msgstr "" -#: nova/virt/powervm/driver.py:118 +#: nova/virt/powervm/driver.py:120 msgid "In get_host_ip_addr" msgstr "" -#: nova/virt/powervm/driver.py:121 +#: nova/virt/powervm/driver.py:123 #, python-format msgid "Attempting to resolve %s" msgstr "" -#: nova/virt/powervm/driver.py:123 +#: nova/virt/powervm/driver.py:125 #, python-format msgid "%(hostname)s was successfully resolved to %(ip_addr)s" msgstr "" -#: nova/virt/powervm/driver.py:166 +#: nova/virt/powervm/driver.py:168 #, python-format msgid "%(inst_name)s captured in %(snapshot_time)s seconds" msgstr "" -#: nova/virt/powervm/driver.py:286 +#: nova/virt/powervm/driver.py:288 #, python-format msgid "Unrecognized root disk information: %s" msgstr "" @@ -8938,7 +8995,7 @@ msgstr "" msgid "Migrated VM to host %s" msgstr "" -#: nova/virt/vmwareapi/vmops.py:1050 nova/virt/xenapi/vmops.py:1263 +#: nova/virt/vmwareapi/vmops.py:1050 nova/virt/xenapi/vmops.py:1273 #, python-format msgid "Found %(instance_count)d hung reboots older than %(timeout)d seconds" msgstr "" @@ -9096,19 +9153,19 @@ msgstr "" msgid "Mountpoint %(mountpoint)s detached from instance %(instance_name)s" msgstr "" -#: nova/virt/xenapi/agent.py:88 nova/virt/xenapi/vmops.py:1506 +#: nova/virt/xenapi/agent.py:88 nova/virt/xenapi/vmops.py:1516 #, 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:1510 +#: nova/virt/xenapi/agent.py:92 nova/virt/xenapi/vmops.py:1520 #, 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:1515 +#: nova/virt/xenapi/agent.py:97 nova/virt/xenapi/vmops.py:1525 #, python-format msgid "The call to %(method)s returned an error: %(e)s. args=%(args)r" msgstr "" @@ -9790,7 +9847,7 @@ msgstr "" msgid "This domU must be running on the host specified by xenapi_connection_url" msgstr "" -#: nova/virt/xenapi/vmops.py:133 nova/virt/xenapi/vmops.py:740 +#: nova/virt/xenapi/vmops.py:133 nova/virt/xenapi/vmops.py:750 #, python-format msgid "Updating progress to %(progress)d" msgstr "" @@ -9804,187 +9861,187 @@ msgstr "" msgid "Error: Agent is disabled" msgstr "" -#: nova/virt/xenapi/vmops.py:267 +#: nova/virt/xenapi/vmops.py:277 msgid "Starting instance" msgstr "" -#: nova/virt/xenapi/vmops.py:336 +#: nova/virt/xenapi/vmops.py:346 msgid "Removing kernel/ramdisk files from dom0" msgstr "" -#: nova/virt/xenapi/vmops.py:409 +#: nova/virt/xenapi/vmops.py:419 #, python-format msgid "Block device information present: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:440 +#: nova/virt/xenapi/vmops.py:450 msgid "Failed to spawn, rolling back" msgstr "" -#: nova/virt/xenapi/vmops.py:519 +#: nova/virt/xenapi/vmops.py:529 msgid "Detected ISO image type, creating blank VM for install" msgstr "" -#: nova/virt/xenapi/vmops.py:536 +#: nova/virt/xenapi/vmops.py:546 msgid "Auto configuring disk, attempting to resize partition..." msgstr "" -#: nova/virt/xenapi/vmops.py:582 +#: nova/virt/xenapi/vmops.py:592 msgid "Starting VM" msgstr "" -#: nova/virt/xenapi/vmops.py:588 +#: nova/virt/xenapi/vmops.py:598 msgid "Waiting for instance state to become running" msgstr "" -#: nova/virt/xenapi/vmops.py:602 +#: nova/virt/xenapi/vmops.py:612 #, python-format msgid "" "Latest agent build for %(hypervisor)s/%(os)s/%(architecture)s is " "%(version)s" msgstr "" -#: nova/virt/xenapi/vmops.py:605 +#: nova/virt/xenapi/vmops.py:615 #, python-format msgid "No agent build found for %(hypervisor)s/%(os)s/%(architecture)s" msgstr "" -#: nova/virt/xenapi/vmops.py:616 +#: nova/virt/xenapi/vmops.py:626 #, python-format msgid "Instance agent version: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:643 +#: nova/virt/xenapi/vmops.py:653 msgid "Setting VCPU weight" msgstr "" -#: nova/virt/xenapi/vmops.py:651 +#: nova/virt/xenapi/vmops.py:661 #, python-format msgid "Could not find VM with name %s" msgstr "" -#: nova/virt/xenapi/vmops.py:709 +#: nova/virt/xenapi/vmops.py:719 msgid "Finished snapshot and upload for VM" msgstr "" -#: nova/virt/xenapi/vmops.py:713 +#: nova/virt/xenapi/vmops.py:723 #, python-format msgid "Migrating VHD '%(vdi_uuid)s' with seq_num %(seq_num)d" msgstr "" -#: nova/virt/xenapi/vmops.py:721 +#: nova/virt/xenapi/vmops.py:731 msgid "Failed to transfer vhd to new host" msgstr "" -#: nova/virt/xenapi/vmops.py:758 +#: nova/virt/xenapi/vmops.py:768 #, python-format msgid "Resizing down VDI %(vdi_uuid)s from %(old_gb)dGB to %(new_gb)dGB" msgstr "" -#: nova/virt/xenapi/vmops.py:764 nova/virt/xenapi/vmops.py:814 +#: nova/virt/xenapi/vmops.py:774 nova/virt/xenapi/vmops.py:824 msgid "Clean shutdown did not complete successfully, trying hard shutdown." msgstr "" -#: nova/virt/xenapi/vmops.py:843 +#: nova/virt/xenapi/vmops.py:853 msgid "Resize down not allowed without auto_disk_config" msgstr "" -#: nova/virt/xenapi/vmops.py:888 +#: nova/virt/xenapi/vmops.py:898 #, python-format msgid "Resizing up VDI %(vdi_uuid)s from %(old_gb)dGB to %(new_gb)dGB" msgstr "" -#: nova/virt/xenapi/vmops.py:893 +#: nova/virt/xenapi/vmops.py:903 msgid "Resize complete" msgstr "" -#: nova/virt/xenapi/vmops.py:937 +#: nova/virt/xenapi/vmops.py:947 msgid "Starting halted instance found during reboot" msgstr "" -#: nova/virt/xenapi/vmops.py:1028 +#: nova/virt/xenapi/vmops.py:1038 msgid "Unable to find root VBD/VDI for VM" msgstr "" -#: nova/virt/xenapi/vmops.py:1032 +#: nova/virt/xenapi/vmops.py:1042 msgid "Destroying VDIs" msgstr "" -#: nova/virt/xenapi/vmops.py:1059 +#: nova/virt/xenapi/vmops.py:1069 msgid "Using RAW or VHD, skipping kernel and ramdisk deletion" msgstr "" -#: nova/virt/xenapi/vmops.py:1066 +#: nova/virt/xenapi/vmops.py:1076 msgid "instance has a kernel or ramdisk but not both" msgstr "" -#: nova/virt/xenapi/vmops.py:1073 +#: nova/virt/xenapi/vmops.py:1083 msgid "kernel/ramdisk files removed" msgstr "" -#: nova/virt/xenapi/vmops.py:1100 +#: nova/virt/xenapi/vmops.py:1110 msgid "Destroying VM" msgstr "" -#: nova/virt/xenapi/vmops.py:1129 +#: nova/virt/xenapi/vmops.py:1139 msgid "VM is not present, skipping destroy..." msgstr "" -#: nova/virt/xenapi/vmops.py:1180 +#: nova/virt/xenapi/vmops.py:1190 #, python-format msgid "Instance is already in Rescue Mode: %s" msgstr "" -#: nova/virt/xenapi/vmops.py:1214 +#: nova/virt/xenapi/vmops.py:1224 msgid "VM is not present, skipping soft delete..." msgstr "" -#: nova/virt/xenapi/vmops.py:1267 +#: nova/virt/xenapi/vmops.py:1277 msgid "Automatically hard rebooting" msgstr "" -#: nova/virt/xenapi/vmops.py:1327 +#: nova/virt/xenapi/vmops.py:1337 msgid "Fetching VM ref while BUILDING failed" msgstr "" -#: nova/virt/xenapi/vmops.py:1410 +#: nova/virt/xenapi/vmops.py:1420 msgid "Injecting network info to xenstore" msgstr "" -#: nova/virt/xenapi/vmops.py:1429 +#: nova/virt/xenapi/vmops.py:1439 msgid "Creating vifs" msgstr "" -#: nova/virt/xenapi/vmops.py:1438 +#: nova/virt/xenapi/vmops.py:1448 #, python-format msgid "Creating VIF for network %(network_ref)s" msgstr "" -#: nova/virt/xenapi/vmops.py:1441 +#: nova/virt/xenapi/vmops.py:1451 #, python-format msgid "Created VIF %(vif_ref)s, network %(network_ref)s" msgstr "" -#: nova/virt/xenapi/vmops.py:1469 +#: nova/virt/xenapi/vmops.py:1479 msgid "Injecting hostname to xenstore" msgstr "" -#: nova/virt/xenapi/vmops.py:1565 +#: nova/virt/xenapi/vmops.py:1575 #, python-format msgid "" "Destination host:%(hostname)s must be in the same aggregate as the source" " server" msgstr "" -#: nova/virt/xenapi/vmops.py:1597 +#: nova/virt/xenapi/vmops.py:1607 msgid "Migrate Receive failed" msgstr "" -#: nova/virt/xenapi/vmops.py:1646 +#: nova/virt/xenapi/vmops.py:1656 msgid "VM.assert_can_migratefailed" msgstr "" -#: nova/virt/xenapi/vmops.py:1682 +#: nova/virt/xenapi/vmops.py:1692 msgid "Migrate Send failed" msgstr "" @@ -10059,9 +10116,17 @@ msgstr "" msgid "Skipping detach because VBD for %(instance_name)s was not found" msgstr "" -#: nova/virt/xenapi/imageupload/glance.py:35 +#: nova/virt/xenapi/imageupload/glance.py:64 +#, python-format +msgid "" +"Asking xapi to upload to glance %(vdi_uuids)s as ID %(image_id)s glance " +"server: %(glance_host)s:%(glance_port)d attempt " +"%(attempt_num)d/%(max_attempts)d" +msgstr "" + +#: nova/virt/xenapi/imageupload/glance.py:77 #, python-format -msgid "Asking xapi to upload to glance %(vdi_uuids)s as ID %(image_id)s" +msgid "upload_vhd failed: %r" msgstr "" #: nova/vnc/xvp_proxy.py:95 nova/vnc/xvp_proxy.py:100 diff --git a/nova/network/api_deprecated.py b/nova/network/api_deprecated.py index b84a08a6d..1f23d90f7 100644 --- a/nova/network/api_deprecated.py +++ b/nova/network/api_deprecated.py @@ -22,82 +22,20 @@ This version of the api is deprecated in Grizzly and will be removed. It is provided just in case a third party manager is in use. """ -import functools -import inspect - from nova.db import base from nova import exception +from nova.network import api as shiny_api from nova.network import model as network_model from nova.network import rpcapi as network_rpcapi from nova.openstack.common import log as logging -from nova import policy LOG = logging.getLogger(__name__) -def refresh_cache(f): - """ - Decorator to update the instance_info_cache - - Requires context and instance as function args - """ - argspec = inspect.getargspec(f) - - @functools.wraps(f) - def wrapper(self, context, *args, **kwargs): - res = f(self, context, *args, **kwargs) - - try: - # get the instance from arguments (or raise ValueError) - instance = kwargs.get('instance') - if not instance: - instance = args[argspec.args.index('instance') - 2] - except ValueError: - msg = _('instance is a required argument to use @refresh_cache') - raise Exception(msg) - - update_instance_cache_with_nw_info(self, context, instance, - nw_info=res) - - # return the original function's return value - return res - return wrapper - - -def update_instance_cache_with_nw_info(api, context, instance, - nw_info=None): - - try: - if not isinstance(nw_info, network_model.NetworkInfo): - nw_info = None - if not nw_info: - nw_info = api._get_instance_nw_info(context, instance) - # update cache - cache = {'network_info': nw_info.json()} - api.db.instance_info_cache_update(context, instance['uuid'], cache) - except Exception: - LOG.exception(_('Failed storing info cache'), instance=instance) - - -def wrap_check_policy(func): - """Check policy corresponding to the wrapped methods prior to execution.""" - - @functools.wraps(func) - def wrapped(self, context, *args, **kwargs): - action = func.__name__ - check_policy(context, action) - return func(self, context, *args, **kwargs) - - return wrapped - - -def check_policy(context, action): - target = { - 'project_id': context.project_id, - 'user_id': context.user_id, - } - _action = 'network:%s' % action - policy.enforce(context, _action, target) +refresh_cache = shiny_api.refresh_cache +_update_instance_cache = shiny_api.update_instance_cache_with_nw_info +update_instance_cache_with_nw_info = _update_instance_cache +wrap_check_policy = shiny_api.wrap_check_policy class API(base.Base): @@ -159,8 +97,8 @@ class API(base.Base): @wrap_check_policy def get_floating_ips_by_fixed_address(self, context, fixed_address): - return self.network_rpcapi.get_floating_ips_by_fixed_address(context, - fixed_address) + args = (context, fixed_address) + return self.network_rpcapi.get_floating_ips_by_fixed_address(*args) @wrap_check_policy def get_backdoor_port(self, context, host): @@ -170,12 +108,12 @@ class API(base.Base): def get_instance_id_by_floating_address(self, context, address): # NOTE(tr3buchet): i hate this return self.network_rpcapi.get_instance_id_by_floating_address(context, - address) + address) @wrap_check_policy def get_vifs_by_instance(self, context, instance): return self.network_rpcapi.get_vifs_by_instance(context, - instance['id']) + instance['id']) @wrap_check_policy def get_vif_by_mac_address(self, context, mac_address): @@ -189,14 +127,16 @@ class API(base.Base): # will probably need to move into a network supervisor # at some point. return self.network_rpcapi.allocate_floating_ip(context, - context.project_id, pool, False) + context.project_id, + pool, + False) @wrap_check_policy def release_floating_ip(self, context, address, affect_auto_assigned=False): """Removes (deallocates) a floating ip with address from a project.""" - return self.network_rpcapi.deallocate_floating_ip(context, address, - affect_auto_assigned) + args = (context, address, affect_auto_assigned) + return self.network_rpcapi.deallocate_floating_ip(*args) @wrap_check_policy @refresh_cache @@ -207,8 +147,8 @@ class API(base.Base): ensures floating ip is allocated to the project in context """ - orig_instance_uuid = self.network_rpcapi.associate_floating_ip(context, - floating_address, fixed_address, affect_auto_assigned) + args = (context, floating_address, fixed_address, affect_auto_assigned) + orig_instance_uuid = self.network_rpcapi.associate_floating_ip(*args) if orig_instance_uuid: msg_dict = dict(address=floating_address, @@ -227,12 +167,14 @@ class API(base.Base): affect_auto_assigned=False): """Disassociates a floating ip from fixed ip it is associated with.""" self.network_rpcapi.disassociate_floating_ip(context, address, - affect_auto_assigned) + affect_auto_assigned) @wrap_check_policy @refresh_cache def allocate_for_instance(self, context, instance, vpn, - requested_networks, macs=None): + requested_networks, macs=None, + conductor_api=None, security_groups=None, + **kwargs): """Allocates all network structures for an instance. TODO(someone): document the rest of these parameters. @@ -246,8 +188,7 @@ class API(base.Base): args = {} args['vpn'] = vpn args['requested_networks'] = requested_networks - args['instance_id'] = instance['id'] - args['instance_uuid'] = instance['uuid'] + args['instance_id'] = instance['uuid'] args['project_id'] = instance['project_id'] args['host'] = instance['host'] args['rxtx_factor'] = instance['instance_type']['rxtx_factor'] @@ -256,7 +197,7 @@ class API(base.Base): return network_model.NetworkInfo.hydrate(nw_info) @wrap_check_policy - def deallocate_for_instance(self, context, instance): + def deallocate_for_instance(self, context, instance, **kwargs): """Deallocates all network structures related to instance.""" args = {} @@ -267,28 +208,32 @@ class API(base.Base): @wrap_check_policy @refresh_cache - def add_fixed_ip_to_instance(self, context, instance, network_id): + def add_fixed_ip_to_instance(self, context, instance, network_id, + conductor_api=None, **kwargs): """Adds a fixed ip to instance from specified network.""" args = {'instance_id': instance['uuid'], 'host': instance['host'], - 'network_id': network_id} + 'network_id': network_id, + 'rxtx_factor': None} self.network_rpcapi.add_fixed_ip_to_instance(context, **args) @wrap_check_policy @refresh_cache - def remove_fixed_ip_from_instance(self, context, instance, address): + def remove_fixed_ip_from_instance(self, context, instance, address, + conductor=None, **kwargs): """Removes a fixed ip from instance from specified network.""" args = {'instance_id': instance['uuid'], 'host': instance['host'], - 'address': address} + 'address': address, + 'rxtx_factor': None} self.network_rpcapi.remove_fixed_ip_from_instance(context, **args) @wrap_check_policy def add_network_to_project(self, context, project_id, network_uuid=None): """Force adds another network to a project.""" self.network_rpcapi.add_network_to_project(context, project_id, - network_uuid) + network_uuid) @wrap_check_policy def associate(self, context, network_uuid, host=_sentinel, @@ -302,18 +247,17 @@ class API(base.Base): self.network_rpcapi.associate(context, network_uuid, associations) @wrap_check_policy - def get_instance_nw_info(self, context, instance, update_cache=True): + def get_instance_nw_info(self, context, instance, conductor_api=None, + **kwargs): """Returns all network info related to an instance.""" result = self._get_instance_nw_info(context, instance) - if update_cache: - update_instance_cache_with_nw_info(self, context, instance, - result) + update_instance_cache_with_nw_info(self, context, instance, + result, conductor_api) return result def _get_instance_nw_info(self, context, instance): """Returns all network info related to an instance.""" - args = {'instance_id': instance['id'], - 'instance_uuid': instance['uuid'], + args = {'instance_id': instance['uuid'], 'rxtx_factor': instance['instance_type']['rxtx_factor'], 'host': instance['host'], 'project_id': instance['project_id']} @@ -398,7 +342,7 @@ class API(base.Base): @wrap_check_policy def setup_networks_on_host(self, context, instance, host=None, - teardown=False): + teardown=False): """Setup or teardown the network structures on hosts related to instance""" host = host or instance['host'] @@ -422,8 +366,8 @@ class API(base.Base): return network['multi_host'] def _get_floating_ip_addresses(self, context, instance): - floating_ips = self.db.instance_floating_address_get_all(context, - instance['uuid']) + args = (context, instance['uuid']) + floating_ips = self.db.instance_floating_address_get_all(*args) return [floating_ip['address'] for floating_ip in floating_ips] @wrap_check_policy @@ -463,3 +407,20 @@ class API(base.Base): args['host'] = migration['dest_compute'] self.network_rpcapi.migrate_instance_finish(context, **args) + + # NOTE(jkoelker) These functions where added to the api after + # deprecation. Stubs provided for support documentation + def allocate_port_for_instance(self, context, instance, port_id, + network_id=None, requested_ip=None, + conductor_api=None): + raise NotImplementedError() + + def deallocate_port_for_instance(self, context, instance, port_id, + conductor_api=None): + raise NotImplementedError() + + def list_ports(self, *args, **kwargs): + raise NotImplementedError() + + def show_port(self, *args, **kwargs): + raise NotImplementedError() diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 29b882a02..cb23e77b6 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -29,8 +29,10 @@ from oslo.config import cfg from nova import db from nova import exception +from nova.openstack.common import excutils from nova.openstack.common import fileutils from nova.openstack.common import importutils +from nova.openstack.common import jsonutils from nova.openstack.common import lockutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils @@ -41,9 +43,9 @@ LOG = logging.getLogger(__name__) linux_net_opts = [ - cfg.StrOpt('dhcpbridge_flagfile', - default='/etc/nova/nova-dhcpbridge.conf', - help='location of flagfile for dhcpbridge'), + cfg.MultiStrOpt('dhcpbridge_flagfile', + default=['/etc/nova/nova-dhcpbridge.conf'], + help='location of flagfiles for dhcpbridge'), cfg.StrOpt('networks_path', default=paths.state_path_def('networks'), help='Location to keep network config files'), @@ -275,6 +277,14 @@ class IptablesTable(object): {'chain': chain, 'rule': rule, 'top': top, 'wrap': wrap}) + def remove_rules_regex(self, regex): + """Remove all rules matching regex.""" + if isinstance(regex, basestring): + regex = re.compile(regex) + num_rules = len(self.rules) + self.rules = filter(lambda r: not regex.match(str(r)), self.rules) + return num_rules - len(self.rules) + def empty_chain(self, chain, wrap=True): """Remove all rules from a chain.""" chained_rules = [rule for rule in self.rules @@ -710,6 +720,12 @@ def ensure_vpn_forward(public_ip, port, private_ip): def ensure_floating_forward(floating_ip, fixed_ip, device, network): """Ensure floating ip forwarding rule.""" + # NOTE(vish): Make sure we never have duplicate rules for the same ip + regex = '.*\s+%s(/32|\s+|$)' % floating_ip + num_rules = iptables_manager.ipv4['nat'].remove_rules_regex(regex) + if num_rules: + msg = _('Removed %(num)d duplicate rules for floating ip %(float)s') + LOG.warn(msg % {'num': num_rules, 'float': floating_ip}) for chain, rule in floating_forward_rules(floating_ip, fixed_ip, device): iptables_manager.ipv4['nat'].add_rule(chain, rule) iptables_manager.apply() @@ -994,7 +1010,7 @@ def restart_dhcp(context, dev, network_ref): LOG.debug(_('Pid %d is stale, relaunching dnsmasq'), pid) cmd = ['env', - 'CONFIG_FILE=%s' % CONF.dhcpbridge_flagfile, + 'CONFIG_FILE=%s' % jsonutils.dumps(CONF.dhcpbridge_flagfile), 'NETWORK_ID=%s' % str(network_ref['id']), 'dnsmasq', '--strict-order', @@ -1390,9 +1406,9 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): utils.execute('ip', 'link', 'delete', vlan_interface, run_as_root=True, check_exit_code=[0, 2, 254]) except exception.ProcessExecutionError: - LOG.error(_("Failed unplugging VLAN interface '%s'"), - vlan_interface) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_("Failed unplugging VLAN interface '%s'"), + vlan_interface) LOG.debug(_("Unplugged VLAN interface '%s'"), vlan_interface) @classmethod @@ -1496,8 +1512,9 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): utils.execute('ip', 'link', 'delete', bridge, run_as_root=True, check_exit_code=[0, 2, 254]) except exception.ProcessExecutionError: - LOG.error(_("Failed unplugging bridge interface '%s'"), bridge) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_("Failed unplugging bridge interface '%s'"), + bridge) LOG.debug(_("Unplugged bridge interface '%s'"), bridge) @@ -1695,8 +1712,9 @@ class QuantumLinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): utils.execute('ip', 'link', 'delete', dev, run_as_root=True, check_exit_code=[0, 2, 254]) except exception.ProcessExecutionError: - LOG.error(_("Failed unplugging gateway interface '%s'"), dev) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_("Failed unplugging gateway interface '%s'"), + dev) LOG.debug(_("Unplugged gateway interface '%s'"), dev) return dev diff --git a/nova/network/model.py b/nova/network/model.py index bfd4639ee..32415be78 100644 --- a/nova/network/model.py +++ b/nova/network/model.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/network/quantumv2/__init__.py b/nova/network/quantumv2/__init__.py index 5d3cf5770..bda0392a9 100644 --- a/nova/network/quantumv2/__init__.py +++ b/nova/network/quantumv2/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/network/quantumv2/api.py b/nova/network/quantumv2/api.py index 851a544dc..5537048a7 100644 --- a/nova/network/quantumv2/api.py +++ b/nova/network/quantumv2/api.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved # Copyright (c) 2012 NEC Corporation # @@ -172,9 +172,10 @@ class API(base.Base): available_macs.discard(port['mac_address']) network_id = port['network_id'] ports[network_id] = port - elif fixed_ip: + elif fixed_ip and network_id: fixed_ips[network_id] = fixed_ip - net_ids.append(network_id) + if network_id: + net_ids.append(network_id) nets = self._get_available_networks(context, instance['project_id'], net_ids) @@ -278,8 +279,15 @@ class API(base.Base): self.trigger_security_group_members_refresh(context, instance) self.trigger_instance_add_security_group_refresh(context, instance) - return self.get_instance_nw_info(context, instance, networks=nets, - conductor_api=kwargs.get('conductor_api')) + nw_info = self.get_instance_nw_info(context, instance, networks=nets, + conductor_api=kwargs.get('conductor_api')) + # NOTE(danms): Only return info about ports we created in this run. + # In the initial allocation case, this will be everything we created, + # and in later runs will only be what was created that time. Thus, + # this only affects the attach case, not the original use for this + # method. + return network_model.NetworkInfo([port for port in nw_info + if port['id'] in created_port_ids]) def _refresh_quantum_extensions_cache(self): if (not self.last_quantum_extension_sync or @@ -774,6 +782,12 @@ class API(base.Base): network_name = net['name'] break + if network_name is None: + raise exception.NotFound(_('Network %(net)s for ' + 'port %(port_id)s not found!') % + {'net': port['network_id'], + 'port': port['id']}) + network_IPs = [network_model.FixedIP(address=ip_address) for ip_address in [ip['ip_address'] for ip in port['fixed_ips']]] diff --git a/nova/network/security_group/quantum_driver.py b/nova/network/security_group/quantum_driver.py index 918c839e9..e6f88e20c 100644 --- a/nova/network/security_group/quantum_driver.py +++ b/nova/network/security_group/quantum_driver.py @@ -27,6 +27,7 @@ from nova import context from nova import exception from nova.network import quantumv2 from nova.network.security_group import security_group_base +from nova.openstack.common import excutils from nova.openstack.common import log as logging from nova.openstack.common import uuidutils @@ -90,13 +91,16 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): nova_rule['to_port'] = -1 else: nova_rule['to_port'] = rule['port_range_max'] - nova_rule['group_id'] = rule['source_group_id'] - nova_rule['cidr'] = rule['source_ip_prefix'] + nova_rule['group_id'] = rule['remote_group_id'] + nova_rule['cidr'] = rule['remote_ip_prefix'] return nova_rule def get(self, context, name=None, id=None, map_exception=False): quantum = quantumv2.get_client(context) try: + if not id and name: + id = quantumv20.find_resourceid_by_name_or_id( + quantum, 'security_group', name) group = quantum.show_security_group(id).get('security_group') except q_exc.QuantumClientException as e: if e.status_code == 404: @@ -113,8 +117,13 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): search_opts=None): """Returns list of security group rules owned by tenant.""" quantum = quantumv2.get_client(context) + search_opts = {} + if names: + search_opts['name'] = names + if ids: + search_opts['id'] = ids try: - security_groups = quantum.list_security_groups().get( + security_groups = quantum.list_security_groups(**search_opts).get( 'security_groups') except q_exc.QuantumClientException as e: LOG.exception(_("Quantum Error getting security groups")) @@ -197,9 +206,9 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): new_rule['ethertype'] = 'IPv4' else: new_rule['ethertype'] = utils.get_ip_version(rule.get('cidr')) - new_rule['source_ip_prefix'] = rule.get('cidr') + new_rule['remote_ip_prefix'] = rule.get('cidr') new_rule['security_group_id'] = rule.get('parent_group_id') - new_rule['source_group_id'] = rule.get('group_id') + new_rule['remote_group_id'] = rule.get('group_id') if rule['from_port'] != -1: new_rule['port_range_min'] = rule['from_port'] if rule['to_port'] != -1: @@ -207,10 +216,6 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): new_rules.append(new_rule) return {'security_group_rules': new_rules} - def create_security_group_rule(self, context, security_group, new_rule): - return self.add_rules(context, new_rule['parent_group_id'], - security_group['name'], [new_rule])[0] - def remove_rules(self, context, security_group, rule_ids): quantum = quantumv2.get_client(context) rule_ids = set(rule_ids) @@ -328,8 +333,8 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): 'port_id': port['id']}) quantum.update_port(port['id'], {'port': updated_port}) except Exception: - LOG.exception(_("Quantum Error:")) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_("Quantum Error:")) @wrap_check_security_groups_policy def remove_from_instance(self, context, instance, security_group_name): @@ -388,10 +393,6 @@ class SecurityGroupAPI(security_group_base.SecurityGroupBase): 'instance': instance['uuid']}) self.raise_not_found(msg) - def rule_exists(self, security_group, new_rule): - # Handled by quantum - pass - def populate_security_groups(self, instance, security_groups): # Setting to emply list since we do not want to populate this field # in the nova database if using the quantum driver diff --git a/nova/network/security_group/security_group_base.py b/nova/network/security_group/security_group_base.py index 499f808b1..4a82bd881 100644 --- a/nova/network/security_group/security_group_base.py +++ b/nova/network/security_group/security_group_base.py @@ -132,6 +132,30 @@ class SecurityGroupBase(object): return values + def create_security_group_rule(self, context, security_group, new_rule): + if self.rule_exists(security_group, new_rule): + msg = (_('This rule already exists in group %s') % + new_rule['parent_group_id']) + self.raise_group_already_exists(msg) + return self.add_rules(context, new_rule['parent_group_id'], + security_group['name'], + [new_rule])[0] + + def rule_exists(self, security_group, new_rule): + """Indicates whether the specified rule is already + defined in the given security group. + """ + for rule in security_group['rules']: + is_duplicate = True + keys = ('group_id', 'cidr', 'from_port', 'to_port', 'protocol') + for key in keys: + if rule.get(key) != new_rule.get(key): + is_duplicate = False + break + if is_duplicate: + return rule.get('id') or True + return False + def validate_property(self, value, property, allowed): pass @@ -174,9 +198,6 @@ class SecurityGroupBase(object): def add_rules(self, context, id, name, vals): raise NotImplementedError() - def create_security_group_rule(self, context, security_group, new_rule): - raise NotImplementedError() - def remove_rules(self, context, security_group, rule_ids): raise NotImplementedError() @@ -192,5 +213,26 @@ class SecurityGroupBase(object): def remove_from_instance(self, context, instance, security_group_name): raise NotImplementedError() - def rule_exists(self, security_group, new_rule): + @staticmethod + def raise_invalid_property(msg): + raise NotImplementedError() + + @staticmethod + def raise_group_already_exists(msg): + raise NotImplementedError() + + @staticmethod + def raise_invalid_group(msg): + raise NotImplementedError() + + @staticmethod + def raise_invalid_cidr(cidr, decoding_exception=None): + raise NotImplementedError() + + @staticmethod + def raise_over_quota(msg): + raise NotImplementedError() + + @staticmethod + def raise_not_found(msg): raise NotImplementedError() diff --git a/nova/notifications.py b/nova/notifications.py index 79d43126a..16a49dcf6 100644 --- a/nova/notifications.py +++ b/nova/notifications.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -26,6 +26,7 @@ from nova import db from nova.image import glance from nova import network from nova.network import model as network_model +from nova.openstack.common import excutils from nova.openstack.common import log from nova.openstack.common.notifier import api as notifier_api from nova.openstack.common import timeutils @@ -33,27 +34,25 @@ from nova import utils LOG = log.getLogger(__name__) -notify_state_opt = cfg.StrOpt('notify_on_state_change', default=None, - help='If set, send compute.instance.update notifications on instance ' - 'state changes. Valid values are None for no notifications, ' - '"vm_state" for notifications on VM state changes, or ' - '"vm_and_task_state" for notifications on VM and task state ' - 'changes.') - -notify_any_opt = cfg.BoolOpt('notify_on_any_change', default=False, - help='If set, send compute.instance.update notifications on instance ' - 'state changes. Valid values are False for no notifications, ' - 'True for notifications on any instance changes.') - -notify_api_faults = cfg.BoolOpt('notify_api_faults', default=False, - help='If set, send api.fault notifications on caught exceptions ' - 'in the API service.') +notify_opts = [ + cfg.StrOpt('notify_on_state_change', default=None, + help='If set, send compute.instance.update notifications on instance ' + 'state changes. Valid values are None for no notifications, ' + '"vm_state" for notifications on VM state changes, or ' + '"vm_and_task_state" for notifications on VM and task state ' + 'changes.'), + cfg.BoolOpt('notify_on_any_change', default=False, + help='If set, send compute.instance.update notifications on instance ' + 'state changes. Valid values are False for no notifications, ' + 'True for notifications on any instance changes.'), + cfg.BoolOpt('notify_api_faults', default=False, + help='If set, send api.fault notifications on caught exceptions ' + 'in the API service.'), +] CONF = cfg.CONF -CONF.register_opt(notify_state_opt) -CONF.register_opt(notify_any_opt) -CONF.register_opt(notify_api_faults) +CONF.register_opts(notify_opts) def send_api_fault(url, status, exception): @@ -227,10 +226,14 @@ def bandwidth_usage(instance_ref, audit_start, nw_info = network.API().get_instance_nw_info(admin_context, instance_ref) except Exception: - LOG.exception(_('Failed to get nw_info'), instance=instance_ref) - if ignore_missing_network_data: - return - raise + try: + with excutils.save_and_reraise_exception(): + LOG.exception(_('Failed to get nw_info'), + instance=instance_ref) + except Exception: + if ignore_missing_network_data: + return + raise macs = [vif['address'] for vif in nw_info] uuids = [instance_ref["uuid"]] diff --git a/nova/objectstore/s3server.py b/nova/objectstore/s3server.py index 3ff5fa003..1c9f19a4e 100644 --- a/nova/objectstore/s3server.py +++ b/nova/objectstore/s3server.py @@ -2,7 +2,7 @@ # # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # Copyright 2009 Facebook # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/context.py b/nova/openstack/common/context.py index dd7dd04c3..709ce4d45 100644 --- a/nova/openstack/common/context.py +++ b/nova/openstack/common/context.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/db/exception.py b/nova/openstack/common/db/exception.py new file mode 100644 index 000000000..61ba1b3a9 --- /dev/null +++ b/nova/openstack/common/db/exception.py @@ -0,0 +1,45 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""DB related custom exceptions.""" + +from nova.openstack.common.gettextutils import _ + + +class DBError(Exception): + """Wraps an implementation specific exception.""" + def __init__(self, inner_exception=None): + self.inner_exception = inner_exception + super(DBError, self).__init__(str(inner_exception)) + + +class DBDuplicateEntry(DBError): + """Wraps an implementation specific exception.""" + def __init__(self, columns=[], inner_exception=None): + self.columns = columns + super(DBDuplicateEntry, self).__init__(inner_exception) + + +class DBDeadlock(DBError): + def __init__(self, inner_exception=None): + super(DBDeadlock, self).__init__(inner_exception) + + +class DBInvalidUnicodeParameter(Exception): + message = _("Invalid Parameter: " + "Unicode is not supported by the current database.") diff --git a/nova/openstack/common/db/sqlalchemy/session.py b/nova/openstack/common/db/sqlalchemy/session.py index fb86d9ca5..cf6713581 100644 --- a/nova/openstack/common/db/sqlalchemy/session.py +++ b/nova/openstack/common/db/sqlalchemy/session.py @@ -246,12 +246,13 @@ import time from eventlet import greenthread from oslo.config import cfg -from sqlalchemy.exc import DisconnectionError, OperationalError, IntegrityError +from sqlalchemy import exc as sqla_exc import sqlalchemy.interfaces import sqlalchemy.orm from sqlalchemy.pool import NullPool, StaticPool from sqlalchemy.sql.expression import literal_column +from nova.openstack.common.db import exception from nova.openstack.common import log as logging from nova.openstack.common.gettextutils import _ from nova.openstack.common import timeutils @@ -327,25 +328,6 @@ def get_session(autocommit=True, expire_on_commit=False): return session -class DBError(Exception): - """Wraps an implementation specific exception.""" - def __init__(self, inner_exception=None): - self.inner_exception = inner_exception - super(DBError, self).__init__(str(inner_exception)) - - -class DBDuplicateEntry(DBError): - """Wraps an implementation specific exception.""" - def __init__(self, columns=[], inner_exception=None): - self.columns = columns - super(DBDuplicateEntry, self).__init__(inner_exception) - - -class InvalidUnicodeParameter(Exception): - message = _("Invalid Parameter: " - "Unicode is not supported by the current database.") - - # note(boris-42): In current versions of DB backends unique constraint # violation messages follow the structure: # @@ -364,7 +346,7 @@ class InvalidUnicodeParameter(Exception): # 'c1'") # N columns - (IntegrityError) (1062, "Duplicate entry 'values joined # with -' for key 'name_of_our_constraint'") -_RE_DB = { +_DUP_KEY_RE_DB = { "sqlite": re.compile(r"^.*columns?([^)]+)(is|are)\s+not\s+unique$"), "postgresql": re.compile(r"^.*duplicate\s+key.*\"([^\"]+)\"\s*\n.*$"), "mysql": re.compile(r"^.*\(1062,.*'([^\']+)'\"\)$") @@ -390,7 +372,7 @@ def raise_if_duplicate_entry_error(integrity_error, engine_name): if engine_name not in ["mysql", "sqlite", "postgresql"]: return - m = _RE_DB[engine_name].match(integrity_error.message) + m = _DUP_KEY_RE_DB[engine_name].match(integrity_error.message) if not m: return columns = m.group(1) @@ -399,7 +381,32 @@ def raise_if_duplicate_entry_error(integrity_error, engine_name): columns = columns.strip().split(", ") else: columns = get_columns_from_uniq_cons_or_name(columns) - raise DBDuplicateEntry(columns, integrity_error) + raise exception.DBDuplicateEntry(columns, integrity_error) + + +# NOTE(comstud): In current versions of DB backends, Deadlock violation +# messages follow the structure: +# +# mysql: +# (OperationalError) (1213, 'Deadlock found when trying to get lock; try ' +# 'restarting transaction') <query_str> <query_args> +_DEADLOCK_RE_DB = { + "mysql": re.compile(r"^.*\(1213, 'Deadlock.*") +} + + +def raise_if_deadlock_error(operational_error, engine_name): + """ + Raise DBDeadlock exception if OperationalError contains a Deadlock + condition. + """ + re = _DEADLOCK_RE_DB.get(engine_name) + if re is None: + return + m = re.match(operational_error.message) + if not m: + return + raise exception.DBDeadlock(operational_error) def wrap_db_error(f): @@ -407,21 +414,26 @@ def wrap_db_error(f): try: return f(*args, **kwargs) except UnicodeEncodeError: - raise InvalidUnicodeParameter() + raise exception.DBInvalidUnicodeParameter() # note(boris-42): We should catch unique constraint violation and # wrap it by our own DBDuplicateEntry exception. Unique constraint # violation is wrapped by IntegrityError. - except IntegrityError, e: + except sqla_exc.OperationalError, e: + raise_if_deadlock_error(e, get_engine().name) + # NOTE(comstud): A lot of code is checking for OperationalError + # so let's not wrap it for now. + raise + except sqla_exc.IntegrityError, e: # note(boris-42): SqlAlchemy doesn't unify errors from different # DBs so we must do this. Also in some tables (for example # instance_types) there are more than one unique constraint. This # means we should get names of columns, which values violate # unique constraint, from error message. raise_if_duplicate_entry_error(e, get_engine().name) - raise DBError(e) + raise exception.DBError(e) except Exception, e: LOG.exception(_('DB exception wrapped.')) - raise DBError(e) + raise exception.DBError(e) _wrap.func_name = f.func_name return _wrap @@ -471,7 +483,7 @@ def ping_listener(dbapi_conn, connection_rec, connection_proxy): except dbapi_conn.OperationalError, ex: if ex.args[0] in (2006, 2013, 2014, 2045, 2055): LOG.warn(_('Got mysql server has gone away: %s'), ex) - raise DisconnectionError("Database server went away") + raise sqla_exc.DisconnectionError("Database server went away") else: raise @@ -532,7 +544,7 @@ def create_engine(sql_connection): try: engine.connect() - except OperationalError, e: + except sqla_exc.OperationalError, e: if not is_db_connection_error(e.args[0]): raise @@ -548,7 +560,7 @@ def create_engine(sql_connection): try: engine.connect() break - except OperationalError, e: + except sqla_exc.OperationalError, e: if (remaining != 'infinite' and remaining == 0) or \ not is_db_connection_error(e.args[0]): raise diff --git a/nova/openstack/common/db/sqlalchemy/utils.py b/nova/openstack/common/db/sqlalchemy/utils.py index ef8af57ce..6a9cb846f 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 LLC. +# Copyright 2010-2011 OpenStack Foundation # Copyright 2012 Justin Santa Barbara # All Rights Reserved. # diff --git a/nova/openstack/common/eventlet_backdoor.py b/nova/openstack/common/eventlet_backdoor.py index 8b81ebf8e..007676847 100644 --- a/nova/openstack/common/eventlet_backdoor.py +++ b/nova/openstack/common/eventlet_backdoor.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 Openstack, LLC. +# Copyright (c) 2012 OpenStack Foundation # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # diff --git a/nova/openstack/common/excutils.py b/nova/openstack/common/excutils.py index e507efced..bfd3fc0ed 100644 --- a/nova/openstack/common/excutils.py +++ b/nova/openstack/common/excutils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2012, Red Hat, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/fileutils.py b/nova/openstack/common/fileutils.py index 4746ad498..cc52e7d44 100644 --- a/nova/openstack/common/fileutils.py +++ b/nova/openstack/common/fileutils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/importutils.py b/nova/openstack/common/importutils.py index 9dec764fb..8b5c00892 100644 --- a/nova/openstack/common/importutils.py +++ b/nova/openstack/common/importutils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/jsonutils.py b/nova/openstack/common/jsonutils.py index b06055117..3a2f27730 100644 --- a/nova/openstack/common/jsonutils.py +++ b/nova/openstack/common/jsonutils.py @@ -38,14 +38,10 @@ import functools import inspect import itertools import json -import logging import xmlrpclib -from nova.openstack.common.gettextutils import _ from nova.openstack.common import timeutils -LOG = logging.getLogger(__name__) - def to_primitive(value, convert_instances=False, convert_datetime=True, level=0, max_depth=3): @@ -85,8 +81,6 @@ def to_primitive(value, convert_instances=False, convert_datetime=True, return 'mock' if level > max_depth: - LOG.error(_('Max serialization depth exceeded on object: %d %s'), - level, value) return '?' # The try block may not be necessary after the class check above, diff --git a/nova/openstack/common/local.py b/nova/openstack/common/local.py index 8bdc837a9..a9796bfe7 100644 --- a/nova/openstack/common/local.py +++ b/nova/openstack/common/local.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/lockutils.py b/nova/openstack/common/lockutils.py index 6ee376929..3270f0473 100644 --- a/nova/openstack/common/lockutils.py +++ b/nova/openstack/common/lockutils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/log.py b/nova/openstack/common/log.py index 796045657..dfad9919f 100644 --- a/nova/openstack/common/log.py +++ b/nova/openstack/common/log.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. @@ -325,16 +325,11 @@ def _create_logging_excepthook(product_name): def setup(product_name): """Setup logging.""" - sys.excepthook = _create_logging_excepthook(product_name) - if CONF.log_config: - try: - logging.config.fileConfig(CONF.log_config) - except Exception: - traceback.print_exc() - raise + logging.config.fileConfig(CONF.log_config) else: _setup_logging_from_conf(product_name) + sys.excepthook = _create_logging_excepthook(product_name) def set_defaults(logging_context_format_string): diff --git a/nova/common/memorycache.py b/nova/openstack/common/memorycache.py index c124784d5..9f876b80c 100644 --- a/nova/common/memorycache.py +++ b/nova/openstack/common/memorycache.py @@ -32,14 +32,19 @@ CONF = cfg.CONF CONF.register_opts(memcache_opts) -def get_client(): +def get_client(memcached_servers=None): client_cls = Client - if CONF.memcached_servers: - import memcache - client_cls = memcache.Client + if not memcached_servers: + memcached_servers = CONF.memcached_servers + if memcached_servers: + try: + import memcache + client_cls = memcache.Client + except ImportError: + pass - return client_cls(CONF.memcached_servers, debug=0) + return client_cls(memcached_servers, debug=0) class Client(object): @@ -54,9 +59,10 @@ class Client(object): this expunges expired keys during each get""" + now = timeutils.utcnow_ts() for k in self.cache.keys(): (timeout, _value) = self.cache[k] - if timeout and timeutils.utcnow_ts() >= timeout: + if timeout and now >= timeout: del self.cache[k] return self.cache.get(key, (0, None))[1] diff --git a/nova/openstack/common/network_utils.py b/nova/openstack/common/network_utils.py index 69f673216..65299b009 100644 --- a/nova/openstack/common/network_utils.py +++ b/nova/openstack/common/network_utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/__init__.py b/nova/openstack/common/notifier/__init__.py index 482d54e4f..31285c4fc 100644 --- a/nova/openstack/common/notifier/__init__.py +++ b/nova/openstack/common/notifier/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/api.py b/nova/openstack/common/notifier/api.py index 70941e243..cb0a38b71 100644 --- a/nova/openstack/common/notifier/api.py +++ b/nova/openstack/common/notifier/api.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/log_notifier.py b/nova/openstack/common/notifier/log_notifier.py index 4fe4d74ea..51e488c94 100644 --- a/nova/openstack/common/notifier/log_notifier.py +++ b/nova/openstack/common/notifier/log_notifier.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/no_op_notifier.py b/nova/openstack/common/notifier/no_op_notifier.py index ee1ddbdca..d22d02072 100644 --- a/nova/openstack/common/notifier/no_op_notifier.py +++ b/nova/openstack/common/notifier/no_op_notifier.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/rpc_notifier.py b/nova/openstack/common/notifier/rpc_notifier.py index b348480c9..a119b2b7a 100644 --- a/nova/openstack/common/notifier/rpc_notifier.py +++ b/nova/openstack/common/notifier/rpc_notifier.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/rpc_notifier2.py b/nova/openstack/common/notifier/rpc_notifier2.py index f1158a2f9..d2ad74fb4 100644 --- a/nova/openstack/common/notifier/rpc_notifier2.py +++ b/nova/openstack/common/notifier/rpc_notifier2.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/notifier/test_notifier.py b/nova/openstack/common/notifier/test_notifier.py index 5e348803d..2e392f8b9 100644 --- a/nova/openstack/common/notifier/test_notifier.py +++ b/nova/openstack/common/notifier/test_notifier.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/plugin/__init__.py b/nova/openstack/common/plugin/__init__.py index 63c3905e2..bf3075ddd 100644 --- a/nova/openstack/common/plugin/__init__.py +++ b/nova/openstack/common/plugin/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/plugin/callbackplugin.py b/nova/openstack/common/plugin/callbackplugin.py index d19a1cf48..371819189 100644 --- a/nova/openstack/common/plugin/callbackplugin.py +++ b/nova/openstack/common/plugin/callbackplugin.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/plugin/plugin.py b/nova/openstack/common/plugin/plugin.py index 96be0af82..66feb000b 100644 --- a/nova/openstack/common/plugin/plugin.py +++ b/nova/openstack/common/plugin/plugin.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/plugin/pluginmanager.py b/nova/openstack/common/plugin/pluginmanager.py index 040b721a4..b789c2c7c 100644 --- a/nova/openstack/common/plugin/pluginmanager.py +++ b/nova/openstack/common/plugin/pluginmanager.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/policy.py b/nova/openstack/common/policy.py index 626a61aa5..8ed40477e 100644 --- a/nova/openstack/common/policy.py +++ b/nova/openstack/common/policy.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/processutils.py b/nova/openstack/common/processutils.py index 297f911c4..8ace63176 100644 --- a/nova/openstack/common/processutils.py +++ b/nova/openstack/common/processutils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/rootwrap/__init__.py b/nova/openstack/common/rootwrap/__init__.py index 671d3c173..f0f23d6a2 100644 --- a/nova/openstack/common/rootwrap/__init__.py +++ b/nova/openstack/common/rootwrap/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/rootwrap/filters.py b/nova/openstack/common/rootwrap/filters.py index 905bbabea..8e92d6bb4 100644 --- a/nova/openstack/common/rootwrap/filters.py +++ b/nova/openstack/common/rootwrap/filters.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/rootwrap/wrapper.py b/nova/openstack/common/rootwrap/wrapper.py index 4452177fe..7dc533e1e 100644 --- a/nova/openstack/common/rootwrap/wrapper.py +++ b/nova/openstack/common/rootwrap/wrapper.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/rpc/impl_fake.py b/nova/openstack/common/rpc/impl_fake.py index f43dbfe91..965d2640d 100644 --- a/nova/openstack/common/rpc/impl_fake.py +++ b/nova/openstack/common/rpc/impl_fake.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/openstack/common/rpc/impl_kombu.py b/nova/openstack/common/rpc/impl_kombu.py index 180685cf3..0d83253f1 100644 --- a/nova/openstack/common/rpc/impl_kombu.py +++ b/nova/openstack/common/rpc/impl_kombu.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/openstack/common/rpc/impl_qpid.py b/nova/openstack/common/rpc/impl_qpid.py index 5601ddb33..542256d0c 100644 --- a/nova/openstack/common/rpc/impl_qpid.py +++ b/nova/openstack/common/rpc/impl_qpid.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Copyright 2011 - 2012, Red Hat, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/openstack/common/setup.py b/nova/openstack/common/setup.py index 35680b304..de008ab15 100644 --- a/nova/openstack/common/setup.py +++ b/nova/openstack/common/setup.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2012-2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # diff --git a/nova/openstack/common/version.py b/nova/openstack/common/version.py index 57803b3d5..6bf41a75c 100644 --- a/nova/openstack/common/version.py +++ b/nova/openstack/common/version.py @@ -1,5 +1,5 @@ -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # Copyright 2012-2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/policy.py b/nova/policy.py index 6e500d926..68f449696 100644 --- a/nova/policy.py +++ b/nova/policy.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/safe_utils.py b/nova/safe_utils.py new file mode 100644 index 000000000..9c8fc2810 --- /dev/null +++ b/nova/safe_utils.py @@ -0,0 +1,55 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 Justin Santa Barbara +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Utilities and helper functions that won't produce circular imports.""" + +import inspect + + +def getcallargs(function, *args, **kwargs): + """This is a simplified inspect.getcallargs (2.7+). + + It should be replaced when python >= 2.7 is standard. + """ + keyed_args = {} + argnames, varargs, keywords, defaults = inspect.getargspec(function) + + keyed_args.update(kwargs) + + #NOTE(alaski) the implicit 'self' or 'cls' argument shows up in + # argnames but not in args or kwargs. Uses 'in' rather than '==' because + # some tests use 'self2'. + if 'self' in argnames[0] or 'cls' == argnames[0]: + # The function may not actually be a method or have im_self. + # Typically seen when it's stubbed with mox. + if inspect.ismethod(function) and hasattr(function, 'im_self'): + keyed_args[argnames[0]] = function.im_self + else: + keyed_args[argnames[0]] = None + + remaining_argnames = filter(lambda x: x not in keyed_args, argnames) + keyed_args.update(dict(zip(remaining_argnames, args))) + + if defaults: + num_defaults = len(defaults) + for argname, value in zip(argnames[-num_defaults:], defaults): + if argname not in keyed_args: + keyed_args[argname] = value + + return keyed_args diff --git a/nova/scheduler/__init__.py b/nova/scheduler/__init__.py index 32e5d4d02..7dc4ffc35 100644 --- a/nova/scheduler/__init__.py +++ b/nova/scheduler/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/scheduler/baremetal_host_manager.py b/nova/scheduler/baremetal_host_manager.py index fdf482de7..226476714 100644 --- a/nova/scheduler/baremetal_host_manager.py +++ b/nova/scheduler/baremetal_host_manager.py @@ -1,5 +1,5 @@ # Copyright (c) 2012 NTT DOCOMO, INC. -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/chance.py b/nova/scheduler/chance.py index c639aaf80..5bbc3ac3b 100644 --- a/nova/scheduler/chance.py +++ b/nova/scheduler/chance.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/nova/scheduler/driver.py b/nova/scheduler/driver.py index 96a3e5e98..3426c484c 100644 --- a/nova/scheduler/driver.py +++ b/nova/scheduler/driver.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. @@ -256,9 +256,11 @@ class Scheduler(object): # If dest is not specified, have scheduler pick one. if dest is None: + instance_type = db.instance_type_get( + context, instance_ref['instance_type_id']) image = self.image_service.show(context, instance_ref['image_ref']) request_spec = {'instance_properties': instance_ref, - 'instance_type': instance_ref['instance_type'], + 'instance_type': instance_type, 'instance_uuids': [instance_ref['uuid']], 'image': image} filter_properties = {'ignore_hosts': ignore_hosts} diff --git a/nova/scheduler/filter_scheduler.py b/nova/scheduler/filter_scheduler.py index b886a04cc..b9768e11b 100644 --- a/nova/scheduler/filter_scheduler.py +++ b/nova/scheduler/filter_scheduler.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/__init__.py b/nova/scheduler/filters/__init__.py index 6e8e7ea7b..0bd069826 100644 --- a/nova/scheduler/filters/__init__.py +++ b/nova/scheduler/filters/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/affinity_filter.py b/nova/scheduler/filters/affinity_filter.py index a7e894320..bb7cb4aff 100644 --- a/nova/scheduler/filters/affinity_filter.py +++ b/nova/scheduler/filters/affinity_filter.py @@ -1,5 +1,5 @@ # Copyright 2012, Piston Cloud Computing, Inc. -# Copyright 2012, OpenStack LLC. +# Copyright 2012, OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/scheduler/filters/aggregate_instance_extra_specs.py b/nova/scheduler/filters/aggregate_instance_extra_specs.py index 3a3628f6a..6e1e47f68 100644 --- a/nova/scheduler/filters/aggregate_instance_extra_specs.py +++ b/nova/scheduler/filters/aggregate_instance_extra_specs.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # Copyright (c) 2012 Cloudscaling # All Rights Reserved. # diff --git a/nova/scheduler/filters/aggregate_multitenancy_isolation.py b/nova/scheduler/filters/aggregate_multitenancy_isolation.py index 539da37d1..d9192af52 100644 --- a/nova/scheduler/filters/aggregate_multitenancy_isolation.py +++ b/nova/scheduler/filters/aggregate_multitenancy_isolation.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2013 OpenStack, LLC. +# Copyright (c) 2011-2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/all_hosts_filter.py b/nova/scheduler/filters/all_hosts_filter.py index 4e01a624e..d6973f944 100644 --- a/nova/scheduler/filters/all_hosts_filter.py +++ b/nova/scheduler/filters/all_hosts_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/availability_zone_filter.py b/nova/scheduler/filters/availability_zone_filter.py index f6c7472bf..fc578a7fb 100644 --- a/nova/scheduler/filters/availability_zone_filter.py +++ b/nova/scheduler/filters/availability_zone_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/compute_capabilities_filter.py b/nova/scheduler/filters/compute_capabilities_filter.py index acbfa4702..e559c18a8 100644 --- a/nova/scheduler/filters/compute_capabilities_filter.py +++ b/nova/scheduler/filters/compute_capabilities_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/compute_filter.py b/nova/scheduler/filters/compute_filter.py index f571955d9..f6c643c1c 100644 --- a/nova/scheduler/filters/compute_filter.py +++ b/nova/scheduler/filters/compute_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/core_filter.py b/nova/scheduler/filters/core_filter.py index a07a1b39a..4eb6ebcf1 100644 --- a/nova/scheduler/filters/core_filter.py +++ b/nova/scheduler/filters/core_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # Copyright (c) 2012 Justin Santa Barbara # # All Rights Reserved. diff --git a/nova/scheduler/filters/disk_filter.py b/nova/scheduler/filters/disk_filter.py index 812b9b212..517d43510 100644 --- a/nova/scheduler/filters/disk_filter.py +++ b/nova/scheduler/filters/disk_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/extra_specs_ops.py b/nova/scheduler/filters/extra_specs_ops.py index c77cd7b60..22fb219df 100644 --- a/nova/scheduler/filters/extra_specs_ops.py +++ b/nova/scheduler/filters/extra_specs_ops.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/image_props_filter.py b/nova/scheduler/filters/image_props_filter.py index a545ce9ff..185d2f4e4 100644 --- a/nova/scheduler/filters/image_props_filter.py +++ b/nova/scheduler/filters/image_props_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC +# Copyright (c) 2011-2012 OpenStack Foundation # Copyright (c) 2012 Canonical Ltd # Copyright (c) 2012 SUSE LINUX Products GmbH # All Rights Reserved. diff --git a/nova/scheduler/filters/io_ops_filter.py b/nova/scheduler/filters/io_ops_filter.py index a60be57e2..7d3337c1a 100644 --- a/nova/scheduler/filters/io_ops_filter.py +++ b/nova/scheduler/filters/io_ops_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/isolated_hosts_filter.py b/nova/scheduler/filters/isolated_hosts_filter.py index 89beb0ed0..c8849bcca 100644 --- a/nova/scheduler/filters/isolated_hosts_filter.py +++ b/nova/scheduler/filters/isolated_hosts_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/json_filter.py b/nova/scheduler/filters/json_filter.py index f77d6dad3..7387cb363 100644 --- a/nova/scheduler/filters/json_filter.py +++ b/nova/scheduler/filters/json_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/num_instances_filter.py b/nova/scheduler/filters/num_instances_filter.py index f65fccbf6..06b5b5b73 100644 --- a/nova/scheduler/filters/num_instances_filter.py +++ b/nova/scheduler/filters/num_instances_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/ram_filter.py b/nova/scheduler/filters/ram_filter.py index 3345bf386..fdf189735 100644 --- a/nova/scheduler/filters/ram_filter.py +++ b/nova/scheduler/filters/ram_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # Copyright (c) 2012 Cloudscaling # All Rights Reserved. # diff --git a/nova/scheduler/filters/retry_filter.py b/nova/scheduler/filters/retry_filter.py index 4d6ed50ee..d49ad1c36 100644 --- a/nova/scheduler/filters/retry_filter.py +++ b/nova/scheduler/filters/retry_filter.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/filters/trusted_filter.py b/nova/scheduler/filters/trusted_filter.py index a7bb850bf..411ae93bd 100644 --- a/nova/scheduler/filters/trusted_filter.py +++ b/nova/scheduler/filters/trusted_filter.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 Intel, Inc. -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/host_manager.py b/nova/scheduler/host_manager.py index c004b2947..d12f15f38 100644 --- a/nova/scheduler/host_manager.py +++ b/nova/scheduler/host_manager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index a9b774a4d..11798ca04 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/nova/scheduler/multi.py b/nova/scheduler/multi.py index ec45ad618..2077fce5b 100644 --- a/nova/scheduler/multi.py +++ b/nova/scheduler/multi.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/nova/scheduler/scheduler_options.py b/nova/scheduler/scheduler_options.py index 1753c897b..f7aa91155 100644 --- a/nova/scheduler/scheduler_options.py +++ b/nova/scheduler/scheduler_options.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -28,6 +28,7 @@ import os from oslo.config import cfg +from nova.openstack.common import excutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils @@ -66,9 +67,9 @@ class SchedulerOptions(object): try: return os.path.getmtime(filename) except os.error, e: - LOG.exception(_("Could not stat scheduler options file " - "%(filename)s: '%(e)s'"), locals()) - raise + with excutils.save_and_reraise_exception(): + LOG.exception(_("Could not stat scheduler options file " + "%(filename)s: '%(e)s'"), locals()) def _load_file(self, handle): """Decode the JSON file. Broken out for testing.""" diff --git a/nova/scheduler/weights/__init__.py b/nova/scheduler/weights/__init__.py index f96ec929a..1a8a15c43 100644 --- a/nova/scheduler/weights/__init__.py +++ b/nova/scheduler/weights/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/weights/least_cost.py b/nova/scheduler/weights/least_cost.py index 0e617ff42..d3e04f47e 100644 --- a/nova/scheduler/weights/least_cost.py +++ b/nova/scheduler/weights/least_cost.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/scheduler/weights/ram.py b/nova/scheduler/weights/ram.py index 3fc15fbdf..b8478c7bd 100644 --- a/nova/scheduler/weights/ram.py +++ b/nova/scheduler/weights/ram.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/servicegroup/__init__.py b/nova/servicegroup/__init__.py index a804c62fa..02a808a14 100644 --- a/nova/servicegroup/__init__.py +++ b/nova/servicegroup/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) IBM 2012 Pavel Kravchenco <kpavel at il dot ibm dot com> +# Copyright 2012 IBM Corp. # Copyright (c) AT&T Labs Inc. 2012 Yun Mao <yunmao@gmail.com> # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/servicegroup/api.py b/nova/servicegroup/api.py index 2701329a0..902d4b640 100644 --- a/nova/servicegroup/api.py +++ b/nova/servicegroup/api.py @@ -1,5 +1,4 @@ -# Copyright (c) IBM 2012 Pavel Kravchenco <kpavel at il dot ibm dot com> -# Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # Copyright (c) AT&T Labs Inc. 2012 Yun Mao <yunmao@gmail.com> # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/servicegroup/drivers/db.py b/nova/servicegroup/drivers/db.py index 994015b34..aa29596db 100644 --- a/nova/servicegroup/drivers/db.py +++ b/nova/servicegroup/drivers/db.py @@ -1,5 +1,4 @@ -# Copyright (c) IBM 2012 Pavel Kravchenco <kpavel at il dot ibm dot com> -# Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/nova/servicegroup/drivers/mc.py b/nova/servicegroup/drivers/mc.py index 2857185d9..0801138ff 100644 --- a/nova/servicegroup/drivers/mc.py +++ b/nova/servicegroup/drivers/mc.py @@ -2,8 +2,7 @@ # Copyright (c) 2013 Akira Yoshiyama <akirayoshiyama at gmail dot com> # # This is derived from nova/servicegroup/drivers/db.py. -# Copyright (c) IBM 2012 Pavel Kravchenco <kpavel at il dot ibm dot com> -# Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -20,10 +19,10 @@ from oslo.config import cfg -from nova.common import memorycache from nova import conductor from nova import context from nova.openstack.common import log as logging +from nova.openstack.common import memorycache from nova.openstack.common import timeutils from nova.servicegroup import api from nova import utils @@ -31,7 +30,7 @@ from nova import utils CONF = cfg.CONF CONF.import_opt('service_down_time', 'nova.service') -CONF.import_opt('memcached_servers', 'nova.common.memorycache') +CONF.import_opt('memcached_servers', 'nova.openstack.common.memorycache') LOG = logging.getLogger(__name__) diff --git a/nova/servicegroup/drivers/zk.py b/nova/servicegroup/drivers/zk.py index 92b49f274..4326ef444 100644 --- a/nova/servicegroup/drivers/zk.py +++ b/nova/servicegroup/drivers/zk.py @@ -1,7 +1,5 @@ # Copyright (c) AT&T 2012-2013 Yun Mao <yunmao@gmail.com> -# -# Copyright (c) IBM 2012 Pavel Kravchenco <kpavel at il dot ibm dot com> -# Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,16 +17,17 @@ import os import eventlet -import evzookeeper -from evzookeeper import membership from oslo.config import cfg -import zookeeper from nova import exception +from nova.openstack.common import importutils from nova.openstack.common import log as logging from nova.servicegroup import api from nova import utils +evzookeeper = importutils.try_import('evzookeeper') +membership = importutils.try_import('evzookeeper.membersip') +zookeeper = importutils.try_import('zookeeper') zk_driver_opts = [ cfg.StrOpt('address', @@ -58,16 +57,18 @@ class ZooKeeperDriver(api.ServiceGroupDriver): def __init__(self, *args, **kwargs): """Create the zk session object.""" + if not all([evzookeeper, membership, zookeeper]): + raise ImportError('zookeeper module not found') null = open(os.devnull, "w") - self._session = evzookeeper.ZKSession(CONF.zk.address, + self._session = evzookeeper.ZKSession(CONF.zookeeper.address, recv_timeout= - CONF.zk.recv_timeout, + CONF.zookeeper.recv_timeout, zklog_fd=null) self._memberships = {} self._monitors = {} # Make sure the prefix exists try: - self._session.create(CONF.zk.sg_prefix, "", + self._session.create(CONF.zookeeper.sg_prefix, "", acl=[evzookeeper.ZOO_OPEN_ACL_UNSAFE]) except zookeeper.NodeExistsException: pass @@ -82,7 +83,7 @@ class ZooKeeperDriver(api.ServiceGroupDriver): member = self._memberships.get((group, member_id), None) if member is None: # the first time to join. Generate a new object - path = "%s/%s" % (CONF.zk.sg_prefix, group) + path = "%s/%s" % (CONF.zookeeper.sg_prefix, group) try: member = membership.Membership(self._session, path, member_id) except RuntimeError: @@ -90,7 +91,7 @@ class ZooKeeperDriver(api.ServiceGroupDriver): "another node exists with the same name, or " "this node just restarted. We will try " "again in a short while to make sure.")) - eventlet.sleep(CONF.zk.sg_retry_interval) + eventlet.sleep(CONF.zookeeper.sg_retry_interval) member = membership.Membership(self._session, path, member_id) self._memberships[(group, member_id)] = member return FakeLoopingCall(self, member_id, group) @@ -120,7 +121,7 @@ class ZooKeeperDriver(api.ServiceGroupDriver): """ monitor = self._monitors.get(group_id, None) if monitor is None: - path = "%s/%s" % (CONF.zk.sg_prefix, group_id) + path = "%s/%s" % (CONF.zookeeper.sg_prefix, group_id) monitor = membership.MembershipMonitor(self._session, path) self._monitors[group_id] = monitor # Note(maoy): When initialized for the first time, it takes a diff --git a/nova/tests/api/__init__.py b/nova/tests/api/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/api/__init__.py +++ b/nova/tests/api/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/ec2/__init__.py b/nova/tests/api/ec2/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/api/ec2/__init__.py +++ b/nova/tests/api/ec2/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/ec2/test_cloud.py b/nova/tests/api/ec2/test_cloud.py index 07780eb02..2ba8cfc60 100644 --- a/nova/tests/api/ec2/test_cloud.py +++ b/nova/tests/api/ec2/test_cloud.py @@ -41,9 +41,12 @@ from nova import db from nova import exception from nova.image import s3 from nova.network import api as network_api +from nova.network import quantumv2 from nova.openstack.common import log as logging from nova.openstack.common import rpc from nova import test +from nova.tests.api.openstack.compute.contrib import ( + test_quantum_security_groups as test_quantum) from nova.tests import fake_network from nova.tests.image import fake from nova.tests import matchers @@ -1904,34 +1907,15 @@ class CloudTestCase(test.TestCase): self.stubs.Set(fake._FakeImageService, 'show', fake_show) def fake_block_device_mapping_get_all_by_instance(context, inst_id): - class BDM(object): - def __init__(self): - self.no_device = None - self.values = dict(id=1, - snapshot_id=snapshots[0], - volume_id=volumes[0], - virtual_name=None, - volume_size=1, - device_name='sda1', - delete_on_termination=False, - connection_info='{"foo":"bar"}') - - def __getattr__(self, name): - """Properly delegate dotted lookups.""" - if name in self.__dict__['values']: - return self.values.get(name) - try: - return self.__dict__[name] - except KeyError: - raise AttributeError - - def __getitem__(self, key): - return self.values.get(key) - - def iteritems(self): - return self.values.iteritems() - - return [BDM()] + return [dict(id=1, + snapshot_id=snapshots[0], + volume_id=volumes[0], + virtual_name=None, + volume_size=1, + device_name='sda1', + delete_on_termination=False, + no_device=None, + connection_info='{"foo":"bar"}')] self.stubs.Set(db, 'block_device_mapping_get_all_by_instance', fake_block_device_mapping_get_all_by_instance) @@ -1995,32 +1979,13 @@ class CloudTestCase(test.TestCase): ec2_instance_id = self._run_instance(**kwargs) def fake_block_device_mapping_get_all_by_instance(context, inst_id): - class BDM(object): - def __init__(self): - self.no_device = None - self.values = dict(snapshot_id=snapshots[0], - volume_id=volumes[0], - virtual_name=None, - volume_size=1, - device_name='vda', - delete_on_termination=False) - - def __getattr__(self, name): - """Properly delegate dotted lookups.""" - if name in self.__dict__['values']: - return self.values.get(name) - try: - return self.__dict__[name] - except KeyError: - raise AttributeError - - def __getitem__(self, key): - return self.values.get(key) - - def iteritems(self): - return self.values.iteritems() - - return [BDM()] + return [dict(snapshot_id=snapshots[0], + volume_id=volumes[0], + virtual_name=None, + volume_size=1, + device_name='vda', + delete_on_termination=False, + no_device=None)] self.stubs.Set(db, 'block_device_mapping_get_all_by_instance', fake_block_device_mapping_get_all_by_instance) @@ -2226,3 +2191,66 @@ class CloudTestCase(test.TestCase): test_dia_iisb('stop', image_id='ami-4') test_dia_iisb('stop', image_id='ami-5') test_dia_iisb('stop', image_id='ami-6') + + +class CloudTestCaseQuantumProxy(test.TestCase): + def setUp(self): + cfg.CONF.set_override('security_group_api', 'quantum') + self.cloud = cloud.CloudController() + self.original_client = quantumv2.get_client + quantumv2.get_client = test_quantum.get_client + self.user_id = 'fake' + self.project_id = 'fake' + self.context = context.RequestContext(self.user_id, + self.project_id, + is_admin=True) + super(CloudTestCaseQuantumProxy, self).setUp() + + def tearDown(self): + quantumv2.get_client = self.original_client + test_quantum.get_client()._reset() + super(CloudTestCaseQuantumProxy, self).tearDown() + + def test_describe_security_groups(self): + # Makes sure describe_security_groups works and filters results. + group_name = 'test' + description = 'test' + self.cloud.create_security_group(self.context, group_name, + description) + result = self.cloud.describe_security_groups(self.context) + # NOTE(vish): should have the default group as well + self.assertEqual(len(result['securityGroupInfo']), 2) + result = self.cloud.describe_security_groups(self.context, + group_name=[group_name]) + self.assertEqual(len(result['securityGroupInfo']), 1) + self.assertEqual(result['securityGroupInfo'][0]['groupName'], + group_name) + self.cloud.delete_security_group(self.context, group_name) + + def test_describe_security_groups_by_id(self): + group_name = 'test' + description = 'test' + self.cloud.create_security_group(self.context, group_name, + description) + quantum = test_quantum.get_client() + # Get id from quantum since cloud.create_security_group + # does not expose it. + search_opts = {'name': group_name} + groups = quantum.list_security_groups( + **search_opts)['security_groups'] + result = self.cloud.describe_security_groups(self.context, + group_id=[groups[0]['id']]) + self.assertEqual(len(result['securityGroupInfo']), 1) + self.assertEqual( + result['securityGroupInfo'][0]['groupName'], + group_name) + self.cloud.delete_security_group(self.context, group_name) + + def test_create_delete_security_group(self): + descript = 'test description' + create = self.cloud.create_security_group + result = create(self.context, 'testgrp', descript) + group_descript = result['securityGroupSet'][0]['groupDescription'] + self.assertEqual(descript, group_descript) + delete = self.cloud.delete_security_group + self.assertTrue(delete(self.context, 'testgrp')) diff --git a/nova/tests/api/openstack/__init__.py b/nova/tests/api/openstack/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/api/openstack/__init__.py +++ b/nova/tests/api/openstack/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/common.py b/nova/tests/api/openstack/common.py index 1e4adf574..468bc5626 100644 --- a/nova/tests/api/openstack/common.py +++ b/nova/tests/api/openstack/common.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/__init__.py b/nova/tests/api/openstack/compute/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/api/openstack/compute/__init__.py +++ b/nova/tests/api/openstack/compute/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/__init__.py b/nova/tests/api/openstack/compute/contrib/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/api/openstack/compute/contrib/__init__.py +++ b/nova/tests/api/openstack/compute/contrib/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py index 600d25889..bb3cbf086 100644 --- a/nova/tests/api/openstack/compute/contrib/test_admin_actions.py +++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py b/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py index 4e577e1f5..1e88d8047 100644 --- a/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py +++ b/nova/tests/api/openstack/compute/contrib/test_admin_actions_with_cells.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 Openstack, LLC. +# Copyright (c) 2012 Openstack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_agents.py b/nova/tests/api/openstack/compute/contrib/test_agents.py index 60659b3c6..0250b9ac5 100644 --- a/nova/tests/api/openstack/compute/contrib/test_agents.py +++ b/nova/tests/api/openstack/compute/contrib/test_agents.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -99,9 +98,6 @@ class AgentsTest(test.TestCase): self.context = context.get_admin_context() self.controller = agents.AgentController() - def tearDown(self): - super(AgentsTest, self).tearDown() - def test_agents_create(self): req = FakeRequest() body = {'agent': {'hypervisor': 'kvm', diff --git a/nova/tests/api/openstack/compute/contrib/test_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py index fb9a36ba9..cd4c616d7 100644 --- a/nova/tests/api/openstack/compute/contrib/test_availability_zone.py +++ b/nova/tests/api/openstack/compute/contrib/test_availability_zone.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/contrib/test_cells.py b/nova/tests/api/openstack/compute/contrib/test_cells.py index 82d469524..89ce4cd5a 100644 --- a/nova/tests/api/openstack/compute/contrib/test_cells.py +++ b/nova/tests/api/openstack/compute/contrib/test_cells.py @@ -1,4 +1,4 @@ -# Copyright 2011-2012 OpenStack LLC. +# Copyright 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_certificates.py b/nova/tests/api/openstack/compute/contrib/test_certificates.py index 9c9625e8e..df5a7e9a1 100644 --- a/nova/tests/api/openstack/compute/contrib/test_certificates.py +++ b/nova/tests/api/openstack/compute/contrib/test_certificates.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py index 40b4e6d93..83dca7a95 100644 --- a/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py +++ b/nova/tests/api/openstack/compute/contrib/test_cloudpipe.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_cloudpipe_update.py b/nova/tests/api/openstack/compute/contrib/test_cloudpipe_update.py index 8068776de..d0f54edcb 100644 --- a/nova/tests/api/openstack/compute/contrib/test_cloudpipe_update.py +++ b/nova/tests/api/openstack/compute/contrib/test_cloudpipe_update.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/contrib/test_config_drive.py b/nova/tests/api/openstack/compute/contrib/test_config_drive.py index e9d23f664..235b9373b 100644 --- a/nova/tests/api/openstack/compute/contrib/test_config_drive.py +++ b/nova/tests/api/openstack/compute/contrib/test_config_drive.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_consoles.py b/nova/tests/api/openstack/compute/contrib/test_consoles.py index cf044dfcd..505f0c1fe 100644 --- a/nova/tests/api/openstack/compute/contrib/test_consoles.py +++ b/nova/tests/api/openstack/compute/contrib/test_consoles.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py b/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py index 66a8a8f82..6d66f8d74 100644 --- a/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py +++ b/nova/tests/api/openstack/compute/contrib/test_coverage_ext.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -34,12 +34,27 @@ def fake_check_coverage(self): return False -def fake_xml_report(self, outfile): - return +class FakeCoverage(object): + def __init__(self, data_file=None): + self.started = False + return super(FakeCoverage, self).__init__() + def save(self): + pass -def fake_report(self, file): - return + def start(self): + self.started = True + + def stop(self): + if not self.started: + raise AssertionError + self.started = False + + def report(self, file): + pass + + def xml_report(self, outfile): + pass class CoverageExtensionTest(test.TestCase): @@ -48,8 +63,7 @@ class CoverageExtensionTest(test.TestCase): super(CoverageExtensionTest, self).setUp() self.stubs.Set(telnetlib.Telnet, 'write', fake_telnet) self.stubs.Set(telnetlib.Telnet, 'expect', fake_telnet) - self.stubs.Set(coverage.coverage, 'report', fake_report) - self.stubs.Set(coverage.coverage, 'xml_report', fake_xml_report) + self.stubs.Set(coverage, 'coverage', FakeCoverage) self.admin_context = context.RequestContext('fakeadmin_0', 'fake', is_admin=True) diff --git a/nova/tests/api/openstack/compute/contrib/test_createserverext.py b/nova/tests/api/openstack/compute/contrib/test_createserverext.py index 9ec866172..7ee05516f 100644 --- a/nova/tests/api/openstack/compute/contrib/test_createserverext.py +++ b/nova/tests/api/openstack/compute/contrib/test_createserverext.py @@ -1,6 +1,6 @@ # vim: tabstop=5 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py b/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py index eba4154e2..4fd44bcd7 100644 --- a/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py +++ b/nova/tests/api/openstack/compute/contrib/test_deferred_delete.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_disk_config.py b/nova/tests/api/openstack/compute/contrib/test_disk_config.py index 9434ba821..278be0580 100644 --- a/nova/tests/api/openstack/compute/contrib/test_disk_config.py +++ b/nova/tests/api/openstack/compute/contrib/test_disk_config.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_evacuate.py b/nova/tests/api/openstack/compute/contrib/test_evacuate.py index 9411b5663..fad89db02 100644 --- a/nova/tests/api/openstack/compute/contrib/test_evacuate.py +++ b/nova/tests/api/openstack/compute/contrib/test_evacuate.py @@ -1,4 +1,4 @@ -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py index d847e54f9..814c0fff4 100644 --- a/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py +++ b/nova/tests/api/openstack/compute/contrib/test_extended_availability_zone.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_server_attributes.py b/nova/tests/api/openstack/compute/contrib/test_extended_server_attributes.py index 63e1b6126..ff5ab7ac5 100644 --- a/nova/tests/api/openstack/compute/contrib/test_extended_server_attributes.py +++ b/nova/tests/api/openstack/compute/contrib/test_extended_server_attributes.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_extended_status.py b/nova/tests/api/openstack/compute/contrib/test_extended_status.py index e368c5986..f219b97bd 100644 --- a/nova/tests/api/openstack/compute/contrib/test_extended_status.py +++ b/nova/tests/api/openstack/compute/contrib/test_extended_status.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py b/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py index 6b6fb8286..818bc3dff 100644 --- a/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py +++ b/nova/tests/api/openstack/compute/contrib/test_fixed_ips.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -107,9 +106,6 @@ class FixedIpTest(test.TestCase): self.context = context.get_admin_context() self.controller = fixed_ips.FixedIPController() - def tearDown(self): - super(FixedIpTest, self).tearDown() - def test_fixed_ips_get(self): req = fakes.HTTPRequest.blank('/v2/fake/os-fixed-ips/192.168.1.1') res_dict = self.controller.show(req, '192.168.1.1') 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 1475edc0a..fc5543409 100644 --- a/nova/tests/api/openstack/compute/contrib/test_flavor_access.py +++ b/nova/tests/api/openstack/compute/contrib/test_flavor_access.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py b/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py index 9b815489e..1c5703381 100644 --- a/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py +++ b/nova/tests/api/openstack/compute/contrib/test_flavorextradata.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py b/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py index a36bb32cf..5521eddb1 100644 --- a/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py +++ b/nova/tests/api/openstack/compute/contrib/test_floating_ip_bulk.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -33,9 +32,6 @@ class FloatingIPBulk(test.TestCase): self.context = context.get_admin_context() self.controller = floating_ips_bulk.FloatingIPBulkController() - def tearDown(self): - super(FloatingIPBulk, self).tearDown() - def _setup_floating_ips(self, ip_range): body = {'floating_ips_bulk_create': {'ip_range': ip_range}} req = fakes.HTTPRequest.blank('/v2/fake/os-floating-ips-bulk') diff --git a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py index 864ab7a9f..00759a7ef 100644 --- a/nova/tests/api/openstack/compute/contrib/test_floating_ips.py +++ b/nova/tests/api/openstack/compute/contrib/test_floating_ips.py @@ -364,8 +364,9 @@ class FloatingIpTest(test.TestCase): body = dict(removeFloatingIp=dict(address='10.10.10.10')) req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action') - rsp = self.manager._remove_floating_ip(req, 'test_inst', body) - self.assertTrue(rsp.status_int == 404) + self.assertRaises(webob.exc.HTTPUnprocessableEntity, + self.manager._remove_floating_ip, + req, 'test_inst', body) def test_floating_ip_associate_non_existent_ip(self): def fake_network_api_associate(self, context, instance, @@ -414,8 +415,9 @@ class FloatingIpTest(test.TestCase): body = dict(removeFloatingIp=dict(address='10.10.10.10')) req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action') - rsp = self.manager._remove_floating_ip(req, wrong_uuid, body) - self.assertTrue(rsp.status_int == 404) + self.assertRaises(webob.exc.HTTPUnprocessableEntity, + self.manager._remove_floating_ip, + req, wrong_uuid, body) def test_floating_ip_disassociate_wrong_instance_id(self): def get_instance_by_floating_ip_addr(self, context, address): @@ -428,8 +430,9 @@ class FloatingIpTest(test.TestCase): body = dict(removeFloatingIp=dict(address='10.10.10.10')) req = fakes.HTTPRequest.blank('/v2/fake/servers/test_inst/action') - rsp = self.manager._remove_floating_ip(req, 'test_inst', body) - self.assertTrue(rsp.status_int == 404) + self.assertRaises(webob.exc.HTTPUnprocessableEntity, + self.manager._remove_floating_ip, + req, 'test_inst', body) def test_floating_ip_disassociate_auto_assigned(self): def fake_get_floating_ip_addr_auto_assigned(self, context, address): diff --git a/nova/tests/api/openstack/compute/contrib/test_fping.py b/nova/tests/api/openstack/compute/contrib/test_fping.py index 1a1e3214e..cdeb0a280 100644 --- a/nova/tests/api/openstack/compute/contrib/test_fping.py +++ b/nova/tests/api/openstack/compute/contrib/test_fping.py @@ -1,5 +1,5 @@ # Copyright 2011 Grid Dynamics -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_hide_server_addresses.py b/nova/tests/api/openstack/compute/contrib/test_hide_server_addresses.py index 804decdff..f77869947 100644 --- a/nova/tests/api/openstack/compute/contrib/test_hide_server_addresses.py +++ b/nova/tests/api/openstack/compute/contrib/test_hide_server_addresses.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_hosts.py b/nova/tests/api/openstack/compute/contrib/test_hosts.py index e103b5b19..85f93a9d5 100644 --- a/nova/tests/api/openstack/compute/contrib/test_hosts.py +++ b/nova/tests/api/openstack/compute/contrib/test_hosts.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC. +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_hypervisors.py b/nova/tests/api/openstack/compute/contrib/test_hypervisors.py index f93c64487..e323dce6a 100644 --- a/nova/tests/api/openstack/compute/contrib/test_hypervisors.py +++ b/nova/tests/api/openstack/compute/contrib/test_hypervisors.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_instance_usage_audit_log.py b/nova/tests/api/openstack/compute/contrib/test_instance_usage_audit_log.py index 920fd86d5..2b2fd1131 100644 --- a/nova/tests/api/openstack/compute/contrib/test_instance_usage_audit_log.py +++ b/nova/tests/api/openstack/compute/contrib/test_instance_usage_audit_log.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_keypairs.py b/nova/tests/api/openstack/compute/contrib/test_keypairs.py index 06454b123..025845637 100644 --- a/nova/tests/api/openstack/compute/contrib/test_keypairs.py +++ b/nova/tests/api/openstack/compute/contrib/test_keypairs.py @@ -236,6 +236,11 @@ class KeypairsTest(test.TestCase): res = req.get_response(self.app) self.assertEqual(res.status_int, 202) + def test_keypair_get_keypair_not_found(self): + req = webob.Request.blank('/v2/fake/os-keypairs/DOESNOTEXIST') + res = req.get_response(self.app) + self.assertEqual(res.status_int, 404) + def test_keypair_delete_not_found(self): def db_key_pair_get_not_found(context, user_id, name): diff --git a/nova/tests/api/openstack/compute/contrib/test_multinic_xs.py b/nova/tests/api/openstack/compute/contrib/test_multinic_xs.py index bf9eebc6b..dc3c21d99 100644 --- a/nova/tests/api/openstack/compute/contrib/test_multinic_xs.py +++ b/nova/tests/api/openstack/compute/contrib/test_multinic_xs.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_networks.py b/nova/tests/api/openstack/compute/contrib/test_networks.py index fef60f20b..8238f9248 100644 --- a/nova/tests/api/openstack/compute/contrib/test_networks.py +++ b/nova/tests/api/openstack/compute/contrib/test_networks.py @@ -1,5 +1,5 @@ # Copyright 2011 Grid Dynamics -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may 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 e32fadbb8..a413babdf 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 @@ -237,6 +237,7 @@ class TestQuantumSecurityGroupRulesTestCase(TestQuantumSecurityGroupsTestCase): id2 = '22222222-2222-2222-2222-222222222222' sg_template2 = test_security_groups.security_group_template( security_group_rules=[], id=id2) + self.controller_sg = security_groups.SecurityGroupController() quantum = get_client() quantum._fake_security_groups[id1] = sg_template1 quantum._fake_security_groups[id2] = sg_template2 @@ -252,12 +253,26 @@ class TestQuantumSecurityGroupRules( TestQuantumSecurityGroupRulesTestCase): def test_create_add_existing_rules_by_cidr(self): - # Enforced by quantum - pass + sg = test_security_groups.security_group_template() + req = fakes.HTTPRequest.blank('/v2/fake/os-security-groups') + self.controller_sg.create(req, {'security_group': sg}) + rule = test_security_groups.security_group_rule_template( + cidr='15.0.0.0/8', parent_group_id=self.sg2['id']) + req = fakes.HTTPRequest.blank('/v2/fake/os-security-group-rules') + self.controller.create(req, {'security_group_rule': rule}) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, {'security_group_rule': rule}) def test_create_add_existing_rules_by_group_id(self): - # Enforced by quantum - pass + sg = test_security_groups.security_group_template() + req = fakes.HTTPRequest.blank('/v2/fake/os-security-groups') + self.controller_sg.create(req, {'security_group': sg}) + rule = test_security_groups.security_group_rule_template( + group=self.sg1['id'], parent_group_id=self.sg2['id']) + req = fakes.HTTPRequest.blank('/v2/fake/os-security-group-rules') + self.controller.create(req, {'security_group_rule': rule}) + self.assertRaises(webob.exc.HTTPBadRequest, self.controller.create, + req, {'security_group_rule': rule}) def test_delete(self): rule = test_security_groups.security_group_rule_template( @@ -517,8 +532,8 @@ class MockClient(object): # does not handle bulk case so just picks rule[0] r = body.get('security_group_rules')[0] fields = ['direction', 'protocol', 'port_range_min', 'port_range_max', - 'ethertype', 'source_ip_prefix', 'tenant_id', - 'security_group_id', 'source_group_id'] + 'ethertype', 'remote_ip_prefix', 'tenant_id', + 'security_group_id', 'remote_group_id'] ret = {} for field in fields: ret[field] = r.get(field) @@ -528,11 +543,15 @@ class MockClient(object): def show_security_group(self, security_group, **_params): try: - return {'security_group': - self._fake_security_groups[security_group]} + sg = self._fake_security_groups[security_group] except KeyError: msg = 'Security Group %s not found' % security_group raise q_exc.QuantumClientException(message=msg, status_code=404) + for security_group_rule in self._fake_security_group_rules.values(): + if security_group_rule['security_group_id'] == sg['id']: + sg['security_group_rules'].append(security_group_rule) + + return {'security_group': sg} def show_security_group_rule(self, security_group_rule, **_params): try: @@ -569,10 +588,21 @@ class MockClient(object): def list_security_groups(self, **_params): ret = [] for security_group in self._fake_security_groups.values(): - if _params.get('name'): - if security_group.get('name') == _params['name']: - ret.append(security_group) - else: + names = _params.get('name') + if names: + if not isinstance(names, list): + names = [names] + for name in names: + if security_group.get('name') == name: + ret.append(security_group) + ids = _params.get('id') + if ids: + if not isinstance(ids, list): + ids = [ids] + for id in ids: + if security_group.get('id') == id: + ret.append(security_group) + elif not (names or ids): ret.append(security_group) return {'security_groups': ret} 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 0c1378a67..7b0b62180 100644 --- a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py +++ b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py index 6636824fd..0616c4628 100644 --- a/nova/tests/api/openstack/compute/contrib/test_quotas.py +++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_rescue.py b/nova/tests/api/openstack/compute/contrib/test_rescue.py index 359eafb2a..0d2e9e5c8 100644 --- a/nova/tests/api/openstack/compute/contrib/test_rescue.py +++ b/nova/tests/api/openstack/compute/contrib/test_rescue.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py b/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py index 732abaad5..9b91ef2c5 100644 --- a/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py +++ b/nova/tests/api/openstack/compute/contrib/test_scheduler_hints.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may 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 5058f17ac..4919d461f 100644 --- a/nova/tests/api/openstack/compute/contrib/test_security_groups.py +++ b/nova/tests/api/openstack/compute/contrib/test_security_groups.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Copyright 2012 Justin Santa Barbara # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_services.py b/nova/tests/api/openstack/compute/contrib/test_services.py index aba1b92c1..d4bf62d19 100644 --- a/nova/tests/api/openstack/compute/contrib/test_services.py +++ b/nova/tests/api/openstack/compute/contrib/test_services.py @@ -1,5 +1,4 @@ -# Copyright 2012 IBM -# All Rights Reserved. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -122,9 +121,6 @@ class ServicesTest(test.TestCase): self.context = context.get_admin_context() self.controller = services.ServiceController() - def tearDown(self): - super(ServicesTest, self).tearDown() - def test_services_list(self): req = FakeRequest() res_dict = self.controller.index(req) diff --git a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py index ef4aacae8..4c59e5aa9 100644 --- a/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py +++ b/nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/contrib/test_used_limits.py b/nova/tests/api/openstack/compute/contrib/test_used_limits.py index ce2322bfe..ebe3e852d 100644 --- a/nova/tests/api/openstack/compute/contrib/test_used_limits.py +++ b/nova/tests/api/openstack/compute/contrib/test_used_limits.py @@ -1,6 +1,6 @@ # vim: tabstop=5 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/extensions/__init__.py b/nova/tests/api/openstack/compute/extensions/__init__.py index 848908a95..4ac574e58 100644 --- a/nova/tests/api/openstack/compute/extensions/__init__.py +++ b/nova/tests/api/openstack/compute/extensions/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/openstack/compute/extensions/foxinsocks.py b/nova/tests/api/openstack/compute/extensions/foxinsocks.py index fdc612047..3b232f327 100644 --- a/nova/tests/api/openstack/compute/extensions/foxinsocks.py +++ b/nova/tests/api/openstack/compute/extensions/foxinsocks.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_api.py b/nova/tests/api/openstack/compute/test_api.py index 782f1a344..9061fd397 100644 --- a/nova/tests/api/openstack/compute/test_api.py +++ b/nova/tests/api/openstack/compute/test_api.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_auth.py b/nova/tests/api/openstack/compute/test_auth.py index 21ef2a162..0aca45573 100644 --- a/nova/tests/api/openstack/compute/test_auth.py +++ b/nova/tests/api/openstack/compute/test_auth.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_consoles.py b/nova/tests/api/openstack/compute/test_consoles.py index 8f0a02e30..134fb0639 100644 --- a/nova/tests/api/openstack/compute/test_consoles.py +++ b/nova/tests/api/openstack/compute/test_consoles.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # diff --git a/nova/tests/api/openstack/compute/test_extensions.py b/nova/tests/api/openstack/compute/test_extensions.py index 68e5e1b99..dcc2c9b3d 100644 --- a/nova/tests/api/openstack/compute/test_extensions.py +++ b/nova/tests/api/openstack/compute/test_extensions.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_flavors.py b/nova/tests/api/openstack/compute/test_flavors.py index 947a2e294..3a11c92fe 100644 --- a/nova/tests/api/openstack/compute/test_flavors.py +++ b/nova/tests/api/openstack/compute/test_flavors.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_image_metadata.py b/nova/tests/api/openstack/compute/test_image_metadata.py index 29165b548..1330bc202 100644 --- a/nova/tests/api/openstack/compute/test_image_metadata.py +++ b/nova/tests/api/openstack/compute/test_image_metadata.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_images.py b/nova/tests/api/openstack/compute/test_images.py index 09e727da3..db0ad51f7 100644 --- a/nova/tests/api/openstack/compute/test_images.py +++ b/nova/tests/api/openstack/compute/test_images.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py index e3fff380d..70c37e745 100644 --- a/nova/tests/api/openstack/compute/test_limits.py +++ b/nova/tests/api/openstack/compute/test_limits.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_server_actions.py b/nova/tests/api/openstack/compute/test_server_actions.py index 101458bf3..62a688962 100644 --- a/nova/tests/api/openstack/compute/test_server_actions.py +++ b/nova/tests/api/openstack/compute/test_server_actions.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -784,32 +784,13 @@ class ServerActionsControllerTest(test.TestCase): image_service.create(None, original_image) def fake_block_device_mapping_get_all_by_instance(context, inst_id): - class BDM(object): - def __init__(self): - self.no_device = None - self.values = dict(volume_id=_fake_id('a'), - virtual_name=None, - volume_size=1, - device_name='vda', - snapshot_id=1, - delete_on_termination=False) - - def __getattr__(self, name): - """Properly delegate dotted lookups.""" - if name in self.__dict__['values']: - return self.values.get(name) - try: - return self.__dict__[name] - except KeyError: - raise AttributeError - - def __getitem__(self, key): - return self.values.get(key) - - def iteritems(self): - return self.values.iteritems() - - return [BDM()] + return [dict(volume_id=_fake_id('a'), + virtual_name=None, + volume_size=1, + device_name='vda', + snapshot_id=1, + delete_on_termination=False, + no_device=None)] self.stubs.Set(db, 'block_device_mapping_get_all_by_instance', fake_block_device_mapping_get_all_by_instance) diff --git a/nova/tests/api/openstack/compute/test_server_metadata.py b/nova/tests/api/openstack/compute/test_server_metadata.py index 3ba895953..fa25ad4a3 100644 --- a/nova/tests/api/openstack/compute/test_server_metadata.py +++ b/nova/tests/api/openstack/compute/test_server_metadata.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py index 228d81f45..638ef79b0 100644 --- a/nova/tests/api/openstack/compute/test_servers.py +++ b/nova/tests/api/openstack/compute/test_servers.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # Copyright 2011 Piston Cloud Computing, Inc. # All Rights Reserved. # @@ -71,19 +71,10 @@ def fake_gen_uuid(): return FAKE_UUID -def return_servers_by_reservation(context, reservation_id=""): - return [fakes.stub_instance(i + 1, - reservation_id=reservation_id) for i in xrange(5)] - - def return_servers_empty(context, *args, **kwargs): return [] -def return_servers_by_reservation_empty(context, reservation_id=""): - return [] - - def return_security_group(context, instance_id, security_group_id): pass @@ -539,9 +530,6 @@ class ServersControllerTest(test.TestCase): self.assertEqual(0, num_servers) def test_get_server_list_with_reservation_id(self): - self.stubs.Set(db, 'instance_get_all_by_reservation', - return_servers_by_reservation) - req = fakes.HTTPRequest.blank('/v2/fake/servers?reservation_id=foo') res_dict = self.controller.index(req) @@ -551,9 +539,6 @@ class ServersControllerTest(test.TestCase): i += 1 def test_get_server_list_with_reservation_id_empty(self): - self.stubs.Set(db, 'instance_get_all_by_reservation', - return_servers_by_reservation_empty) - req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?' 'reservation_id=foo') res_dict = self.controller.detail(req) @@ -564,9 +549,6 @@ class ServersControllerTest(test.TestCase): i += 1 def test_get_server_list_with_reservation_id_details(self): - self.stubs.Set(db, 'instance_get_all_by_reservation', - return_servers_by_reservation) - req = fakes.HTTPRequest.blank('/v2/fake/servers/detail?' 'reservation_id=foo') res_dict = self.controller.detail(req) @@ -2060,6 +2042,52 @@ class ServersControllerCreateTest(test.TestCase): self.assertRaises(webob.exc.HTTPBadRequest, self._test_create_extra, params, no_image=True) + def test_create_multiple_instance_with_non_integer_max_count(self): + self.ext_mgr.extensions = {'os-multiple-create': 'fake'} + image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'max_count': 2.5, + 'name': 'server_test', + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': {'hello': 'world', + 'open': 'stack'}, + 'personality': [] + } + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = jsonutils.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, req, body) + + def test_create_multiple_instance_with_non_integer_min_count(self): + self.ext_mgr.extensions = {'os-multiple-create': 'fake'} + image_href = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' + flavor_ref = 'http://localhost/123/flavors/3' + body = { + 'server': { + 'min_count': 2.5, + 'name': 'server_test', + 'imageRef': image_href, + 'flavorRef': flavor_ref, + 'metadata': {'hello': 'world', + 'open': 'stack'}, + 'personality': [] + } + } + + req = fakes.HTTPRequest.blank('/v2/fake/servers') + req.method = 'POST' + req.body = jsonutils.dumps(body) + req.headers["content-type"] = "application/json" + self.assertRaises(webob.exc.HTTPBadRequest, + self.controller.create, req, body) + def test_create_instance_image_ref_is_bookmark(self): image_uuid = '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6' image_href = 'http://localhost/fake/images/%s' % image_uuid @@ -2120,15 +2148,27 @@ class ServersControllerCreateTest(test.TestCase): def test_create_instance_with_security_group_enabled(self): self.ext_mgr.extensions = {'os-security-groups': 'fake'} group = 'foo' - params = {'security_groups': [{'name': group}]} old_create = compute_api.API.create + def sec_group_get(ctx, proj, name): + if name == group: + return True + else: + raise exception.SecurityGroupNotFoundForProject( + project_id=proj, security_group_id=name) + def create(*args, **kwargs): self.assertEqual(kwargs['security_group'], [group]) return old_create(*args, **kwargs) + self.stubs.Set(db, 'security_group_get_by_name', sec_group_get) + # negative test + self.assertRaises(webob.exc.HTTPBadRequest, + self._test_create_extra, + {'security_groups': [{'name': 'bogus'}]}) + # positive test - extra assert in create path self.stubs.Set(compute_api.API, 'create', create) - self._test_create_extra(params) + self._test_create_extra({'security_groups': [{'name': group}]}) def test_create_instance_with_security_group_disabled(self): group = 'foo' diff --git a/nova/tests/api/openstack/compute/test_urlmap.py b/nova/tests/api/openstack/compute/test_urlmap.py index 6367a8e5e..8cb98944c 100644 --- a/nova/tests/api/openstack/compute/test_urlmap.py +++ b/nova/tests/api/openstack/compute/test_urlmap.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/compute/test_versions.py b/nova/tests/api/openstack/compute/test_versions.py index bd2e9fa7b..973fd0105 100644 --- a/nova/tests/api/openstack/compute/test_versions.py +++ b/nova/tests/api/openstack/compute/test_versions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/fakes.py b/nova/tests/api/openstack/fakes.py index c906dae7f..1bc7b313e 100644 --- a/nova/tests/api/openstack/fakes.py +++ b/nova/tests/api/openstack/fakes.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -587,7 +587,7 @@ def stub_snapshot(id, **kwargs): 'volume_id': 12, 'status': 'available', 'volume_size': 100, - 'created_at': None, + 'created_at': timeutils.utcnow(), 'display_name': 'Default name', 'display_description': 'Default description', 'project_id': 'fake' diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py index 68a5f0bf4..227044572 100644 --- a/nova/tests/api/openstack/test_common.py +++ b/nova/tests/api/openstack/test_common.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/test_faults.py b/nova/tests/api/openstack/test_faults.py index a413f9c4d..1bdb9f8c6 100644 --- a/nova/tests/api/openstack/test_faults.py +++ b/nova/tests/api/openstack/test_faults.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/openstack/test_xmlutil.py b/nova/tests/api/openstack/test_xmlutil.py index 83382cb58..bd7f24233 100644 --- a/nova/tests/api/openstack/test_xmlutil.py +++ b/nova/tests/api/openstack/test_xmlutil.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/api/test_auth.py b/nova/tests/api/test_auth.py index 083e6c0e9..ed69474c8 100644 --- a/nova/tests/api/test_auth.py +++ b/nova/tests/api/test_auth.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/test_sizelimit.py b/nova/tests/api/test_sizelimit.py index 9e7a33d29..f5735f287 100644 --- a/nova/tests/api/test_sizelimit.py +++ b/nova/tests/api/test_sizelimit.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/api/test_validator.py b/nova/tests/api/test_validator.py index 132e67e95..93a7deb66 100644 --- a/nova/tests/api/test_validator.py +++ b/nova/tests/api/test_validator.py @@ -73,14 +73,6 @@ class ValidatorTestCase(test.TestCase): self.assertFalse(validator.validate_ec2_id(1234)) self.assertTrue(validator.validate_ec2_id('i-284f3a41')) - def test_validate_ipv4(self): - self.assertTrue(validator.validate_ipv4('4.2.2.4')) - self.assertFalse(validator.validate_ipv4('foobar')) - self.assertFalse( - validator.validate_ipv4('2001:5a8:4:68e0:e6ce:8fff:fe27:d116')) - self.assertFalse(validator.validate_ipv4(123)) - self.assertFalse(validator.validate_ipv4('')) - def test_validate_url_path(self): self.assertTrue(validator.validate_url_path('/path/to/file')) self.assertFalse(validator.validate_url_path('path/to/file')) diff --git a/nova/tests/api/test_wsgi.py b/nova/tests/api/test_wsgi.py index 6504e664d..210bf6cf6 100644 --- a/nova/tests/api/test_wsgi.py +++ b/nova/tests/api/test_wsgi.py @@ -2,7 +2,7 @@ # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/baremetal/db/test_bm_interface.py b/nova/tests/baremetal/db/test_bm_interface.py index 32beb1ce0..e870ec5e0 100644 --- a/nova/tests/baremetal/db/test_bm_interface.py +++ b/nova/tests/baremetal/db/test_bm_interface.py @@ -18,7 +18,7 @@ Bare-metal DB testcase for BareMetalInterface """ from nova import exception -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.tests.baremetal.db import base from nova.virt.baremetal import db @@ -28,7 +28,7 @@ class BareMetalInterfaceTestCase(base.BMDBTestCase): def test_unique_address(self): pif1_id = db.bm_interface_create(self.context, 1, '11:11:11:11:11:11', '0x1', 1) - self.assertRaises(db_session.DBError, + self.assertRaises(db_exc.DBError, db.bm_interface_create, self.context, 2, '11:11:11:11:11:11', '0x2', 2) # succeed after delete pif1 diff --git a/nova/tests/baremetal/db/test_bm_pxe_ip.py b/nova/tests/baremetal/db/test_bm_pxe_ip.py index 9820f3af0..fe8ba5b3e 100644 --- a/nova/tests/baremetal/db/test_bm_pxe_ip.py +++ b/nova/tests/baremetal/db/test_bm_pxe_ip.py @@ -18,7 +18,7 @@ Bare-metal DB testcase for BareMetalPxeIp """ from nova import exception -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.tests.baremetal.db import base from nova.tests.baremetal.db import utils from nova.virt.baremetal import db @@ -51,14 +51,14 @@ class BareMetalPxeIpTestCase(base.BMDBTestCase): # address duplicates i = utils.new_bm_pxe_ip(address='10.1.1.1', server_address='10.1.1.201') - self.assertRaises(db_session.DBError, + self.assertRaises(db_exc.DBError, db.bm_pxe_ip_create_direct, self.context, i) # server_address duplicates i = utils.new_bm_pxe_ip(address='10.1.1.3', server_address='10.1.1.101') - self.assertRaises(db_session.DBError, + self.assertRaises(db_exc.DBError, db.bm_pxe_ip_create_direct, self.context, i) diff --git a/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py b/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py index b78aa5e8b..7ec7fd0fd 100644 --- a/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py +++ b/nova/tests/baremetal/test_nova_baremetal_deploy_helper.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 NTT DOCOMO, INC. -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Copyright 2011 Ilya Alekseyev # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/baremetal/test_nova_baremetal_manage.py b/nova/tests/baremetal/test_nova_baremetal_manage.py index c4fdaac6b..74e084113 100644 --- a/nova/tests/baremetal/test_nova_baremetal_manage.py +++ b/nova/tests/baremetal/test_nova_baremetal_manage.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 NTT DOCOMO, INC. -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Copyright 2011 Ilya Alekseyev # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/baremetal/test_pxe.py b/nova/tests/baremetal/test_pxe.py index d9e41bc67..dffecf9cd 100644 --- a/nova/tests/baremetal/test_pxe.py +++ b/nova/tests/baremetal/test_pxe.py @@ -27,7 +27,7 @@ from oslo.config import cfg from testtools import matchers from nova import exception -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.tests.baremetal.db import base as bm_db_base from nova.tests.baremetal.db import utils as bm_db_utils from nova.tests.image import fake as fake_image @@ -37,6 +37,7 @@ from nova.virt.baremetal import db from nova.virt.baremetal import pxe from nova.virt.baremetal import utils as bm_utils from nova.virt.disk import api as disk_api +from nova.virt import fake as fake_virt CONF = cfg.CONF @@ -61,7 +62,7 @@ class BareMetalPXETestCase(bm_db_base.BMDBTestCase): super(BareMetalPXETestCase, self).setUp() self.flags(**COMMON_FLAGS) self.flags(**BAREMETAL_FLAGS) - self.driver = pxe.PXE() + self.driver = pxe.PXE(fake_virt.FakeVirtAPI()) fake_image.stub_out_image_service(self.stubs) self.addCleanup(fake_image.FakeImageService_reset) @@ -201,8 +202,8 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase): def test_get_instance_deploy_ids(self): self.instance['extra_specs'] = { - 'deploy_kernel_id': 'aaaa', - 'deploy_ramdisk_id': 'bbbb', + 'baremetal:deploy_kernel_id': 'aaaa', + 'baremetal:deploy_ramdisk_id': 'bbbb', } self.flags(deploy_kernel="fail", group='baremetal') self.flags(deploy_ramdisk="fail", group='baremetal') @@ -239,20 +240,21 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase): self.assertEqual(sizes[1], 1) def test_get_tftp_image_info(self): + instance_type = utils.get_test_instance_type() # Raises an exception when options are neither specified # on the instance nor in configuration file CONF.baremetal.deploy_kernel = None CONF.baremetal.deploy_ramdisk = None self.assertRaises(exception.NovaException, pxe.get_tftp_image_info, - self.instance) + self.instance, instance_type) # Test that other non-true values also raise an exception CONF.baremetal.deploy_kernel = "" CONF.baremetal.deploy_ramdisk = "" self.assertRaises(exception.NovaException, pxe.get_tftp_image_info, - self.instance) + self.instance, instance_type) # Even if the instance includes kernel_id and ramdisk_id, # we still need deploy_kernel_id and deploy_ramdisk_id. @@ -262,7 +264,7 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase): self.instance['ramdisk_id'] = 'bbbb' self.assertRaises(exception.NovaException, pxe.get_tftp_image_info, - self.instance) + self.instance, instance_type) # If an instance doesn't specify deploy_kernel_id or deploy_ramdisk_id, # but defaults are set in the config file, we should use those. @@ -272,7 +274,7 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase): CONF.baremetal.deploy_kernel = 'cccc' CONF.baremetal.deploy_ramdisk = 'dddd' base = os.path.join(CONF.baremetal.tftp_root, self.instance['uuid']) - res = pxe.get_tftp_image_info(self.instance) + res = pxe.get_tftp_image_info(self.instance, instance_type) expected = { 'kernel': ['aaaa', os.path.join(base, 'kernel')], 'ramdisk': ['bbbb', os.path.join(base, 'ramdisk')], @@ -287,24 +289,24 @@ class PXEClassMethodsTestCase(BareMetalPXETestCase): # Note that it is passed on the 'instance' object, despite being # inherited from the instance_types_extra_specs table. extra_specs = { - 'deploy_kernel_id': 'eeee', - 'deploy_ramdisk_id': 'ffff', + 'baremetal:deploy_kernel_id': 'eeee', + 'baremetal:deploy_ramdisk_id': 'ffff', } - self.instance['extra_specs'] = extra_specs - res = pxe.get_tftp_image_info(self.instance) + instance_type['extra_specs'] = extra_specs + res = pxe.get_tftp_image_info(self.instance, instance_type) self.assertEqual(res['deploy_kernel'][0], 'eeee') self.assertEqual(res['deploy_ramdisk'][0], 'ffff') # However, if invalid values are passed on the image extra_specs, # this should still raise an exception. extra_specs = { - 'deploy_kernel_id': '', - 'deploy_ramdisk_id': '', + 'baremetal:deploy_kernel_id': '', + 'baremetal:deploy_ramdisk_id': '', } - self.instance['extra_specs'] = extra_specs + instance_type['extra_specs'] = extra_specs self.assertRaises(exception.NovaException, pxe.get_tftp_image_info, - self.instance) + self.instance, instance_type) class PXEPrivateMethodsTestCase(BareMetalPXETestCase): @@ -320,12 +322,13 @@ class PXEPrivateMethodsTestCase(BareMetalPXETestCase): def test_cache_tftp_images(self): self.instance['kernel_id'] = 'aaaa' self.instance['ramdisk_id'] = 'bbbb' + instance_type = utils.get_test_instance_type() extra_specs = { - 'deploy_kernel_id': 'cccc', - 'deploy_ramdisk_id': 'dddd', + 'baremetal:deploy_kernel_id': 'cccc', + 'baremetal:deploy_ramdisk_id': 'dddd', } - self.instance['extra_specs'] = extra_specs - image_info = pxe.get_tftp_image_info(self.instance) + instance_type['extra_specs'] = extra_specs + image_info = pxe.get_tftp_image_info(self.instance, instance_type) self.mox.StubOutWithMock(os, 'makedirs') self.mox.StubOutWithMock(os.path, 'exists') @@ -390,12 +393,15 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase): def test_cache_images(self): self._create_node() + self.mox.StubOutWithMock(self.driver.virtapi, 'instance_type_get') self.mox.StubOutWithMock(pxe, "get_tftp_image_info") self.mox.StubOutWithMock(self.driver, "_cache_tftp_images") self.mox.StubOutWithMock(self.driver, "_cache_image") self.mox.StubOutWithMock(self.driver, "_inject_into_image") - pxe.get_tftp_image_info(self.instance).AndReturn([]) + self.driver.virtapi.instance_type_get( + self.context, self.instance['instance_type_id']).AndReturn({}) + pxe.get_tftp_image_info(self.instance, {}).AndReturn([]) self.driver._cache_tftp_images(self.context, self.instance, []) self.driver._cache_image(self.context, self.instance, []) self.driver._inject_into_image(self.context, self.node, self.instance, @@ -440,6 +446,7 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase): pxe_path = pxe.get_pxe_config_file_path(self.instance) image_path = pxe.get_image_file_path(self.instance) + self.mox.StubOutWithMock(self.driver.virtapi, 'instance_type_get') self.mox.StubOutWithMock(pxe, 'get_tftp_image_info') self.mox.StubOutWithMock(pxe, 'get_partition_sizes') self.mox.StubOutWithMock(bm_utils, 'random_alnum') @@ -447,7 +454,9 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase): self.mox.StubOutWithMock(bm_utils, 'write_to_file') self.mox.StubOutWithMock(bm_utils, 'create_link_without_raise') - pxe.get_tftp_image_info(self.instance).AndReturn(image_info) + self.driver.virtapi.instance_type_get( + self.context, self.instance['instance_type_id']).AndReturn({}) + pxe.get_tftp_image_info(self.instance, {}).AndReturn(image_info) pxe.get_partition_sizes(self.instance).AndReturn((0, 0)) bm_utils.random_alnum(32).AndReturn('alnum') pxe.build_pxe_config( @@ -466,18 +475,24 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase): def test_activate_and_deactivate_bootloader(self): self._create_node() - extra_specs = { - 'deploy_kernel_id': 'eeee', - 'deploy_ramdisk_id': 'ffff', + instance_type = { + 'extra_specs': { + 'baremetal:deploy_kernel_id': 'eeee', + 'baremetal:deploy_ramdisk_id': 'ffff', + } } - self.instance['extra_specs'] = extra_specs self.instance['uuid'] = 'fake-uuid' + self.mox.StubOutWithMock(self.driver.virtapi, 'instance_type_get') self.mox.StubOutWithMock(bm_utils, 'write_to_file') self.mox.StubOutWithMock(bm_utils, 'create_link_without_raise') self.mox.StubOutWithMock(bm_utils, 'unlink_without_raise') self.mox.StubOutWithMock(bm_utils, 'rmtree_without_raise') + self.driver.virtapi.instance_type_get( + self.context, self.instance['instance_type_id']).AndReturn( + instance_type) + # create the config file bm_utils.write_to_file(mox.StrContains('fake-uuid'), mox.StrContains(CONF.baremetal.tftp_root)) @@ -525,11 +540,14 @@ class PXEPublicMethodsTestCase(BareMetalPXETestCase): self.mox.StubOutWithMock(pxe, 'get_tftp_image_info') self.mox.StubOutWithMock(self.driver, '_collect_mac_addresses') - pxe.get_tftp_image_info(self.instance).\ + extra_specs = dict(extra_specs={ + 'baremetal:deploy_ramdisk_id': 'ignore', + 'baremetal:deploy_kernel_id': 'ignore'}) + pxe.get_tftp_image_info(self.instance, extra_specs).\ AndRaise(exception.NovaException) bm_utils.unlink_without_raise(pxe_path) self.driver._collect_mac_addresses(self.context, self.node).\ - AndRaise(db_session.DBError) + AndRaise(db_exc.DBError) bm_utils.rmtree_without_raise( os.path.join(CONF.baremetal.tftp_root, 'fake-uuid')) self.mox.ReplayAll() diff --git a/nova/tests/baremetal/test_virtual_power_driver.py b/nova/tests/baremetal/test_virtual_power_driver.py index 5a38ed87b..4b140f66a 100644 --- a/nova/tests/baremetal/test_virtual_power_driver.py +++ b/nova/tests/baremetal/test_virtual_power_driver.py @@ -49,6 +49,7 @@ BAREMETAL_FLAGS = dict( virtual_power_type='vbox', virtual_power_host_user=None, virtual_power_host_pass=None, + virtual_power_host_key=None, group='baremetal', ) @@ -128,7 +129,7 @@ class VPDClassMethodsTestCase(BareMetalVPDTestCase): self.flags(virtual_power_host_user='user', group="baremetal") self.flags(virtual_power_host_pass='password', group="baremetal") - def test_get_conn_success(self): + def test_get_conn_success_pass(self): self._create_node() self._create_pm() self._conn = self.pm._get_conn() @@ -139,6 +140,24 @@ class VPDClassMethodsTestCase(BareMetalVPDTestCase): self.assertEqual(self.pm.connection_data.host, '127.0.0.1') self.assertEqual(self.pm.connection_data.username, 'user') self.assertEqual(self.pm.connection_data.password, 'password') + self.assertEqual(self.pm.connection_data.keyfile, None) + self.mox.VerifyAll() + + def test_get_conn_success_key(self): + self.flags(virtual_power_host_pass='', group="baremetal") + self.flags(virtual_power_host_key='/id_rsa_file.txt', + group="baremetal") + self._create_node() + self._create_pm() + self._conn = self.pm._get_conn() + self.mox.StubOutWithMock(connection, 'ssh_connect') + connection.ssh_connect(mox.IsA(self._conn)).AndReturn(True) + self.mox.ReplayAll() + self.pm._set_connection() + self.assertEqual(self.pm.connection_data.host, '127.0.0.1') + self.assertEqual(self.pm.connection_data.username, 'user') + self.assertEqual(self.pm.connection_data.password, '') + self.assertEqual(self.pm.connection_data.keyfile, '/id_rsa_file.txt') self.mox.VerifyAll() def test_get_full_node_list(self): diff --git a/nova/tests/cert/__init__.py b/nova/tests/cert/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/cert/__init__.py +++ b/nova/tests/cert/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/__init__.py b/nova/tests/compute/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/compute/__init__.py +++ b/nova/tests/compute/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/fake_resource_tracker.py b/nova/tests/compute/fake_resource_tracker.py index ab24bc7b9..2cd69b2c3 100644 --- a/nova/tests/compute/fake_resource_tracker.py +++ b/nova/tests/compute/fake_resource_tracker.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/test_claims.py b/nova/tests/compute/test_claims.py index d908c0089..42de11c09 100644 --- a/nova/tests/compute/test_claims.py +++ b/nova/tests/compute/test_claims.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py index 5ad333c9e..e247b41c9 100644 --- a/nova/tests/compute/test_compute.py +++ b/nova/tests/compute/test_compute.py @@ -605,6 +605,18 @@ class ComputeTestCase(BaseTestCase): fake_network.unset_stub_network_methods(self.stubs) instance = jsonutils.to_primitive(self._create_fake_instance()) + orig_update = self.compute._instance_update + + # Make sure the access_ip_* updates happen in the same DB + # update as the set to ACTIVE. + def _instance_update(ctxt, instance_uuid, **kwargs): + if kwargs.get('vm_state', None) == vm_states.ACTIVE: + self.assertEqual(kwargs['access_ip_v4'], '192.168.1.100') + self.assertEqual(kwargs['access_ip_v6'], '2001:db8:0:1::1') + return orig_update(ctxt, instance_uuid, **kwargs) + + self.stubs.Set(self.compute, '_instance_update', _instance_update) + try: self.compute.run_instance(self.context, instance=instance, is_first_time=True) @@ -850,6 +862,29 @@ class ComputeTestCase(BaseTestCase): self.assert_(instance['launched_at'] < terminate) self.assert_(instance['deleted_at'] > terminate) + def test_run_terminate_deallocate_net_failure_sets_error_state(self): + instance = jsonutils.to_primitive(self._create_fake_instance()) + + self.compute.run_instance(self.context, instance=instance) + + instances = db.instance_get_all(self.context) + LOG.info(_("Running instances: %s"), instances) + self.assertEqual(len(instances), 1) + + def _fake_deallocate_network(*args, **kwargs): + raise Exception() + + self.stubs.Set(self.compute, '_deallocate_network', + _fake_deallocate_network) + + try: + self.compute.terminate_instance(self.context, instance=instance) + except Exception: + pass + + instance = db.instance_get_by_uuid(self.context, instance['uuid']) + self.assertEqual(instance['vm_state'], vm_states.ERROR) + def test_stop(self): # Ensure instance can be stopped. instance = jsonutils.to_primitive(self._create_fake_instance()) @@ -1062,7 +1097,7 @@ class ComputeTestCase(BaseTestCase): self.compute.terminate_instance(self.context, instance=jsonutils.to_primitive(instance)) - def _test_reboot(self, soft, legacy_nwinfo_driver): + def _test_reboot(self, soft, legacy_nwinfo_driver, test_delete=False): # This is a true unit test, so we don't need the network stubs. fake_network.unset_stub_network_methods(self.stubs) @@ -1141,13 +1176,24 @@ class ComputeTestCase(BaseTestCase): # Power state should be updated again self.compute._get_power_state(econtext, updated_instance1).AndReturn(fake_power_state2) - self.compute._instance_update(econtext, updated_instance1['uuid'], - power_state=fake_power_state2, - task_state=None, - vm_state=vm_states.ACTIVE).AndReturn(updated_instance2) - self.compute._notify_about_instance_usage(econtext, - updated_instance2, - 'reboot.end') + if test_delete: + self.compute._instance_update(econtext, updated_instance1['uuid'], + power_state=fake_power_state2, + task_state=None, + vm_state=vm_states.ACTIVE).AndRaise( + exception.InstanceNotFound( + instance_id=updated_instance1['uuid'])) + self.compute._notify_about_instance_usage(econtext, + updated_instance1, + 'reboot.end') + else: + self.compute._instance_update(econtext, updated_instance1['uuid'], + power_state=fake_power_state2, + task_state=None, + vm_state=vm_states.ACTIVE).AndReturn(updated_instance2) + self.compute._notify_about_instance_usage(econtext, + updated_instance2, + 'reboot.end') self.mox.ReplayAll() self.compute.reboot_instance(self.context, instance=instance, @@ -1158,9 +1204,15 @@ class ComputeTestCase(BaseTestCase): def test_reboot_soft(self): self._test_reboot(True, False) + def test_reboot_soft_and_delete(self): + self._test_reboot(True, False, True) + def test_reboot_hard(self): self._test_reboot(False, False) + def test_reboot_hard_and_delete(self): + self._test_reboot(False, False, True) + def test_reboot_soft_legacy_nwinfo_driver(self): self._test_reboot(True, True) @@ -3109,16 +3161,12 @@ class ComputeTestCase(BaseTestCase): self.compute.host = instance['host'] - self.mox.StubOutWithMock(self.compute.driver, 'list_instances') - self.compute.driver.list_instances().AndReturn([instance['name']]) + self.mox.StubOutWithMock(self.compute, '_get_instances_on_driver') + self.compute._get_instances_on_driver(admin_context).AndReturn( + [instance]) self.flags(running_deleted_instance_timeout=3600, running_deleted_instance_action='reap') - self.mox.StubOutWithMock(self.compute.conductor_api, - "instance_get_all_by_host") - self.compute.conductor_api.instance_get_all_by_host( - admin_context, self.compute.host).AndReturn([instance]) - bdms = [] self.mox.StubOutWithMock(self.compute, "_shutdown_instance") @@ -3135,32 +3183,28 @@ class ComputeTestCase(BaseTestCase): self.compute._cleanup_running_deleted_instances(admin_context) def test_running_deleted_instances(self): - self.mox.StubOutWithMock(self.compute.driver, 'list_instances') - self.compute.driver.list_instances().AndReturn(['herp', 'derp']) + admin_context = context.get_admin_context() + self.compute.host = 'host' instance1 = {} - instance1['name'] = 'herp' instance1['deleted'] = True instance1['deleted_at'] = "sometimeago" instance2 = {} - instance2['name'] = 'derp' instance2['deleted'] = False instance2['deleted_at'] = None + self.mox.StubOutWithMock(self.compute, '_get_instances_on_driver') + self.compute._get_instances_on_driver(admin_context).AndReturn( + [instance1, instance2]) + self.mox.StubOutWithMock(timeutils, 'is_older_than') timeutils.is_older_than('sometimeago', CONF.running_deleted_instance_timeout).AndReturn(True) - self.mox.StubOutWithMock(self.compute.conductor_api, - "instance_get_all_by_host") - self.compute.conductor_api.instance_get_all_by_host('context', - 'host').AndReturn( - [instance1, - instance2]) self.mox.ReplayAll() - val = self.compute._running_deleted_instances('context') + val = self.compute._running_deleted_instances(admin_context) self.assertEqual(val, [instance1]) def test_get_instance_nw_info(self): @@ -3607,6 +3651,7 @@ class ComputeTestCase(BaseTestCase): 'info_cache': None, 'power_state': power_state.RUNNING, 'vm_state': vm_states.ACTIVE, + 'task_state': None, } self.flags(resume_guests_state_on_host_boot=True) self.mox.StubOutWithMock(self.compute, '_get_power_state') @@ -3630,6 +3675,38 @@ class ComputeTestCase(BaseTestCase): self.mox.ReplayAll() self.compute._init_instance('fake-context', instance) + def test_init_instance_reverts_crashed_migrations(self): + instance = { + 'uuid': 'foo', + 'vm_state': vm_states.ERROR, + 'task_state': task_states.RESIZE_MIGRATING, + 'power_state': power_state.SHUTDOWN, + } + fixed = dict(instance, task_state=None) + self.mox.StubOutWithMock(compute_utils, 'get_nw_info_for_instance') + self.mox.StubOutWithMock(self.compute.driver, 'plug_vifs') + self.mox.StubOutWithMock(self.compute.driver, + 'finish_revert_migration') + self.mox.StubOutWithMock(self.compute, + '_get_instance_volume_block_device_info') + self.mox.StubOutWithMock(self.compute.driver, 'get_info') + self.mox.StubOutWithMock(self.compute, '_instance_update') + + compute_utils.get_nw_info_for_instance(instance).AndReturn( + network_model.NetworkInfo()) + self.compute.driver.plug_vifs(instance, []) + self.compute._get_instance_volume_block_device_info( + self.context, instance).AndReturn([]) + self.compute.driver.finish_revert_migration(instance, [], []) + self.compute._instance_update(self.context, instance['uuid'], + task_state=None).AndReturn(fixed) + self.compute.driver.get_info(fixed).AndReturn( + {'state': power_state.SHUTDOWN}) + + self.mox.ReplayAll() + + self.compute._init_instance(self.context, instance) + def test_get_instances_on_driver(self): fake_context = context.get_admin_context() @@ -3641,14 +3718,14 @@ class ComputeTestCase(BaseTestCase): self.mox.StubOutWithMock(self.compute.driver, 'list_instance_uuids') self.mox.StubOutWithMock(self.compute.conductor_api, - 'instance_get_by_uuid') + 'instance_get_all_by_filters') self.compute.driver.list_instance_uuids().AndReturn( [inst['uuid'] for inst in driver_instances]) - for x in xrange(len(driver_instances)): - self.compute.conductor_api.instance_get_by_uuid(fake_context, - driver_instances[x]['uuid']).AndReturn( - driver_instances[x]) + self.compute.conductor_api.instance_get_all_by_filters( + fake_context, {'uuid': [inst['uuid'] for + inst in driver_instances]}).AndReturn( + driver_instances) self.mox.ReplayAll() @@ -3658,6 +3735,7 @@ class ComputeTestCase(BaseTestCase): def test_get_instances_on_driver_fallback(self): # Test getting instances when driver doesn't support # 'list_instance_uuids' + self.compute.host = 'host' fake_context = context.get_admin_context() all_instances = [] @@ -3673,14 +3751,14 @@ class ComputeTestCase(BaseTestCase): self.mox.StubOutWithMock(self.compute.driver, 'list_instances') self.mox.StubOutWithMock(self.compute.conductor_api, - 'instance_get_all') + 'instance_get_all_by_host') self.compute.driver.list_instance_uuids().AndRaise( NotImplementedError()) self.compute.driver.list_instances().AndReturn( [inst['name'] for inst in driver_instances]) - self.compute.conductor_api.instance_get_all( - fake_context).AndReturn(all_instances) + self.compute.conductor_api.instance_get_all_by_host( + fake_context, self.compute.host).AndReturn(all_instances) self.mox.ReplayAll() @@ -3707,6 +3785,30 @@ class ComputeTestCase(BaseTestCase): self.mox.ReplayAll() self.compute._instance_usage_audit(self.context) + def test_add_remove_fixed_ip_updates_instance_updated_at(self): + def _noop(*args, **kwargs): + pass + + self.stubs.Set(self.compute.network_api, + 'add_fixed_ip_to_instance', _noop) + self.stubs.Set(self.compute.network_api, + 'remove_fixed_ip_from_instance', _noop) + + instance = self._create_fake_instance() + updated_at_1 = instance['updated_at'] + + self.compute.add_fixed_ip_to_instance(self.context, 'fake', instance) + instance = db.instance_get_by_uuid(self.context, instance['uuid']) + updated_at_2 = instance['updated_at'] + + self.compute.remove_fixed_ip_from_instance(self.context, 'fake', + instance) + instance = db.instance_get_by_uuid(self.context, instance['uuid']) + updated_at_3 = instance['updated_at'] + + updated_ats = (updated_at_1, updated_at_2, updated_at_3) + self.assertEqual(len(updated_ats), len(set(updated_ats))) + class ComputeAPITestCase(BaseTestCase): @@ -4557,6 +4659,30 @@ class ComputeAPITestCase(BaseTestCase): inst_ref, reboot_type) + def test_soft_reboot_of_rescued_instance(self): + # Ensure instance can't be rebooted while in rescued state. + instance = jsonutils.to_primitive(self._create_fake_instance()) + self.compute.run_instance(self.context, instance=instance) + + inst_ref = db.instance_get_by_uuid(self.context, instance['uuid']) + + db.instance_update(self.context, instance['uuid'], + {"vm_state": vm_states.RESCUED}) + + inst_ref = db.instance_get_by_uuid(self.context, inst_ref['uuid']) + + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.reboot, + self.context, + inst_ref, + 'SOFT') + + self.assertRaises(exception.InstanceInvalidState, + self.compute_api.reboot, + self.context, + inst_ref, + 'HARD') + def test_hostname_create(self): # Ensure instance hostname is set during creation. inst_type = instance_types.get_instance_type_by_name('m1.tiny') @@ -4663,8 +4789,8 @@ class ComputeAPITestCase(BaseTestCase): def test_snapshot_minram_mindisk_VHD(self): """Ensure a snapshots min_ram and min_disk are correct. - A snapshot of a non-shrinkable VHD should have min_ram - and min_disk set to that of the original instances flavor. + A snapshot of a non-shrinkable VHD should have min_disk + set to that of the original instances flavor. """ self.fake_image.update(disk_format='vhd', @@ -4678,7 +4804,7 @@ class ComputeAPITestCase(BaseTestCase): self.assertEqual(image['name'], 'snap1') instance_type = instance['instance_type'] - self.assertEqual(image['min_ram'], instance_type['memory_mb']) + self.assertEqual(image['min_ram'], self.fake_image['min_ram']) self.assertEqual(image['min_disk'], instance_type['root_gb']) properties = image['properties'] self.assertTrue('backup_type' not in properties) @@ -5073,7 +5199,6 @@ class ComputeAPITestCase(BaseTestCase): instance = self._create_fake_instance(dict(host='host2')) instance = db.instance_get_by_uuid(self.context, instance['uuid']) instance = jsonutils.to_primitive(instance) - instance['instance_type']['extra_specs'] = [] orig_instance_type = instance['instance_type'] self.compute.run_instance(self.context, instance=instance) # We need to set the host to something 'known'. Unfortunately, @@ -6348,8 +6473,14 @@ class ComputeAPITestCase(BaseTestCase): def fake_service_is_up(*args, **kwargs): return False + def fake_rebuild_instance(*args, **kwargs): + db.instance_update(self.context, instance_uuid, + {'host': kwargs['host']}) + self.stubs.Set(self.compute_api.servicegroup_api, 'service_is_up', fake_service_is_up) + self.stubs.Set(self.compute_api.compute_rpcapi, 'rebuild_instance', + fake_rebuild_instance) self.compute_api.evacuate(self.context.elevated(), instance, host='fake_dest_host', @@ -6358,6 +6489,7 @@ class ComputeAPITestCase(BaseTestCase): instance = db.instance_get_by_uuid(self.context, instance_uuid) self.assertEqual(instance['task_state'], task_states.REBUILDING) + self.assertEqual(instance['host'], 'fake_dest_host') db.instance_destroy(self.context, instance['uuid']) @@ -7225,6 +7357,41 @@ class ComputeRescheduleOrReraiseTestCase(BaseTestCase): self.compute._reschedule_or_reraise(self.context, self.instance, exc_info, None, None, None, False, None, {}) + def test_no_reschedule_on_delete_during_spawn(self): + # instance should not be rescheduled if instance is deleted + # during the build + self.mox.StubOutWithMock(self.compute, '_spawn') + self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise') + + exc = exception.UnexpectedTaskStateError(expected=task_states.SPAWNING, + actual=task_states.DELETING) + self.compute._spawn(mox.IgnoreArg(), self.instance, mox.IgnoreArg(), + mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), + mox.IgnoreArg(), set_access_ip=False).AndRaise(exc) + + self.mox.ReplayAll() + # test succeeds if mocked method '_reschedule_or_reraise' is not + # called. + self.compute._run_instance(self.context, None, {}, None, None, None, + False, None, self.instance) + + def test_no_reschedule_on_unexpected_task_state(self): + # instance shouldn't be rescheduled if unexpected task state arises. + # the exception should get reraised. + self.mox.StubOutWithMock(self.compute, '_spawn') + self.mox.StubOutWithMock(self.compute, '_reschedule_or_reraise') + + exc = exception.UnexpectedTaskStateError(expected=task_states.SPAWNING, + actual=task_states.SCHEDULING) + self.compute._spawn(mox.IgnoreArg(), self.instance, mox.IgnoreArg(), + mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), + mox.IgnoreArg(), set_access_ip=False).AndRaise(exc) + + self.mox.ReplayAll() + self.assertRaises(exception.UnexpectedTaskStateError, + self.compute._run_instance, self.context, None, {}, None, None, + None, False, None, self.instance) + class ComputeRescheduleResizeOrReraiseTestCase(BaseTestCase): """Test logic and exception handling around rescheduling prep resize diff --git a/nova/tests/compute/test_compute_utils.py b/nova/tests/compute/test_compute_utils.py index 0f96e657d..884aac628 100644 --- a/nova/tests/compute/test_compute_utils.py +++ b/nova/tests/compute/test_compute_utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/test_host_api.py b/nova/tests/compute/test_host_api.py index 772ae1eb1..3b5a9b871 100644 --- a/nova/tests/compute/test_host_api.py +++ b/nova/tests/compute/test_host_api.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/test_multiple_nodes.py b/nova/tests/compute/test_multiple_nodes.py index 1a967c5e4..8bf3781c7 100644 --- a/nova/tests/compute/test_multiple_nodes.py +++ b/nova/tests/compute/test_multiple_nodes.py @@ -19,7 +19,6 @@ from oslo.config import cfg from nova import context -from nova import exception from nova.openstack.common import importutils from nova import test from nova.virt import fake @@ -72,8 +71,8 @@ class FakeDriverMultiNodeTestCase(BaseTestCase): res_b = self.driver.get_available_resource('bbb') self.assertEqual(res_b['hypervisor_hostname'], 'bbb') - self.assertRaises(exception.NovaException, - self.driver.get_available_resource, 'xxx') + res_x = self.driver.get_available_resource('xxx') + self.assertEqual(res_x, {}) class MultiNodeComputeTestCase(BaseTestCase): @@ -101,3 +100,22 @@ class MultiNodeComputeTestCase(BaseTestCase): self.compute.update_available_resource(ctx) self.assertEqual(sorted(self.compute._resource_tracker_dict.keys()), ['A', 'B', 'C']) + + def test_compute_manager_removes_deleted_node(self): + ctx = context.get_admin_context() + fake.set_nodes(['A', 'B']) + self.compute.update_available_resource(ctx) + + rt_A = self.compute._resource_tracker_dict['A'] + rt_B = self.compute._resource_tracker_dict['B'] + self.mox.StubOutWithMock(rt_A, 'update_available_resource') + self.mox.StubOutWithMock(rt_B, 'update_available_resource') + rt_A.update_available_resource(ctx) + rt_B.update_available_resource(ctx, delete=True) + self.mox.ReplayAll() + + fake.set_nodes(['A']) + self.compute.update_available_resource(ctx) + self.mox.VerifyAll() + self.assertEqual(sorted(self.compute._resource_tracker_dict.keys()), + ['A']) diff --git a/nova/tests/compute/test_resource_tracker.py b/nova/tests/compute/test_resource_tracker.py index 84dbc69fc..860ea9fab 100644 --- a/nova/tests/compute/test_resource_tracker.py +++ b/nova/tests/compute/test_resource_tracker.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -347,6 +347,9 @@ class BaseTrackerTestCase(BaseTestCase): # database models and a compatible compute driver: super(BaseTrackerTestCase, self).setUp() + self.updated = False + self.deleted = False + self.tracker = self._tracker() self._migrations = {} @@ -354,6 +357,8 @@ class BaseTrackerTestCase(BaseTestCase): self._fake_service_get_by_compute_host) self.stubs.Set(db, 'compute_node_update', self._fake_compute_node_update) + self.stubs.Set(db, 'compute_node_delete', + self._fake_compute_node_delete) self.stubs.Set(db, 'migration_update', self._fake_migration_update) self.stubs.Set(db, 'migration_get_in_progress_by_host_and_node', @@ -375,6 +380,11 @@ class BaseTrackerTestCase(BaseTestCase): self.compute.update(values) return self.compute + def _fake_compute_node_delete(self, ctx, compute_node_id): + self.deleted = True + self.compute.update({'deleted': 1}) + return self.compute + def _fake_migration_get_in_progress_by_host_and_node(self, ctxt, host, node): status = ['confirmed', 'reverted'] @@ -867,10 +877,6 @@ class ResizeClaimTestCase(BaseTrackerTestCase): class OrphanTestCase(BaseTrackerTestCase): - - def setUp(self): - super(OrphanTestCase, self).setUp() - def _driver(self): class OrphanVirtDriver(FakeVirtDriver): def get_per_instance_usage(self): @@ -892,3 +898,18 @@ class OrphanTestCase(BaseTrackerTestCase): orphans = self.tracker._find_orphaned_instances() self.assertEqual(2, len(orphans)) + + +class DeletedNodeTestCase(BaseTrackerTestCase): + + def test_remove_deleted_node(self): + self.assertFalse(self.tracker.disabled) + self.assertTrue(self.updated) + + def _get_available_resource(nodename): + return {} + self.tracker.driver.get_available_resource = _get_available_resource + + self.tracker.update_available_resource(self.context, delete=True) + self.assertEqual(self.deleted, True) + self.assertEqual(self.compute['deleted'], 1) diff --git a/nova/tests/compute/test_rpcapi.py b/nova/tests/compute/test_rpcapi.py index 1257f67e1..6c40a95e2 100644 --- a/nova/tests/compute/test_rpcapi.py +++ b/nova/tests/compute/test_rpcapi.py @@ -162,9 +162,6 @@ class ComputeRpcAPITestCase(test.TestCase): self._test_compute_api('get_diagnostics', 'call', instance=self.fake_instance) - def test_get_host_uptime(self): - self._test_compute_api('get_host_uptime', 'call') - def test_get_vnc_console(self): self._test_compute_api('get_vnc_console', 'call', instance=self.fake_instance, console_type='type') diff --git a/nova/tests/compute/test_stats.py b/nova/tests/compute/test_stats.py index a798670c7..03fe4b359 100644 --- a/nova/tests/compute/test_stats.py +++ b/nova/tests/compute/test_stats.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/compute/test_virtapi.py b/nova/tests/compute/test_virtapi.py index 568bf456d..e3887d033 100644 --- a/nova/tests/compute/test_virtapi.py +++ b/nova/tests/compute/test_virtapi.py @@ -77,6 +77,10 @@ class VirtAPIBaseTest(test.TestCase, test.APICoverage): self.assertExpected('agent_build_get_by_triple', 'fake-hv', 'gnu/hurd', 'fake-arch') + def test_instance_type_get(self): + self.assertExpected('instance_type_get', + 'fake-instance-type') + class FakeVirtAPITest(VirtAPIBaseTest): diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py index 32e685623..72c04e427 100644 --- a/nova/tests/conductor/test_conductor.py +++ b/nova/tests/conductor/test_conductor.py @@ -429,6 +429,14 @@ class _BaseTestCase(object): 'fake-values', False) self.assertEqual(result, 'fake-result') + def test_compute_node_delete(self): + node = {'id': 'fake-id'} + self.mox.StubOutWithMock(db, 'compute_node_delete') + db.compute_node_delete(self.context, node['id']).AndReturn(None) + self.mox.ReplayAll() + result = self.conductor.compute_node_delete(self.context, node) + self.assertEqual(result, None) + def test_instance_fault_create(self): self.mox.StubOutWithMock(db, 'instance_fault_create') db.instance_fault_create(self.context, 'fake-values').AndReturn( diff --git a/nova/tests/console/__init__.py b/nova/tests/console/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/console/__init__.py +++ b/nova/tests/console/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/console/test_console.py b/nova/tests/console/test_console.py index 0f95f3d95..54bcb32ca 100644 --- a/nova/tests/console/test_console.py +++ b/nova/tests/console/test_console.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # diff --git a/nova/tests/consoleauth/__init__.py b/nova/tests/consoleauth/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/consoleauth/__init__.py +++ b/nova/tests/consoleauth/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/consoleauth/test_consoleauth.py b/nova/tests/consoleauth/test_consoleauth.py index 54e3d2261..9b9b0c92a 100644 --- a/nova/tests/consoleauth/test_consoleauth.py +++ b/nova/tests/consoleauth/test_consoleauth.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # diff --git a/nova/tests/db/fakes.py b/nova/tests/db/fakes.py index d77e189df..455751809 100644 --- a/nova/tests/db/fakes.py +++ b/nova/tests/db/fakes.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 X.commerce, a business unit of eBay Inc. -# Copyright 2010 OpenStack, LLC +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -331,51 +331,56 @@ def stub_out_db_instance_api(stubs, injected=True): INSTANCE_TYPES = { 'm1.tiny': dict(id=2, + name='m1.tiny', memory_mb=512, vcpus=1, vcpu_weight=None, root_gb=0, ephemeral_gb=10, flavorid=1, - rxtx_cap=1, + rxtx_factor=1.0, swap=0), 'm1.small': dict(id=5, + name='m1.small', memory_mb=2048, vcpus=1, vcpu_weight=None, root_gb=20, ephemeral_gb=0, flavorid=2, - rxtx_cap=2, + rxtx_factor=1.0, swap=1024), 'm1.medium': dict(id=1, + name='m1.medium', memory_mb=4096, vcpus=2, vcpu_weight=None, root_gb=40, ephemeral_gb=40, flavorid=3, - rxtx_cap=3, + rxtx_factor=1.0, swap=0), 'm1.large': dict(id=3, + name='m1.large', memory_mb=8192, vcpus=4, vcpu_weight=None, root_gb=80, ephemeral_gb=80, flavorid=4, - rxtx_cap=4, + rxtx_factor=1.0, swap=0), 'm1.xlarge': dict(id=4, + name='m1.xlarge', memory_mb=16384, vcpus=8, vcpu_weight=None, root_gb=160, ephemeral_gb=160, flavorid=5, - rxtx_cap=5, + rxtx_factor=1.0, swap=0)} flat_network_fields = {'id': 'fake_flat', diff --git a/nova/tests/fake_hosts.py b/nova/tests/fake_hosts.py index e6831d124..618566c0b 100644 --- a/nova/tests/fake_hosts.py +++ b/nova/tests/fake_hosts.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/fake_instance_actions.py b/nova/tests/fake_instance_actions.py index f34d9b213..e12ae827f 100644 --- a/nova/tests/fake_instance_actions.py +++ b/nova/tests/fake_instance_actions.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2013 OpenStack LLC +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fake_libvirt_utils.py b/nova/tests/fake_libvirt_utils.py index 31b1af231..ba00a7091 100644 --- a/nova/tests/fake_libvirt_utils.py +++ b/nova/tests/fake_libvirt_utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack LLC +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fake_loadables/__init__.py b/nova/tests/fake_loadables/__init__.py index 824243347..a74c55d21 100644 --- a/nova/tests/fake_loadables/__init__.py +++ b/nova/tests/fake_loadables/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. # All Rights Reserved. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fake_loadables/fake_loadable1.py b/nova/tests/fake_loadables/fake_loadable1.py index 58f9704b3..cc02fe717 100644 --- a/nova/tests/fake_loadables/fake_loadable1.py +++ b/nova/tests/fake_loadables/fake_loadable1.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. # All Rights Reserved. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fake_loadables/fake_loadable2.py b/nova/tests/fake_loadables/fake_loadable2.py index 3e365effc..e72b58200 100644 --- a/nova/tests/fake_loadables/fake_loadable2.py +++ b/nova/tests/fake_loadables/fake_loadable2.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. # All Rights Reserved. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fake_network_cache_model.py b/nova/tests/fake_network_cache_model.py index 32ace8bdc..3aa3bf586 100644 --- a/nova/tests/fake_network_cache_model.py +++ b/nova/tests/fake_network_cache_model.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py index 7f9fffddc..94380058d 100644 --- a/nova/tests/fake_policy.py +++ b/nova/tests/fake_policy.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/fakelibvirt.py b/nova/tests/fakelibvirt.py index 69a4e677e..05dce0c76 100644 --- a/nova/tests/fakelibvirt.py +++ b/nova/tests/fakelibvirt.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -16,6 +16,7 @@ from lxml import etree +import time import uuid # Allow passing None to the various connect methods diff --git a/nova/tests/hyperv/db_fakes.py b/nova/tests/hyperv/db_fakes.py index 7169edf8d..5152bd035 100644 --- a/nova/tests/hyperv/db_fakes.py +++ b/nova/tests/hyperv/db_fakes.py @@ -41,7 +41,7 @@ def get_fake_instance_data(name, project_id, user_id): {'name': 'm1.tiny', 'memory_mb': 512, 'vcpus': 1, - 'root_gb': 0, + 'root_gb': 1024, 'flavorid': 1, 'rxtx_factor': 1} } @@ -69,8 +69,6 @@ def get_fake_volume_info_data(target_portal, volume_id): 'target_portal': target_portal, 'target_lun': 1, 'auth_method': 'CHAP', - 'auth_method': 'fake', - 'auth_method': 'fake', } } @@ -121,6 +119,9 @@ def stub_out_db_instance_api(stubs): def __getitem__(self, key): return self.get(key) + def __setitem__(self, key, value): + self.values[key] = value + def __str__(self): return str(self.values) diff --git a/nova/tests/image/__init__.py b/nova/tests/image/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/image/__init__.py +++ b/nova/tests/image/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/image/fake.py b/nova/tests/image/fake.py index 06f2f5147..d2d80ab35 100644 --- a/nova/tests/image/fake.py +++ b/nova/tests/image/fake.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 Justin Santa Barbara -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/image/test_fake.py b/nova/tests/image/test_fake.py index c63bb5389..266d03fc6 100644 --- a/nova/tests/image/test_fake.py +++ b/nova/tests/image/test_fake.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Author: Soren Hansen # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py index a7ed4c409..2eca4b969 100644 --- a/nova/tests/image/test_glance.py +++ b/nova/tests/image/test_glance.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.json.tpl b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.json.tpl new file mode 100644 index 000000000..3d360a57b --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.json.tpl @@ -0,0 +1,6 @@ +{ + "volumeAttachment": { + "volumeId": "%(volume_id)s", + "device": "%(device)s" + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.xml.tpl new file mode 100644 index 000000000..ffb20ad1e --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-req.xml.tpl @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="UTF-8"?> +<volumeAttachment volumeId="%(volume_id)s" device="%(device)s" /> diff --git a/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.json.tpl new file mode 100644 index 000000000..4730b3c19 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.json.tpl @@ -0,0 +1,8 @@ +{ + "volumeAttachment": { + "device": "%(device)s", + "id": "%(volume_id)s", + "serverId": "%(uuid)s", + "volumeId": "%(volume_id)s" + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.xml.tpl new file mode 100644 index 000000000..efad2fd02 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/attach-volume-to-server-resp.xml.tpl @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachment device="%(device)s" serverId="%(uuid)s" id="%(volume_id)s" volumeId="%(volume_id)s"/> diff --git a/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.json.tpl new file mode 100644 index 000000000..6c1da07ef --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.json.tpl @@ -0,0 +1,16 @@ +{ + "volumeAttachments": [ + { + "device": "/dev/sdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "%(uuid)s", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + }, + { + "device": "/dev/sdc", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f804", + "serverId": "%(uuid)s", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f804" + } + ] +} diff --git a/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.xml.tpl new file mode 100644 index 000000000..351646d81 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/list-volume-attachments-resp.xml.tpl @@ -0,0 +1,5 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachments> + <volumeAttachment device="/dev/sdd" serverId="%(uuid)s" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> + <volumeAttachment device="/dev/sdc" serverId="%(uuid)s" id="a26887c6-c47b-4654-abb5-dfadf7d3f804" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f804"/> +</volumeAttachments> diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.json.tpl new file mode 100644 index 000000000..eeca4489e --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.json.tpl @@ -0,0 +1,24 @@ +{ + "volumes": [ + { + "attachments": [ + { + "device": "/", + "id": "%(uuid)s", + "serverId": "%(uuid)s", + "volumeId": "%(uuid)s" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "%(timestamp)s", + "displayDescription": "%(volume_desc)s", + "displayName": "%(volume_name)s", + "id": "%(uuid)s", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } + ] +} diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.xml.tpl new file mode 100644 index 000000000..7410bed49 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-detail-resp.xml.tpl @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumes> + <volume status="in-use" displayDescription="%(volume_desc)s" availabilityZone="zone1:host1" displayName="%(volume_name)s" volumeType="Backup" snapshotId="None" id="%(uuid)s" createdAt="%(timestamp)s" size="100"> + <attachments> + <attachment device="/" serverId="%(uuid)s" id="%(uuid)s" volumeId="%(uuid)s"/> + </attachments> + <metadata/> + </volume> +</volumes> diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.json.tpl new file mode 100644 index 000000000..4343e6c0a --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.json.tpl @@ -0,0 +1,22 @@ +{ + "volume": { + "attachments": [ + { + "device": "/", + "id": "%(uuid)s", + "serverId": "%(uuid)s", + "volumeId": "%(uuid)s" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "%(timestamp)s", + "displayDescription": "%(volume_desc)s", + "displayName": "%(volume_name)s", + "id": "%(uuid)s", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.xml.tpl new file mode 100644 index 000000000..6503138f0 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-get-resp.xml.tpl @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volume status="in-use" displayDescription="%(volume_desc)s" availabilityZone="zone1:host1" displayName="%(volume_name)s" volumeType="Backup" snapshotId="None" id="%(uuid)s" createdAt="%(timestamp)s" size="100"> + <attachments> + <attachment device="/" serverId="%(uuid)s" id="%(uuid)s" volumeId="%(uuid)s"/> + </attachments> + <metadata/> +</volume> diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.json.tpl new file mode 100644 index 000000000..eeca4489e --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.json.tpl @@ -0,0 +1,24 @@ +{ + "volumes": [ + { + "attachments": [ + { + "device": "/", + "id": "%(uuid)s", + "serverId": "%(uuid)s", + "volumeId": "%(uuid)s" + } + ], + "availabilityZone": "zone1:host1", + "createdAt": "%(timestamp)s", + "displayDescription": "%(volume_desc)s", + "displayName": "%(volume_name)s", + "id": "%(uuid)s", + "metadata": {}, + "size": 100, + "snapshotId": null, + "status": "in-use", + "volumeType": "Backup" + } + ] +} diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.xml.tpl new file mode 100644 index 000000000..7410bed49 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-index-resp.xml.tpl @@ -0,0 +1,9 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumes> + <volume status="in-use" displayDescription="%(volume_desc)s" availabilityZone="zone1:host1" displayName="%(volume_name)s" volumeType="Backup" snapshotId="None" id="%(uuid)s" createdAt="%(timestamp)s" size="100"> + <attachments> + <attachment device="/" serverId="%(uuid)s" id="%(uuid)s" volumeId="%(uuid)s"/> + </attachments> + <metadata/> + </volume> +</volumes> diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.json.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.json.tpl new file mode 100644 index 000000000..db7fbff4d --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.json.tpl @@ -0,0 +1,9 @@ +{ + "volume": + { + "availability_zone": "zone1:host1", + "display_name": "%(volume_name)s", + "display_description": "%(volume_desc)s", + "size": 100 + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.xml.tpl new file mode 100644 index 000000000..bb115cc61 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-req.xml.tpl @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> + <volume displayDescription="%(volume_desc)s" availabilityZone="zone1:host1" displayName="%(volume_name)s" size="100"/> diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.json.tpl new file mode 100644 index 000000000..f1a3d3ca3 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.json.tpl @@ -0,0 +1,21 @@ +{ + "volume": { + "status": "in-use", + "displayDescription": "%(volume_desc)s", + "availabilityZone": "zone1:host1", + "displayName": "%(volume_name)s", + "attachments": [ + { "device": "/", + "serverId": "%(uuid)s", + "id": "%(uuid)s", + "volumeId": "%(uuid)s" + } + ], + "volumeType": "Backup", + "snapshotId": null, + "metadata": {}, + "id": "%(uuid)s", + "createdAt": "%(timestamp)s", + "size": 100 + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.xml.tpl new file mode 100644 index 000000000..6503138f0 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/os-volumes-post-resp.xml.tpl @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volume status="in-use" displayDescription="%(volume_desc)s" availabilityZone="zone1:host1" displayName="%(volume_name)s" volumeType="Backup" snapshotId="None" id="%(uuid)s" createdAt="%(timestamp)s" size="100"> + <attachments> + <attachment device="/" serverId="%(uuid)s" id="%(uuid)s" volumeId="%(uuid)s"/> + </attachments> + <metadata/> +</volume> diff --git a/nova/tests/integrated/api_samples/os-volumes/server-post-req.json.tpl b/nova/tests/integrated/api_samples/os-volumes/server-post-req.json.tpl new file mode 100644 index 000000000..d3916d1aa --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/server-post-req.json.tpl @@ -0,0 +1,16 @@ +{ + "server" : { + "name" : "new-server-test", + "imageRef" : "%(host)s/openstack/images/%(image_id)s", + "flavorRef" : "%(host)s/openstack/flavors/1", + "metadata" : { + "My Server Name" : "Apache1" + }, + "personality" : [ + { + "path" : "/etc/banner.txt", + "contents" : "ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBpdCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5kIGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVsc2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4gQnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRoZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlvdSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vyc2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6b25zLiINCg0KLVJpY2hhcmQgQmFjaA==" + } + ] + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/server-post-req.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/server-post-req.xml.tpl new file mode 100644 index 000000000..f92614984 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/server-post-req.xml.tpl @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="UTF-8"?> +<server xmlns="http://docs.openstack.org/compute/api/v1.1" imageRef="%(host)s/openstack/images/%(image_id)s" flavorRef="%(host)s/openstack/flavors/1" name="new-server-test"> + <metadata> + <meta key="My Server Name">Apache1</meta> + </metadata> + <personality> + <file path="/etc/banner.txt"> + ICAgICAgDQoiQSBjbG91ZCBkb2VzIG5vdCBrbm93IHdoeSBp + dCBtb3ZlcyBpbiBqdXN0IHN1Y2ggYSBkaXJlY3Rpb24gYW5k + IGF0IHN1Y2ggYSBzcGVlZC4uLkl0IGZlZWxzIGFuIGltcHVs + c2lvbi4uLnRoaXMgaXMgdGhlIHBsYWNlIHRvIGdvIG5vdy4g + QnV0IHRoZSBza3kga25vd3MgdGhlIHJlYXNvbnMgYW5kIHRo + ZSBwYXR0ZXJucyBiZWhpbmQgYWxsIGNsb3VkcywgYW5kIHlv + dSB3aWxsIGtub3csIHRvbywgd2hlbiB5b3UgbGlmdCB5b3Vy + c2VsZiBoaWdoIGVub3VnaCB0byBzZWUgYmV5b25kIGhvcml6 + b25zLiINCg0KLVJpY2hhcmQgQmFjaA== + </file> + </personality> +</server> diff --git a/nova/tests/integrated/api_samples/os-volumes/server-post-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/server-post-resp.json.tpl new file mode 100644 index 000000000..d5f030c87 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/server-post-resp.json.tpl @@ -0,0 +1,16 @@ +{ + "server": { + "adminPass": "%(password)s", + "id": "%(id)s", + "links": [ + { + "href": "%(host)s/v2/openstack/servers/%(uuid)s", + "rel": "self" + }, + { + "href": "%(host)s/openstack/servers/%(uuid)s", + "rel": "bookmark" + } + ] + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/server-post-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/server-post-resp.xml.tpl new file mode 100644 index 000000000..3bb13e69b --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/server-post-resp.xml.tpl @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<server xmlns:atom="http://www.w3.org/2005/Atom" xmlns="http://docs.openstack.org/compute/api/v1.1" id="%(id)s" adminPass="%(password)s"> + <metadata/> + <atom:link href="%(host)s/v2/openstack/servers/%(uuid)s" rel="self"/> + <atom:link href="%(host)s/openstack/servers/%(uuid)s" rel="bookmark"/> +</server> diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.json.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.json.tpl new file mode 100644 index 000000000..a8d47ea03 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.json.tpl @@ -0,0 +1,8 @@ +{ + "snapshot": { + "display_name": "%(snapshot_name)s", + "display_description": "%(description)s", + "volume_id": "%(volume_id)s", + "force": false + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.xml.tpl new file mode 100644 index 000000000..a5b670bc2 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-req.xml.tpl @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8"?> + <snapshot> + <display_name>%(snapshot_name)s</display_name> + <display_description>%(description)s</display_description> + <volume_id>%(volume_id)s</volume_id> + <force>false</force> + </snapshot> diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.json.tpl new file mode 100644 index 000000000..73cd02d9d --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.json.tpl @@ -0,0 +1,32 @@ +{ + "snapshot": { + "createdAt": "%(timestamp)s", + "displayDescription": "%(description)s", + "displayName": "%(snapshot_name)s", + "id": 100, + "size": 100, + "status": "available", + "volumeId": { + "attach_status": "attached", + "availability_zone": "fakeaz", + "created_at": "%(timestamp)s", + "display_description": "displaydesc", + "display_name": "displayname", + "host": "fakehost", + "id": "%(uuid)s", + "instance_uuid": "fakeuuid", + "mountpoint": "/", + "name": "vol name", + "project_id": "fakeproject", + "size": 1, + "snapshot_id": null, + "status": "fakestatus", + "user_id": "fakeuser", + "volume_metadata": [], + "volume_type": { + "name": "vol_type_name" + }, + "volume_type_id": "fakevoltype" + } + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.xml.tpl new file mode 100644 index 000000000..aa713311f --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshot-create-resp.xml.tpl @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshot status="available" displayDescription="%(description)s" displayName="%(snapshot_name)s" volumeId="{'instance_uuid': 'fakeuuid', 'status': 'fakestatus', 'user_id': 'fakeuser', 'name': 'vol name', 'display_name': 'displayname', 'availability_zone': 'fakeaz', 'created_at': datetime.datetime(1999, 1, 1, 1, 1, 1), 'attach_status': 'attached', 'display_description': 'displaydesc', 'host': 'fakehost', 'volume_type_id': 'fakevoltype', 'volume_metadata': [], 'volume_type': {'name': 'vol_type_name'}, 'snapshot_id': None, 'mountpoint': '/', 'project_id': 'fakeproject', 'id': u'521752a6-acf6-4b2d-bc7a-119f9148cd8c', 'size': 1}" id="100" createdAt="%(timestamp)s" size="100"/> diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.json.tpl new file mode 100644 index 000000000..f6b4a3abf --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.json.tpl @@ -0,0 +1,31 @@ +{ + "snapshots": [ + { + "createdAt": "%(timestamp)s", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 100, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "%(timestamp)s", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 101, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "%(timestamp)s", + "displayDescription": "Default description", + "displayName": "Default name", + "id": 102, + "size": 100, + "status": "available", + "volumeId": 12 + } + ] +} diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.xml.tpl new file mode 100644 index 000000000..dbfe32526 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-detail-resp.xml.tpl @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshots> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="100" createdAt="%(timestamp)s" size="100"/> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="101" createdAt="%(timestamp)s" size="100"/> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="102" createdAt="%(timestamp)s" size="100"/> +</snapshots> diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.json.tpl new file mode 100644 index 000000000..5cfbd7283 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.json.tpl @@ -0,0 +1,31 @@ +{ + "snapshots": [ + { + "createdAt": "%(timestamp)s", + "displayDescription": "%(text)s", + "displayName": "%(text)s", + "id": 100, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "%(timestamp)s", + "displayDescription": "%(text)s", + "displayName": "%(text)s", + "id": 101, + "size": 100, + "status": "available", + "volumeId": 12 + }, + { + "createdAt": "%(timestamp)s", + "displayDescription": "%(text)s", + "displayName": "%(text)s", + "id": 102, + "size": 100, + "status": "available", + "volumeId": 12 + } + ] +} diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.xml.tpl new file mode 100644 index 000000000..dbfe32526 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-list-resp.xml.tpl @@ -0,0 +1,6 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshots> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="100" createdAt="%(timestamp)s" size="100"/> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="101" createdAt="%(timestamp)s" size="100"/> + <snapshot status="available" displayDescription="%(text)s" displayName="%(text)s" volumeId="12" id="102" createdAt="%(timestamp)s" size="100"/> +</snapshots> diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.json.tpl new file mode 100644 index 000000000..0690ed8b6 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.json.tpl @@ -0,0 +1,11 @@ +{ + "snapshot": { + "createdAt": "%(timestamp)s", + "displayDescription": "%(description)s", + "displayName": "%(snapshot_name)s", + "id": "100", + "size": 100, + "status": "available", + "volumeId": 12 + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.xml.tpl new file mode 100644 index 000000000..3525851cf --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/snapshots-show-resp.xml.tpl @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<snapshot status="available" displayDescription="%(description)s" displayName="%(snapshot_name)s" volumeId="12" id="100" createdAt="%(timestamp)s" size="100"/> diff --git a/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.json.tpl b/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.json.tpl new file mode 100644 index 000000000..86099eeb8 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.json.tpl @@ -0,0 +1,8 @@ +{ + "volumeAttachment": { + "device": "/dev/sdd", + "id": "a26887c6-c47b-4654-abb5-dfadf7d3f803", + "serverId": "%(uuid)s", + "volumeId": "a26887c6-c47b-4654-abb5-dfadf7d3f803" + } +} diff --git a/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.xml.tpl b/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.xml.tpl new file mode 100644 index 000000000..45fd19979 --- /dev/null +++ b/nova/tests/integrated/api_samples/os-volumes/volume-attachment-detail-resp.xml.tpl @@ -0,0 +1,2 @@ +<?xml version='1.0' encoding='UTF-8'?> +<volumeAttachment device="/dev/sdd" serverId="%(uuid)s" id="a26887c6-c47b-4654-abb5-dfadf7d3f803" volumeId="a26887c6-c47b-4654-abb5-dfadf7d3f803"/> diff --git a/nova/tests/integrated/test_api_samples.py b/nova/tests/integrated/test_api_samples.py index d48ef5091..9fe2c6566 100644 --- a/nova/tests/integrated/test_api_samples.py +++ b/nova/tests/integrated/test_api_samples.py @@ -33,6 +33,7 @@ from nova.api.openstack.compute.contrib import fping # Import extensions to pull in osapi_compute_extension CONF option used below. from nova.cloudpipe import pipelib from nova.compute import api as compute_api +from nova.compute import manager as compute_manager from nova import context from nova import db from nova.db.sqlalchemy import models @@ -46,6 +47,7 @@ import nova.quota from nova.scheduler import driver from nova.servicegroup import api as service_group_api from nova import test +from nova.tests.api.openstack.compute.contrib import test_coverage_ext from nova.tests.api.openstack.compute.contrib import test_fping from nova.tests.api.openstack.compute.contrib import test_networks from nova.tests.api.openstack.compute.contrib import test_services @@ -57,6 +59,7 @@ from nova.tests.image import fake from nova.tests.integrated import integrated_helpers from nova.tests import utils as test_utils from nova import utils +from nova.volume import cinder CONF = cfg.CONF CONF.import_opt('allow_resize_to_same_host', 'nova.compute.api') @@ -173,8 +176,18 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase): ex_keys = sorted(expected.keys()) res_keys = sorted(result.keys()) if ex_keys != res_keys: - raise NoMatch(_('Key mismatch:\n' - '%(ex_keys)s\n%(res_keys)s') % locals()) + ex_delta = [] + res_delta = [] + for key in ex_keys: + if key not in res_keys: + ex_delta.append(key) + for key in res_keys: + if key not in ex_keys: + res_delta.append(key) + raise NoMatch(_('Dictionary key mismatch:\n' + 'Extra key(s) in template:\n%(ex_delta)s\n' + 'Extra key(s) in response:\n%(res_delta)s\n') + % locals()) for key in ex_keys: res = self._compare_result(subs, expected[key], result[key]) matched_value = res or matched_value @@ -199,11 +212,11 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase): error = [] if expected: - error.append(_('Extra items in expected:')) + error.append(_('Extra list items in template:')) error.extend([repr(o) for o in expected]) if extra: - error.append(_('Extra items in result:')) + error.append(_('Extra list items in response:')) error.extend([repr(o) for o in extra]) if error: @@ -223,7 +236,8 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase): match = re.match(expected, result) if not match: raise NoMatch(_('Values do not match:\n' - '%(expected)s\n%(result)s') % locals()) + 'Template: %(expected)s\nResponse: %(result)s') + % locals()) try: matched_value = match.group('id') except IndexError: @@ -236,7 +250,8 @@ class ApiSampleTestBase(integrated_helpers._IntegratedTestBase): result = result.strip() if expected != result: raise NoMatch(_('Values do not match:\n' - '%(expected)s\n%(result)s') % locals()) + 'Template: %(expected)s\nResponse: %(result)s') + % locals()) return matched_value def _verify_something(self, subs, expected, data): @@ -384,7 +399,6 @@ class ApiSamplesTrap(ApiSampleTestBase): # removed) soon. do_not_approve_additions = [] do_not_approve_additions.append('os-create-server-ext') - do_not_approve_additions.append('os-volumes') tests = self._get_extensions_tested() extensions = self._get_extensions() @@ -760,7 +774,7 @@ class CoverageExtJsonTests(ApiSampleTestBase): self.stubs.Set(coverage_ext.CoverageController, '_check_coverage', _fake_check_coverage) - self.stubs.Set(coverage.coverage, 'xml_report', _fake_xml_report) + self.stubs.Set(coverage, 'coverage', test_coverage_ext.FakeCoverage) def test_start_coverage(self): # Start coverage data collection. @@ -1591,9 +1605,6 @@ class CloudPipeUpdateJsonTest(ApiSampleTestBase): 'nova.api.openstack.compute.contrib.cloudpipe.Cloudpipe') return f - def setUp(self): - super(CloudPipeUpdateJsonTest, self).setUp() - def test_cloud_pipe_update(self): subs = {'vpn_ip': '192.168.1.1', 'vpn_port': 2000} @@ -1868,9 +1879,6 @@ class CertificatesSamplesJsonTest(ApiSampleTestBase): extension_name = ("nova.api.openstack.compute.contrib.certificates." "Certificates") - def setUp(self): - super(CertificatesSamplesJsonTest, self).setUp() - def test_create_certificates(self): response = self._do_post('os-certificates', 'certificate-create-req', {}) @@ -3593,3 +3601,277 @@ class AttachInterfacesSampleJsonTest(ServersSampleBase): class AttachInterfacesSampleXmlTest(AttachInterfacesSampleJsonTest): ctype = 'xml' + + +class SnapshotsSampleJsonTests(ApiSampleTestBase): + extension_name = "nova.api.openstack.compute.contrib.volumes.Volumes" + + create_subs = { + 'snapshot_name': 'snap-001', + 'description': 'Daily backup', + 'volume_id': '521752a6-acf6-4b2d-bc7a-119f9148cd8c' + } + + def setUp(self): + super(SnapshotsSampleJsonTests, self).setUp() + self.stubs.Set(cinder.API, "get_all_snapshots", + fakes.stub_snapshot_get_all) + self.stubs.Set(cinder.API, "get_snapshot", fakes.stub_snapshot_get) + + def _create_snapshot(self): + self.stubs.Set(cinder.API, "create_snapshot", + fakes.stub_snapshot_create) + self.stubs.Set(cinder.API, "get", fakes.stub_volume_get) + + response = self._do_post("os-snapshots", + "snapshot-create-req", + self.create_subs) + return response + + def test_snapshots_create(self): + response = self._create_snapshot() + self.assertEqual(response.status, 200) + self.create_subs.update(self._get_regexes()) + return self._verify_response("snapshot-create-resp", + self.create_subs, response) + + def test_snapshots_delete(self): + self.stubs.Set(cinder.API, "delete_snapshot", + fakes.stub_snapshot_delete) + self._create_snapshot() + response = self._do_delete('os-snapshots/100') + self.assertEqual(response.status, 202) + self.assertEqual(response.read(), '') + + def test_snapshots_detail(self): + response = self._do_get('os-snapshots/detail') + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('snapshots-detail-resp', + subs, response) + + def test_snapshots_list(self): + response = self._do_get('os-snapshots') + self.assertEqual(response.status, 200) + subs = self._get_regexes() + return self._verify_response('snapshots-list-resp', + subs, response) + + def test_snapshots_show(self): + response = self._do_get('os-snapshots/100') + self.assertEqual(response.status, 200) + subs = { + 'snapshot_name': 'Default name', + 'description': 'Default description' + } + subs.update(self._get_regexes()) + return self._verify_response('snapshots-show-resp', + subs, response) + + +class SnapshotsSampleXmlTests(SnapshotsSampleJsonTests): + ctype = "xml" + + +class VolumeAttachmentsSampleJsonTest(ServersSampleBase): + extension_name = ("nova.api.openstack.compute.contrib.volumes.Volumes") + + def test_attach_volume_to_server(self): + device_name = '/dev/vdd' + self.stubs.Set(cinder.API, 'get', fakes.stub_volume_get) + self.stubs.Set(cinder.API, 'check_attach', lambda *a, **k: None) + self.stubs.Set(cinder.API, 'reserve_volume', lambda *a, **k: None) + self.stubs.Set(compute_manager.ComputeManager, + "reserve_block_device_name", + lambda *a, **k: device_name) + + volume = fakes.stub_volume_get(None, context.get_admin_context(), + 'a26887c6-c47b-4654-abb5-dfadf7d3f803') + subs = { + 'volume_id': volume['id'], + 'device': device_name + } + server_id = self._post_server() + response = self._do_post('servers/%s/os-volume_attachments' + % server_id, + 'attach-volume-to-server-req', subs) + + self.assertEqual(response.status, 200) + subs.update(self._get_regexes()) + self._verify_response('attach-volume-to-server-resp', + subs, response) + + def _stub_compute_api_get_instance_bdms(self, server_id): + + def fake_compute_api_get_instance_bdms(self, context, instance): + bdms = [ + {'volume_id': 'a26887c6-c47b-4654-abb5-dfadf7d3f803', + 'instance_uuid': server_id, + 'device_name': '/dev/sdd'}, + {'volume_id': 'a26887c6-c47b-4654-abb5-dfadf7d3f804', + 'instance_uuid': server_id, + 'device_name': '/dev/sdc'} + ] + return bdms + + self.stubs.Set(compute_api.API, "get_instance_bdms", + fake_compute_api_get_instance_bdms) + + def _stub_compute_api_get(self): + + def fake_compute_api_get(self, context, instance_id): + return {'uuid': instance_id} + + self.stubs.Set(compute_api.API, 'get', fake_compute_api_get) + + def test_list_volume_attachments(self): + server_id = self._post_server() + + self._stub_compute_api_get_instance_bdms(server_id) + + response = self._do_get('servers/%s/os-volume_attachments' + % server_id) + self.assertEqual(response.status, 200) + subs = self._get_regexes() + self._verify_response('list-volume-attachments-resp', + subs, response) + + def test_volume_attachment_detail(self): + server_id = self._post_server() + attach_id = "a26887c6-c47b-4654-abb5-dfadf7d3f803" + self._stub_compute_api_get_instance_bdms(server_id) + self._stub_compute_api_get() + response = self._do_get('servers/%s/os-volume_attachments/%s' + % (server_id, attach_id)) + self.assertEqual(response.status, 200) + subs = self._get_regexes() + self._verify_response('volume-attachment-detail-resp', + subs, response) + + def test_volume_attachment_delete(self): + server_id = self._post_server() + attach_id = "a26887c6-c47b-4654-abb5-dfadf7d3f803" + self._stub_compute_api_get_instance_bdms(server_id) + self._stub_compute_api_get() + self.stubs.Set(compute_api.API, 'detach_volume', lambda *a, **k: None) + response = self._do_delete('servers/%s/os-volume_attachments/%s' + % (server_id, attach_id)) + self.assertEqual(response.status, 202) + self.assertEqual(response.read(), '') + + +class VolumeAttachmentsSampleXmlTest(VolumeAttachmentsSampleJsonTest): + ctype = 'xml' + + +class VolumesSampleJsonTest(ServersSampleBase): + extension_name = ("nova.api.openstack.compute.contrib.volumes.Volumes") + + def _get_volume_id(self): + return 'a26887c6-c47b-4654-abb5-dfadf7d3f803' + + def _stub_volume(self, id, displayname="Volume Name", + displaydesc="Volume Description", size=100): + volume = { + 'id': id, + 'size': size, + 'availability_zone': 'zone1:host1', + 'instance_uuid': '3912f2b4-c5ba-4aec-9165-872876fe202e', + 'mountpoint': '/', + 'status': 'in-use', + 'attach_status': 'attached', + 'name': 'vol name', + 'display_name': displayname, + 'display_description': displaydesc, + 'created_at': "2008-12-01T11:01:55", + 'snapshot_id': None, + 'volume_type_id': 'fakevoltype', + 'volume_metadata': [], + 'volume_type': {'name': 'Backup'} + } + return volume + + def _stub_volume_get(self, context, volume_id): + return self._stub_volume(volume_id) + + def _stub_volume_delete(self, context, *args, **param): + pass + + def _stub_volume_get_all(self, context, search_opts=None): + id = self._get_volume_id() + return [self._stub_volume(id)] + + def _stub_volume_create(self, context, size, name, description, snapshot, + **param): + id = self._get_volume_id() + return self._stub_volume(id) + + def setUp(self): + super(VolumesSampleJsonTest, self).setUp() + fakes.stub_out_networking(self.stubs) + fakes.stub_out_rate_limiting(self.stubs) + + self.stubs.Set(cinder.API, "delete", self._stub_volume_delete) + self.stubs.Set(cinder.API, "get", self._stub_volume_get) + self.stubs.Set(cinder.API, "get_all", self._stub_volume_get_all) + + def _post_volume(self): + subs_req = { + 'volume_name': "Volume Name", + 'volume_desc': "Volume Description", + } + + self.stubs.Set(cinder.API, "create", self._stub_volume_create) + response = self._do_post('os-volumes', 'os-volumes-post-req', + subs_req) + self.assertEqual(response.status, 200) + subs = self._get_regexes() + subs.update(subs_req) + return self._verify_response('os-volumes-post-resp', subs, response) + + def test_volumes_show(self): + subs = { + 'volume_name': "Volume Name", + 'volume_desc': "Volume Description", + } + vol_id = self._get_volume_id() + response = self._do_get('os-volumes/%s' % vol_id) + self.assertEqual(response.status, 200) + subs.update(self._get_regexes()) + return self._verify_response('os-volumes-get-resp', subs, response) + + def test_volumes_index(self): + subs = { + 'volume_name': "Volume Name", + 'volume_desc': "Volume Description", + } + response = self._do_get('os-volumes') + self.assertEqual(response.status, 200) + subs.update(self._get_regexes()) + return self._verify_response('os-volumes-index-resp', subs, response) + + def test_volumes_detail(self): + # For now, index and detail are the same. + # See the volumes api + subs = { + 'volume_name': "Volume Name", + 'volume_desc': "Volume Description", + } + response = self._do_get('os-volumes/detail') + self.assertEqual(response.status, 200) + subs.update(self._get_regexes()) + return self._verify_response('os-volumes-detail-resp', subs, response) + + def test_volumes_create(self): + return self._post_volume() + + def test_volumes_delete(self): + self._post_volume() + vol_id = self._get_volume_id() + response = self._do_delete('os-volumes/%s' % vol_id) + self.assertEqual(response.status, 202) + self.assertEqual(response.read(), '') + + +class VolumesSampleXmlTest(VolumesSampleJsonTest): + ctype = 'xml' diff --git a/nova/tests/integrated/test_multiprocess_api.py b/nova/tests/integrated/test_multiprocess_api.py index 91e37116d..c85a43a0c 100644 --- a/nova/tests/integrated/test_multiprocess_api.py +++ b/nova/tests/integrated/test_multiprocess_api.py @@ -1,5 +1,5 @@ # Copyright (c) 2012 Intel, LLC -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/integrated/test_servers.py b/nova/tests/integrated/test_servers.py index 95c2da2a1..b45bd88f7 100644 --- a/nova/tests/integrated/test_servers.py +++ b/nova/tests/integrated/test_servers.py @@ -185,7 +185,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): def test_deferred_delete_restore(self): # Creates, deletes and restores a server. - self.flags(reclaim_instance_interval=1) + self.flags(reclaim_instance_interval=3600) fake_network.set_stub_network_methods(self.stubs) # Create server @@ -218,7 +218,7 @@ class ServersTest(integrated_helpers._IntegratedTestBase): def test_deferred_delete_force(self): # Creates, deletes and force deletes a server. - self.flags(reclaim_instance_interval=1) + self.flags(reclaim_instance_interval=3600) fake_network.set_stub_network_methods(self.stubs) # Create server diff --git a/nova/tests/monkey_patch_example/__init__.py b/nova/tests/monkey_patch_example/__init__.py index 779dc72f3..8eaaf41a1 100644 --- a/nova/tests/monkey_patch_example/__init__.py +++ b/nova/tests/monkey_patch_example/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/monkey_patch_example/example_a.py b/nova/tests/monkey_patch_example/example_a.py index 21e79bcb0..ae852a406 100644 --- a/nova/tests/monkey_patch_example/example_a.py +++ b/nova/tests/monkey_patch_example/example_a.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/monkey_patch_example/example_b.py b/nova/tests/monkey_patch_example/example_b.py index 9d8f6d339..8a171834b 100644 --- a/nova/tests/monkey_patch_example/example_b.py +++ b/nova/tests/monkey_patch_example/example_b.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/network/__init__.py b/nova/tests/network/__init__.py index adc424847..34c7255d3 100644 --- a/nova/tests/network/__init__.py +++ b/nova/tests/network/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/network/test_deprecated_api.py b/nova/tests/network/test_deprecated_api.py new file mode 100644 index 000000000..48a7e4d6d --- /dev/null +++ b/nova/tests/network/test_deprecated_api.py @@ -0,0 +1,80 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Openstack Foundation +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +"""Tests for the deprecated network API.""" + +import inspect + +from nova.network import api +from nova.network import api_deprecated +from nova import test + +# NOTE(jkoelker) These tests require that decorators in the apis +# "do the right thing" and set __name__ properly +# they should all be using functools.wraps or similar +# functionality. + + +def isapimethod(obj): + if inspect.ismethod(obj) and not obj.__name__.startswith('_'): + return True + return False + + +def discover_real_method(name, method): + if method.func_closure: + for closure in method.func_closure: + if closure.cell_contents.__name__ == name: + return closure.cell_contents + return method + + +class DeprecatedApiTestCase(test.TestCase): + def setUp(self): + super(DeprecatedApiTestCase, self).setUp() + self.api = api.API() + self.api_deprecated = api_deprecated.API() + + self.api_methods = inspect.getmembers(self.api, isapimethod) + + def test_api_compat(self): + methods = [m[0] for m in self.api_methods] + deprecated_methods = [getattr(self.api_deprecated, n, None) + for n in methods] + missing = [m[0] for m in zip(methods, deprecated_methods) + if m[1] is None] + + self.assertFalse(missing, + 'Deprecated api needs methods: %s' % missing) + + def test_method_signatures(self): + for name, method in self.api_methods: + deprecated_method = getattr(self.api_deprecated, name, None) + self.assertIsNotNone(deprecated_method, + 'Deprecated api has no method %s' % name) + + method = discover_real_method(name, method) + deprecated_method = discover_real_method(name, + deprecated_method) + + api_argspec = inspect.getargspec(method) + deprecated_argspec = inspect.getargspec(deprecated_method) + + # NOTE/TODO(jkoelker) Should probably handle the case where + # varargs/keywords are used. + self.assertEqual(api_argspec.args, deprecated_argspec.args, + "API method %s arguments differ" % name) diff --git a/nova/tests/network/test_linux_net.py b/nova/tests/network/test_linux_net.py index cba08d9ce..09b38f7a9 100644 --- a/nova/tests/network/test_linux_net.py +++ b/nova/tests/network/test_linux_net.py @@ -26,6 +26,7 @@ from nova import db from nova.network import driver from nova.network import linux_net from nova.openstack.common import fileutils +from nova.openstack.common import jsonutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils from nova import test @@ -496,7 +497,7 @@ class LinuxNetworkTestCase(test.TestCase): dev = 'br100' linux_net.restart_dhcp(self.context, dev, network_ref) expected = ['env', - 'CONFIG_FILE=%s' % CONF.dhcpbridge_flagfile, + 'CONFIG_FILE=%s' % jsonutils.dumps(CONF.dhcpbridge_flagfile), 'NETWORK_ID=fake', 'dnsmasq', '--strict-order', @@ -729,6 +730,19 @@ class LinuxNetworkTestCase(test.TestCase): ] self._test_initialize_gateway(existing, expected) + def test_ensure_floating_no_duplicate_forwards(self): + ln = linux_net + self.stubs.Set(ln.iptables_manager, 'apply', lambda: None) + self.stubs.Set(ln, 'ensure_ebtables_rules', lambda *a, **kw: None) + net = {'bridge': 'br100', 'cidr': '10.0.0.0/24'} + ln.ensure_floating_forward('10.10.10.10', '10.0.0.1', 'eth0', net) + one_forward_rules = len(linux_net.iptables_manager.ipv4['nat'].rules) + ln.ensure_floating_forward('10.10.10.11', '10.0.0.10', 'eth0', net) + two_forward_rules = len(linux_net.iptables_manager.ipv4['nat'].rules) + ln.ensure_floating_forward('10.10.10.10', '10.0.0.3', 'eth0', net) + dup_forward_rules = len(linux_net.iptables_manager.ipv4['nat'].rules) + self.assertEqual(two_forward_rules, dup_forward_rules) + def test_apply_ran(self): manager = linux_net.IptablesManager() manager.iptables_apply_deferred = False diff --git a/nova/tests/network/test_manager.py b/nova/tests/network/test_manager.py index ba997ac9d..92b8e1d91 100644 --- a/nova/tests/network/test_manager.py +++ b/nova/tests/network/test_manager.py @@ -29,7 +29,7 @@ from nova.network import floating_ips from nova.network import linux_net from nova.network import manager as network_manager from nova.network import model as net_model -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.openstack.common import importutils from nova.openstack.common import log as logging from nova.openstack.common import rpc @@ -2157,7 +2157,7 @@ class FloatingIPTestCase(test.TestCase): # address column, so fake the collision-avoidance here def fake_vif_save(vif): if vif.address == crash_test_dummy_vif['address']: - raise db_session.DBError("If you're smart, you'll retry!") + raise db_exc.DBError("If you're smart, you'll retry!") self.stubs.Set(models.VirtualInterface, 'save', fake_vif_save) # Attempt to add another and make sure that both MACs are consumed diff --git a/nova/tests/network/test_network_info.py b/nova/tests/network/test_network_info.py index d2ab6a746..021e6b5e6 100644 --- a/nova/tests/network/test_network_info.py +++ b/nova/tests/network/test_network_info.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/network/test_quantumv2.py b/nova/tests/network/test_quantumv2.py index e9e19ef45..167b418ad 100644 --- a/nova/tests/network/test_quantumv2.py +++ b/nova/tests/network/test_quantumv2.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -227,6 +227,7 @@ class TestQuantumv2(test.TestCase): 'port_id': self.port_data2[1]['id'], 'fixed_ip_address': fixed_ip_address, 'router_id': 'router_id1'} + self._returned_nw_info = [] def tearDown(self): self.addCleanup(CONF.reset) @@ -457,13 +458,14 @@ class TestQuantumv2(test.TestCase): api.get_instance_nw_info(mox.IgnoreArg(), self.instance, networks=nets, - conductor_api=mox.IgnoreArg()).AndReturn(None) + conductor_api=mox.IgnoreArg()).AndReturn( + self._returned_nw_info) self.mox.ReplayAll() return api def _allocate_for_instance(self, net_idx=1, **kwargs): api = self._stub_allocate_for_instance(net_idx, **kwargs) - api.allocate_for_instance(self.context, self.instance, **kwargs) + return api.allocate_for_instance(self.context, self.instance, **kwargs) def test_allocate_for_instance_1(self): # Allocate one port in one network env. @@ -631,6 +633,29 @@ class TestQuantumv2(test.TestCase): self.assertRaises(QUANTUM_CLIENT_EXCEPTION, api.allocate_for_instance, self.context, self.instance) + def test_allocate_for_instance_no_port_or_network(self): + class BailOutEarly(Exception): + pass + api = quantumapi.API() + self.mox.StubOutWithMock(api, '_get_available_networks') + # Make sure we get an empty list and then bail out of the rest + # of the function + api._get_available_networks(self.context, self.instance['project_id'], + []).AndRaise(BailOutEarly) + self.mox.ReplayAll() + self.assertRaises(BailOutEarly, + api.allocate_for_instance, + self.context, self.instance, + requested_networks=[(None, None, None)]) + + def test_allocate_for_instance_second_time(self): + # Make sure that allocate_for_instance only returns ports that it + # allocated during _that_ run. + new_port = {'id': 'fake'} + self._returned_nw_info = self.port_data1 + [new_port] + nw_info = self._allocate_for_instance() + self.assertEqual(nw_info, [new_port]) + def _deallocate_for_instance(self, number): port_data = number == 1 and self.port_data1 or self.port_data2 self.moxed_client.list_ports( diff --git a/nova/tests/scheduler/__init__.py b/nova/tests/scheduler/__init__.py index 7e04e7c73..4c506c9fa 100644 --- a/nova/tests/scheduler/__init__.py +++ b/nova/tests/scheduler/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/fakes.py b/nova/tests/scheduler/fakes.py index 652893662..4e4ab7c37 100644 --- a/nova/tests/scheduler/fakes.py +++ b/nova/tests/scheduler/fakes.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_chance_scheduler.py b/nova/tests/scheduler/test_chance_scheduler.py index 0ee617044..d2de055b5 100644 --- a/nova/tests/scheduler/test_chance_scheduler.py +++ b/nova/tests/scheduler/test_chance_scheduler.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_filter_scheduler.py b/nova/tests/scheduler/test_filter_scheduler.py index 849f63f5d..5256dc35f 100644 --- a/nova/tests/scheduler/test_filter_scheduler.py +++ b/nova/tests/scheduler/test_filter_scheduler.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_host_filters.py b/nova/tests/scheduler/test_host_filters.py index 8fe998daa..c977871d5 100644 --- a/nova/tests/scheduler/test_host_filters.py +++ b/nova/tests/scheduler/test_host_filters.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. # All Rights Reserved. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/scheduler/test_host_manager.py b/nova/tests/scheduler/test_host_manager.py index 088aa4da9..ddc9bd29a 100644 --- a/nova/tests/scheduler/test_host_manager.py +++ b/nova/tests/scheduler/test_host_manager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011 OpenStack, LLC +# Copyright (c) 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_least_cost.py b/nova/tests/scheduler/test_least_cost.py index d920b7255..8cee3b4d7 100644 --- a/nova/tests/scheduler/test_least_cost.py +++ b/nova/tests/scheduler/test_least_cost.py @@ -1,4 +1,4 @@ -# Copyright 2011-2012 OpenStack LLC. +# Copyright 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_multi_scheduler.py b/nova/tests/scheduler/test_multi_scheduler.py index 17e3331ed..fb25ae9da 100644 --- a/nova/tests/scheduler/test_multi_scheduler.py +++ b/nova/tests/scheduler/test_multi_scheduler.py @@ -2,7 +2,7 @@ # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_scheduler.py b/nova/tests/scheduler/test_scheduler.py index 5d0228c62..4e95061a7 100644 --- a/nova/tests/scheduler/test_scheduler.py +++ b/nova/tests/scheduler/test_scheduler.py @@ -403,6 +403,7 @@ class SchedulerTestCase(test.TestCase): 'vm_state': '', 'task_state': '', 'instance_type': {'memory_mb': 1024}, + 'instance_type_id': 1, 'image_ref': 'fake-image-ref'} def test_live_migration_basic(self): @@ -736,6 +737,7 @@ class SchedulerTestCase(test.TestCase): def test_live_migration_dest_check_auto_set_host(self): # Confirm dest is picked by scheduler if not set. self.mox.StubOutWithMock(self.driver, 'select_hosts') + self.mox.StubOutWithMock(db, 'instance_type_get') instance = self._live_migration_instance() request_spec = {'instance_properties': instance, @@ -747,6 +749,8 @@ class SchedulerTestCase(test.TestCase): ignore_hosts = [instance['host']] filter_properties = {'ignore_hosts': ignore_hosts} + db.instance_type_get(self.context, 1).AndReturn( + instance['instance_type']) self.driver.select_hosts(self.context, request_spec, filter_properties).AndReturn(['fake_host2']) @@ -757,6 +761,7 @@ class SchedulerTestCase(test.TestCase): def test_live_migration_auto_set_dest(self): # Confirm scheduler picks target host if none given. + self.mox.StubOutWithMock(db, 'instance_type_get') self.mox.StubOutWithMock(self.driver, '_live_migration_src_check') self.mox.StubOutWithMock(self.driver, 'select_hosts') self.mox.StubOutWithMock(self.driver, '_live_migration_common_check') @@ -776,6 +781,9 @@ class SchedulerTestCase(test.TestCase): self.driver._live_migration_src_check(self.context, instance) + db.instance_type_get(self.context, 1).MultipleTimes().AndReturn( + instance['instance_type']) + # First selected host raises exception.InvalidHypervisorType self.driver.select_hosts(self.context, request_spec, {'ignore_hosts': [instance['host']]}).AndReturn(['fake_host2']) diff --git a/nova/tests/scheduler/test_scheduler_options.py b/nova/tests/scheduler/test_scheduler_options.py index 17c1bb731..df54cde5f 100644 --- a/nova/tests/scheduler/test_scheduler_options.py +++ b/nova/tests/scheduler/test_scheduler_options.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/scheduler/test_weights.py b/nova/tests/scheduler/test_weights.py index 8699ed811..3ea6c945f 100644 --- a/nova/tests/scheduler/test_weights.py +++ b/nova/tests/scheduler/test_weights.py @@ -1,4 +1,4 @@ -# Copyright 2011-2012 OpenStack LLC. +# Copyright 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/servicegroup/__init__.py b/nova/tests/servicegroup/__init__.py index 4549abf92..efbc9063d 100644 --- a/nova/tests/servicegroup/__init__.py +++ b/nova/tests/servicegroup/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/servicegroup/test_db_servicegroup.py b/nova/tests/servicegroup/test_db_servicegroup.py index d14427439..a7ab3ff6f 100644 --- a/nova/tests/servicegroup/test_db_servicegroup.py +++ b/nova/tests/servicegroup/test_db_servicegroup.py @@ -1,4 +1,4 @@ -# Copyright (c) IBM 2012 Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/servicegroup/test_mc_servicegroup.py b/nova/tests/servicegroup/test_mc_servicegroup.py index 255184219..9d5601ff8 100644 --- a/nova/tests/servicegroup/test_mc_servicegroup.py +++ b/nova/tests/servicegroup/test_mc_servicegroup.py @@ -1,7 +1,7 @@ # Copyright (c) 2013 Akira Yoshiyama <akirayoshiyama at gmail dot com> # # This is derived from test_db_servicegroup.py. -# Copyright (c) IBM 2012 Alexey Roytman <roytman at il dot ibm dot com> +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/servicegroup/test_zk_driver.py b/nova/tests/servicegroup/test_zk_driver.py index 7330da66a..cdb919307 100644 --- a/nova/tests/servicegroup/test_zk_driver.py +++ b/nova/tests/servicegroup/test_zk_driver.py @@ -1,5 +1,5 @@ # Copyright (c) AT&T 2012-2013 Yun Mao <yunmao@gmail.com> -# Copyright (c) IBM 2012 Alexey Roytman <roytman at il dot ibm dot com>. +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -38,7 +38,7 @@ class ZKServiceGroupTestCase(test.TestCase): servicegroup.API._driver = None try: from nova.servicegroup.drivers import zk - _unused = zk + _unused = zk.ZooKeeperDriver() except ImportError: self.skipTest("Unable to test due to lack of ZooKeeper") self.flags(servicegroup_driver='zk') diff --git a/nova/tests/test_cinder.py b/nova/tests/test_cinder.py index 79b5ae66a..06eb467ab 100644 --- a/nova/tests/test_cinder.py +++ b/nova/tests/test_cinder.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_context.py b/nova/tests/test_context.py index 527534fd5..99b5c705c 100644 --- a/nova/tests/test_context.py +++ b/nova/tests/test_context.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_crypto.py b/nova/tests/test_crypto.py index cec3ca9c1..e328babfe 100644 --- a/nova/tests/test_crypto.py +++ b/nova/tests/test_crypto.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_db_api.py b/nova/tests/test_db_api.py index 346e0b2b7..769ddaea2 100644 --- a/nova/tests/test_db_api.py +++ b/nova/tests/test_db_api.py @@ -451,41 +451,6 @@ class DbApiTestCase(test.TestCase): self.assertEquals("building", old_ref["vm_state"]) self.assertEquals("needscoffee", new_ref["vm_state"]) - def test_instance_update_with_extra_specs(self): - # Ensure _extra_specs are returned from _instance_update. - ctxt = context.get_admin_context() - - # create a flavor - inst_type_dict = dict( - name="test_flavor", - memory_mb=1, - vcpus=1, - root_gb=1, - ephemeral_gb=1, - flavorid=105) - inst_type_ref = db.instance_type_create(ctxt, inst_type_dict) - - # add some extra spec to our flavor - spec = {'test_spec': 'foo'} - db.instance_type_extra_specs_update_or_create( - ctxt, - inst_type_ref['flavorid'], - spec) - - # create instance, just populates db, doesn't pull extra_spec - instance = db.instance_create( - ctxt, - {'instance_type_id': inst_type_ref['id']}) - self.assertNotIn('extra_specs', instance) - - # update instance, used when starting instance to set state, etc - (old_ref, new_ref) = db.instance_update_and_get_original( - ctxt, - instance['uuid'], - {}) - self.assertEquals(spec, old_ref['extra_specs']) - self.assertEquals(spec, new_ref['extra_specs']) - def _test_instance_update_updates_metadata(self, metadata_type): ctxt = context.get_admin_context() @@ -734,7 +699,7 @@ class DbApiTestCase(test.TestCase): self.assertEqual('schedule', events[0]['event']) self.assertEqual(start_time, events[0]['start_time']) - def test_instance_action_event_finish(self): + def test_instance_action_event_finish_success(self): """Finish an instance action event.""" ctxt = context.get_admin_context() uuid = str(stdlib_uuid.uuid4()) @@ -758,15 +723,55 @@ class DbApiTestCase(test.TestCase): event_finish_values = {'event': 'schedule', 'request_id': ctxt.request_id, 'instance_uuid': uuid, - 'finish_time': finish_time} + 'finish_time': finish_time, + 'result': 'Success'} + db.action_event_finish(ctxt, event_finish_values) + + # Retrieve the event to ensure it was successfully added + events = db.action_events_get(ctxt, action['id']) + action = db.action_get_by_request_id(ctxt, uuid, ctxt.request_id) + self.assertEqual(1, len(events)) + self.assertEqual('schedule', events[0]['event']) + self.assertEqual(start_time, events[0]['start_time']) + self.assertEqual(finish_time, events[0]['finish_time']) + self.assertNotEqual(action['message'], 'Error') + + def test_instance_action_event_finish_error(self): + """Finish an instance action event with an error.""" + ctxt = context.get_admin_context() + uuid = str(stdlib_uuid.uuid4()) + + start_time = timeutils.utcnow() + action_values = {'action': 'run_instance', + 'instance_uuid': uuid, + 'request_id': ctxt.request_id, + 'user_id': ctxt.user_id, + 'project_id': ctxt.project_id, + 'start_time': start_time} + action = db.action_start(ctxt, action_values) + + event_values = {'event': 'schedule', + 'request_id': ctxt.request_id, + 'instance_uuid': uuid, + 'start_time': start_time} + db.action_event_start(ctxt, event_values) + + finish_time = timeutils.utcnow() + datetime.timedelta(seconds=5) + event_finish_values = {'event': 'schedule', + 'request_id': ctxt.request_id, + 'instance_uuid': uuid, + 'finish_time': finish_time, + 'result': 'Error'} db.action_event_finish(ctxt, event_finish_values) # Retrieve the event to ensure it was successfully added events = db.action_events_get(ctxt, action['id']) + action = db.action_get_by_request_id(ctxt, uuid, ctxt.request_id) self.assertEqual(1, len(events)) self.assertEqual('schedule', events[0]['event']) self.assertEqual(start_time, events[0]['start_time']) self.assertEqual(finish_time, events[0]['finish_time']) + self.assertEqual(action['message'], 'Error') def test_instance_action_and_event_start_string_time(self): """Create an instance action and event with a string start_time.""" diff --git a/nova/tests/test_driver.py b/nova/tests/test_driver.py index 2dee7725f..6fd8b00b1 100644 --- a/nova/tests/test_driver.py +++ b/nova/tests/test_driver.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2013 Citrix Systems, Inc. -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_exception.py b/nova/tests/test_exception.py index ad67cff26..6f5a9909e 100644 --- a/nova/tests/test_exception.py +++ b/nova/tests/test_exception.py @@ -133,3 +133,10 @@ class NovaExceptionTestCase(test.TestCase): exc = FakeNovaException(code=404) self.assertEquals(exc.kwargs['code'], 404) + + def test_cleanse_dict(self): + kwargs = {'foo': 1, 'blah_pass': 2, 'zoo_password': 3, '_pass': 4} + self.assertEquals(exception._cleanse_dict(kwargs), {'foo': 1}) + + kwargs = {} + self.assertEquals(exception._cleanse_dict(kwargs), {}) diff --git a/nova/tests/test_fakelibvirt.py b/nova/tests/test_fakelibvirt.py index 32c85a95a..ee2008544 100644 --- a/nova/tests/test_fakelibvirt.py +++ b/nova/tests/test_fakelibvirt.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_filters.py b/nova/tests/test_filters.py index 13fd122c8..d20836168 100644 --- a/nova/tests/test_filters.py +++ b/nova/tests/test_filters.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. # All Rights Reserved. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_hooks.py b/nova/tests/test_hooks.py index 0b61d6924..1f4625294 100644 --- a/nova/tests/test_hooks.py +++ b/nova/tests/test_hooks.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_hypervapi.py b/nova/tests/test_hypervapi.py index 5912bb301..c6d75aea1 100644 --- a/nova/tests/test_hypervapi.py +++ b/nova/tests/test_hypervapi.py @@ -56,7 +56,7 @@ from nova.virt.hyperv import volumeutilsv2 from nova.virt import images CONF = cfg.CONF -CONF.import_opt('vswitch_name', 'nova.virt.hyperv.vif') +CONF.import_opt('vswitch_name', 'nova.virt.hyperv.vif', 'hyperv') class HyperVAPITestCase(test.TestCase): @@ -86,9 +86,11 @@ class HyperVAPITestCase(test.TestCase): self._setup_stubs() self.flags(instances_path=r'C:\Hyper-V\test\instances', - vswitch_name='external', - network_api_class='nova.network.quantumv2.api.API', - force_volumeutils_v1=True) + network_api_class='nova.network.quantumv2.api.API') + + self.flags(vswitch_name='external', + force_volumeutils_v1=True, + group='hyperv') self._conn = driver_hyperv.HyperVDriver(None) @@ -154,6 +156,8 @@ class HyperVAPITestCase(test.TestCase): self._mox.StubOutWithMock(vhdutils.VHDUtils, 'merge_vhd') self._mox.StubOutWithMock(vhdutils.VHDUtils, 'get_vhd_parent_path') self._mox.StubOutWithMock(vhdutils.VHDUtils, 'get_vhd_info') + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'resize_vhd') + self._mox.StubOutWithMock(vhdutils.VHDUtils, 'validate_vhd') self._mox.StubOutWithMock(hostutils.HostUtils, 'get_cpus_info') self._mox.StubOutWithMock(hostutils.HostUtils, @@ -331,7 +335,7 @@ class HyperVAPITestCase(test.TestCase): cdb.__exit__(None, None, None).AndReturn(None) if not use_cdrom: - utils.execute(CONF.qemu_img_cmd, + utils.execute(CONF.hyperv.qemu_img_cmd, 'convert', '-f', 'raw', @@ -351,7 +355,7 @@ class HyperVAPITestCase(test.TestCase): def _test_spawn_config_drive(self, use_cdrom): self.flags(force_config_drive=True) - self.flags(config_drive_cdrom=use_cdrom) + self.flags(config_drive_cdrom=use_cdrom, group='hyperv') self.flags(mkisofs_cmd='mkisofs.exe') self._setup_spawn_config_drive_mocks(use_cdrom) @@ -391,7 +395,7 @@ class HyperVAPITestCase(test.TestCase): fake_vswitch_port = 'fake port' m = networkutils.NetworkUtils.get_external_vswitch( - CONF.vswitch_name) + CONF.hyperv.vswitch_name) m.AndReturn(fake_vswitch_path) m = networkutils.NetworkUtils.create_vswitch_port( @@ -410,7 +414,7 @@ class HyperVAPITestCase(test.TestCase): def setup_vif_mocks(): m = networkutils.NetworkUtils.get_external_vswitch( - CONF.vswitch_name) + CONF.hyperv.vswitch_name) m.AndRaise(vmutils.HyperVException(_('fake vswitch not found'))) self.assertRaises(vmutils.HyperVException, self._test_spawn_instance, @@ -516,7 +520,7 @@ class HyperVAPITestCase(test.TestCase): self._setup_destroy_mocks() self._mox.ReplayAll() - self._conn.destroy(self._instance_data) + self._conn.destroy(self._instance_data, None) self._mox.VerifyAll() def test_live_migration(self): @@ -567,6 +571,8 @@ class HyperVAPITestCase(test.TestCase): self.flags(use_cow_images=cow) instance_data = self._get_instance_data() + instance = db.instance_create(self._context, instance_data) + instance['system_metadata'] = {} network_info = fake_network.fake_get_instance_nw_info(self.stubs, spectacular=True) @@ -579,10 +585,14 @@ class HyperVAPITestCase(test.TestCase): None) m.AndReturn(False) - vhdutils.VHDUtils.get_vhd_info(mox.Func(self._check_img_path)) + m = vhdutils.VHDUtils.get_vhd_info(mox.Func(self._check_img_path)) + m.AndReturn({'MaxInternalSize': 1024}) + + fake.PathUtils.copyfile(mox.IsA(str), mox.IsA(str)) + vhdutils.VHDUtils.resize_vhd(mox.IsA(str), mox.IsA(object)) self._mox.ReplayAll() - self._conn.pre_live_migration(self._context, instance_data, + self._conn.pre_live_migration(self._context, instance, None, network_info) self._mox.VerifyAll() @@ -697,6 +707,7 @@ class HyperVAPITestCase(test.TestCase): self._instance_data = self._get_instance_data() instance = db.instance_create(self._context, self._instance_data) + instance['system_metadata'] = {} image = db_fakes.get_fake_image_data(self._project_id, self._user_id) @@ -763,12 +774,16 @@ class HyperVAPITestCase(test.TestCase): m.AndReturn(boot_from_volume) if not boot_from_volume: - vhdutils.VHDUtils.get_vhd_info(mox.Func(self._check_img_path)) + m = vhdutils.VHDUtils.get_vhd_info(mox.Func(self._check_img_path)) + m.AndReturn({'MaxInternalSize': 1024}) if cow: - vhdutils.VHDUtils.create_differencing_vhd( - mox.IsA(str), mox.Func(self._check_img_path)) + fake.PathUtils.copyfile(mox.IsA(str), mox.IsA(str)) + vhdutils.VHDUtils.resize_vhd(mox.IsA(str), mox.IsA(object)) + vhdutils.VHDUtils.create_differencing_vhd(mox.IsA(str), + mox.IsA(str)) else: + vhdutils.VHDUtils.resize_vhd(mox.IsA(str), mox.IsA(object)) fake.PathUtils.copyfile(mox.IsA(str), mox.IsA(str)) self._setup_create_instance_mocks(setup_vif_mocks_func, @@ -1009,6 +1024,7 @@ class HyperVAPITestCase(test.TestCase): def test_finish_migration(self): self._instance_data = self._get_instance_data() instance = db.instance_create(self._context, self._instance_data) + instance['system_metadata'] = {} network_info = fake_network.fake_get_instance_nw_info( self.stubs, spectacular=True) @@ -1032,6 +1048,12 @@ class HyperVAPITestCase(test.TestCase): vhdutils.VHDUtils.reconnect_parent_vhd(mox.IsA(str), mox.IsA(str)) + m = vhdutils.VHDUtils.get_vhd_info(mox.IsA(str)) + m.AndReturn({'MaxInternalSize': 1024}) + + m = fake.PathUtils.exists(mox.IsA(str)) + m.AndReturn(True) + self._set_vm_name(instance['name']) self._setup_create_instance_mocks(None, False) diff --git a/nova/tests/test_iptables_network.py b/nova/tests/test_iptables_network.py index 7e62d3a6e..e64dcf66b 100644 --- a/nova/tests/test_iptables_network.py +++ b/nova/tests/test_iptables_network.py @@ -68,19 +68,19 @@ class IptablesManagerTestCase(test.TestCase): ':OUTPUT ACCEPT [63491:4191863]', ':POSTROUTING ACCEPT [63112:4108641]', ':%s-OUTPUT - [0:0]' % (binary_name), - ':%s-float-snat - [0:0]' % (binary_name), ':%s-snat - [0:0]' % (binary_name), ':%s-PREROUTING - [0:0]' % (binary_name), + ':%s-float-snat - [0:0]' % (binary_name), ':%s-POSTROUTING - [0:0]' % (binary_name), ':nova-postrouting-bottom - [0:0]', '[0:0] -A PREROUTING -j %s-PREROUTING' % (binary_name), '[0:0] -A OUTPUT -j %s-OUTPUT' % (binary_name), '[0:0] -A POSTROUTING -j %s-POSTROUTING' % (binary_name), - '[0:0] -A POSTROUTING -j nova-postrouting-bottom', '[0:0] -A nova-postrouting-bottom ' - '-j %s-SNATTING' % (binary_name), - '[0:0] -A %s-SNATTING ' - '-j %s-floating-ip-snat' % (binary_name, binary_name), + '-j %s-snat' % (binary_name), + '[0:0] -A %s-snat ' + '-j %s-float-snat' % (binary_name, binary_name), + '[0:0] -A POSTROUTING -j nova-postrouting-bottom', 'COMMIT', '# Completed on Fri Feb 18 15:17:05 2011'] @@ -103,6 +103,33 @@ class IptablesManagerTestCase(test.TestCase): '-s 1.2.3.4/5 -j DROP' % self.binary_name not in new_lines) + def test_remove_rules_regex(self): + current_lines = self.sample_nat + table = self.manager.ipv4['nat'] + table.add_rule('float-snat', '-s 10.0.0.1 -j SNAT --to 10.10.10.10' + ' -d 10.0.0.1') + table.add_rule('float-snat', '-s 10.0.0.1 -j SNAT --to 10.10.10.10' + ' -o eth0') + table.add_rule('PREROUTING', '-d 10.10.10.10 -j DNAT --to 10.0.0.1') + table.add_rule('OUTPUT', '-d 10.10.10.10 -j DNAT --to 10.0.0.1') + table.add_rule('float-snat', '-s 10.0.0.10 -j SNAT --to 10.10.10.11' + ' -d 10.0.0.10') + table.add_rule('float-snat', '-s 10.0.0.10 -j SNAT --to 10.10.10.11' + ' -o eth0') + table.add_rule('PREROUTING', '-d 10.10.10.11 -j DNAT --to 10.0.0.10') + table.add_rule('OUTPUT', '-d 10.10.10.11 -j DNAT --to 10.0.0.10') + new_lines = self.manager._modify_rules(current_lines, table) + self.assertEqual(len(new_lines) - len(current_lines), 8) + regex = '.*\s+%s(/32|\s+|$)' + num_removed = table.remove_rules_regex(regex % '10.10.10.10') + self.assertEqual(num_removed, 4) + new_lines = self.manager._modify_rules(current_lines, table) + self.assertEqual(len(new_lines) - len(current_lines), 4) + num_removed = table.remove_rules_regex(regex % '10.10.10.11') + self.assertEqual(num_removed, 4) + new_lines = self.manager._modify_rules(current_lines, table) + self.assertEqual(new_lines, current_lines) + def test_nat_rules(self): current_lines = self.sample_nat new_lines = self.manager._modify_rules(current_lines, diff --git a/nova/tests/test_ipv6.py b/nova/tests/test_ipv6.py index b16855eb4..df3d34c1f 100644 --- a/nova/tests/test_ipv6.py +++ b/nova/tests/test_ipv6.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack LLC +# Copyright (c) 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py index cad556851..2b405152e 100644 --- a/nova/tests/test_libvirt.py +++ b/nova/tests/test_libvirt.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # Copyright 2012 University Of Minho # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -171,9 +171,6 @@ class CacheConcurrencyTestCase(test.TestCase): 'nova.virt.libvirt.imagebackend.libvirt_utils', fake_libvirt_utils)) - def tearDown(self): - super(CacheConcurrencyTestCase, self).tearDown() - def test_same_fname_concurrency(self): # Ensures that the same fname cache runs at a sequentially. uuid = uuidutils.generate_uuid() @@ -3948,8 +3945,10 @@ class IptablesFirewallTestCase(test.TestCase): ipv6 = self.fw.iptables.ipv6['filter'].rules ipv4_network_rules = len(ipv4) - len(inst_ipv4) - ipv4_len ipv6_network_rules = len(ipv6) - len(inst_ipv6) - ipv6_len - self.assertEquals(ipv4_network_rules, - ipv4_rules_per_addr * ipv4_addr_per_network * networks_count) + # Extra rules are for the DHCP request + rules = (ipv4_rules_per_addr * ipv4_addr_per_network * + networks_count) + 2 + self.assertEquals(ipv4_network_rules, rules) self.assertEquals(ipv6_network_rules, ipv6_rules_per_addr * ipv6_addr_per_network * networks_count) @@ -4840,6 +4839,53 @@ class LibvirtDriverTestCase(test.TestCase): self.libvirtconnection.finish_revert_migration(ins_ref, None) + def _test_finish_revert_migration_after_crash(self, backup_made, new_made): + class FakeLoopingCall: + def start(self, *a, **k): + return self + + def wait(self): + return None + + self.mox.StubOutWithMock(libvirt_utils, 'get_instance_path') + self.mox.StubOutWithMock(os.path, 'exists') + self.mox.StubOutWithMock(shutil, 'rmtree') + self.mox.StubOutWithMock(utils, 'execute') + + self.stubs.Set(blockinfo, 'get_disk_info', lambda *a: None) + self.stubs.Set(self.libvirtconnection, 'to_xml', lambda *a, **k: None) + self.stubs.Set(self.libvirtconnection, '_create_domain_and_network', + lambda *a: None) + self.stubs.Set(utils, 'FixedIntervalLoopingCall', + lambda *a, **k: FakeLoopingCall()) + + libvirt_utils.get_instance_path({}).AndReturn('/fake/foo') + os.path.exists('/fake/foo_resize').AndReturn(backup_made) + if backup_made: + os.path.exists('/fake/foo').AndReturn(new_made) + if new_made: + shutil.rmtree('/fake/foo') + utils.execute('mv', '/fake/foo_resize', '/fake/foo') + + self.mox.ReplayAll() + + self.libvirtconnection.finish_revert_migration({}, []) + + def test_finish_revert_migration_after_crash(self): + self._test_finish_revert_migration_after_crash(True, True) + + def test_finish_revert_migration_after_crash_before_new(self): + self._test_finish_revert_migration_after_crash(True, False) + + def test_finish_revert_migration_after_crash_before_backup(self): + self._test_finish_revert_migration_after_crash(False, False) + + def test_cleanup_failed_migration(self): + self.mox.StubOutWithMock(shutil, 'rmtree') + shutil.rmtree('/fake/inst') + self.mox.ReplayAll() + self.libvirtconnection._cleanup_failed_migration('/fake/inst') + def test_confirm_migration(self): ins_ref = self._create_instance() diff --git a/nova/tests/test_libvirt_blockinfo.py b/nova/tests/test_libvirt_blockinfo.py index 5560e63fd..0165d77b6 100644 --- a/nova/tests/test_libvirt_blockinfo.py +++ b/nova/tests/test_libvirt_blockinfo.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # Copyright 2012 University Of Minho # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -419,13 +419,13 @@ class LibvirtBlockInfoTest(test.TestCase): device_type='cdrom') self.assertEqual(bus, 'ide') - image_meta = {'properties': {'disk_bus': 'scsi'}} + image_meta = {'properties': {'hw_disk_bus': 'scsi'}} bus = blockinfo.get_disk_bus_for_device_type('kvm', image_meta) self.assertEqual(bus, 'scsi') - image_meta = {'properties': {'disk_bus': 'usb', - 'cdrom_bus': 'scsi'}} + image_meta = {'properties': {'hw_disk_bus': 'usb', + 'hw_cdrom_bus': 'scsi'}} bus = blockinfo.get_disk_bus_for_device_type('kvm', image_meta, device_type='cdrom') @@ -435,7 +435,7 @@ class LibvirtBlockInfoTest(test.TestCase): image_meta) self.assertEqual(bus, 'usb') - image_meta = {'properties': {'disk_bus': 'xen'}} + image_meta = {'properties': {'hw_disk_bus': 'xen'}} self.assertRaises(exception.UnsupportedHardware, blockinfo.get_disk_bus_for_device_type, 'kvm', diff --git a/nova/tests/test_libvirt_vif.py b/nova/tests/test_libvirt_vif.py index 026e55e9c..6160105ce 100644 --- a/nova/tests/test_libvirt_vif.py +++ b/nova/tests/test_libvirt_vif.py @@ -277,7 +277,7 @@ class LibvirtVifTestCase(test.TestCase): return fakelibvirt.Connection("qemu:///session", False) d = vif.LibvirtGenericVIFDriver(get_connection) - image_meta = {'properties': {'vif_model': 'e1000'}} + image_meta = {'properties': {'hw_vif_model': 'e1000'}} xml = self._get_instance_xml(d, self.net_bridge, self.mapping_bridge, @@ -301,7 +301,7 @@ class LibvirtVifTestCase(test.TestCase): return fakelibvirt.Connection("qemu:///session", False) d = vif.LibvirtGenericVIFDriver(get_connection) - image_meta = {'properties': {'vif_model': 'acme'}} + image_meta = {'properties': {'hw_vif_model': 'acme'}} self.assertRaises(exception.UnsupportedHardware, self._get_instance_xml, d, diff --git a/nova/tests/test_libvirt_volume.py b/nova/tests/test_libvirt_volume.py index 28d0c8088..1186ed268 100644 --- a/nova/tests/test_libvirt_volume.py +++ b/nova/tests/test_libvirt_volume.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # Copyright 2012 University Of Minho # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_loadables.py b/nova/tests/test_loadables.py index 6d16b9fa8..6b7a96a65 100644 --- a/nova/tests/test_loadables.py +++ b/nova/tests/test_loadables.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC. # All Rights Reserved. +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py index 7c75a64ea..cf5c2f509 100644 --- a/nova/tests/test_migrations.py +++ b/nova/tests/test_migrations.py @@ -1,6 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack, LLC +# Copyright 2010-2011 OpenStack Foundation +# Copyright 2012-2013 IBM Corp. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -44,16 +45,19 @@ import collections import commands import ConfigParser import datetime -import netaddr import os -import sqlalchemy -import sqlalchemy.exc import urlparse import uuid from migrate.versioning import repository +import netaddr +import sqlalchemy +from sqlalchemy.dialects import postgresql +from sqlalchemy.dialects import sqlite +import sqlalchemy.exc import nova.db.sqlalchemy.migrate_repo +from nova.openstack.common import lockutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils from nova import test @@ -244,11 +248,36 @@ class BaseMigrationTestCase(test.TestCase): self._reset_databases() super(BaseMigrationTestCase, self).tearDown() + def execute_cmd(self, cmd=None): + status, output = commands.getstatusoutput(cmd) + LOG.debug(output) + self.assertEqual(0, status, + "Failed to run: %s\n%s" % (cmd, output)) + + @lockutils.synchronized('pgadmin', 'nova-', external=True) + def _reset_pg(self, conn_pieces): + (user, password, database, host) = \ + get_pgsql_connection_info(conn_pieces) + os.environ['PGPASSWORD'] = password + os.environ['PGUSER'] = user + # note(boris-42): We must create and drop database, we can't + # drop database which we have connected to, so for such + # operations there is a special database template1. + sqlcmd = ("psql -w -U %(user)s -h %(host)s -c" + " '%(sql)s' -d template1") + + sql = ("drop database if exists %(database)s;") % locals() + droptable = sqlcmd % locals() + self.execute_cmd(droptable) + + sql = ("create database %(database)s;") % locals() + createtable = sqlcmd % locals() + self.execute_cmd(createtable) + + os.unsetenv('PGPASSWORD') + os.unsetenv('PGUSER') + def _reset_databases(self): - def execute_cmd(cmd=None): - status, output = commands.getstatusoutput(cmd) - LOG.debug(output) - self.assertEqual(0, status) for key, engine in self.engines.items(): conn_string = self.test_databases[key] conn_pieces = urlparse.urlparse(conn_string) @@ -271,29 +300,9 @@ class BaseMigrationTestCase(test.TestCase): "create database %(database)s;") % locals() cmd = ("mysql -u \"%(user)s\" %(password)s -h %(host)s " "-e \"%(sql)s\"") % locals() - execute_cmd(cmd) + self.execute_cmd(cmd) elif conn_string.startswith('postgresql'): - # note(krtaylor): File creation problems with tests in - # venv using .pgpass authentication, changed to - # PGPASSWORD environment variable which is no longer - # planned to be deprecated - (user, password, database, host) = \ - get_pgsql_connection_info(conn_pieces) - os.environ['PGPASSWORD'] = password - os.environ['PGUSER'] = user - # note(boris-42): We must create and drop database, we can't - # drop database which we have connected to, so for such - # operations there is a special database template1. - sqlcmd = ("psql -w -U %(user)s -h %(host)s -c" - " '%(sql)s' -d template1") - sql = ("drop database if exists %(database)s;") % locals() - droptable = sqlcmd % locals() - execute_cmd(droptable) - sql = ("create database %(database)s;") % locals() - createtable = sqlcmd % locals() - execute_cmd(createtable) - os.unsetenv('PGPASSWORD') - os.unsetenv('PGUSER') + self._reset_pg(conn_pieces) def _test_mysql_opportunistically(self): # Test that table creation on mysql only builds InnoDB tables @@ -363,36 +372,37 @@ class BaseMigrationTestCase(test.TestCase): self.migration_api.db_version(engine, self.REPOSITORY)) - self.migration_api.upgrade(engine, - self.REPOSITORY, - self.INIT_VERSION + 1) - LOG.debug('latest version is %s' % self.REPOSITORY.latest) + versions = range(self.INIT_VERSION + 1, self.REPOSITORY.latest + 1) - for version in xrange(self.INIT_VERSION + 2, - self.REPOSITORY.latest + 1): + for version in versions: # upgrade -> downgrade -> upgrade self._migrate_up(engine, version, with_data=True) if snake_walk: - self._migrate_down(engine, version - 1) - self._migrate_up(engine, version) + downgraded = self._migrate_down( + engine, version - 1, with_data=True) + if downgraded: + self._migrate_up(engine, version) if downgrade: # Now walk it back down to 0 from the latest, testing # the downgrade paths. - for version in reversed( - xrange(self.INIT_VERSION + 2, - self.REPOSITORY.latest + 1)): + for version in reversed(versions): # downgrade -> upgrade -> downgrade - self._migrate_down(engine, version - 1) - if snake_walk: + downgraded = self._migrate_down(engine, version - 1) + + if snake_walk and downgraded: self._migrate_up(engine, version) self._migrate_down(engine, version - 1) - def _migrate_down(self, engine, version): - self.migration_api.downgrade(engine, - self.REPOSITORY, - version) + def _migrate_down(self, engine, version, with_data=False): + try: + self.migration_api.downgrade(engine, self.REPOSITORY, version) + except NotImplementedError: + # NOTE(sirp): some migrations, namely release-level + # migrations, don't support a downgrade. + return False + self.assertEqual(version, self.migration_api.db_version(engine, self.REPOSITORY)) @@ -400,10 +410,13 @@ class BaseMigrationTestCase(test.TestCase): # NOTE(sirp): `version` is what we're downgrading to (i.e. the 'target' # version). So if we have any downgrade checks, they need to be run for # the previous (higher numbered) migration. - post_downgrade = getattr( - self, "_post_downgrade_%d" % (version + 1), None) - if post_downgrade: - post_downgrade(engine) + if with_data: + post_downgrade = getattr( + self, "_post_downgrade_%03d" % (version + 1), None) + if post_downgrade: + post_downgrade(engine) + + return True def _migrate_up(self, engine, version, with_data=False): """migrate up to a new version of the db. @@ -417,20 +430,17 @@ class BaseMigrationTestCase(test.TestCase): try: if with_data: data = None - pre_upgrade = getattr(self, "_pre_upgrade_%d" % version, None) + pre_upgrade = getattr( + self, "_pre_upgrade_%03d" % version, None) if pre_upgrade: data = pre_upgrade(engine) - self.migration_api.upgrade(engine, - self.REPOSITORY, - version) - self.assertEqual( - version, - self.migration_api.db_version(engine, - self.REPOSITORY)) - + self.migration_api.upgrade(engine, self.REPOSITORY, version) + self.assertEqual(version, + self.migration_api.db_version(engine, + self.REPOSITORY)) if with_data: - check = getattr(self, "_check_%d" % version, None) + check = getattr(self, "_check_%03d" % version, None) if check: check(engine, data) except Exception: @@ -588,8 +598,24 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): services = get_table(engine, 'services') engine.execute(services.insert(), data) + self._pre_upgrade_147_no_duplicate_aggregate_hosts(engine) return data + def _pre_upgrade_147_no_duplicate_aggregate_hosts(self, engine): + engine.execute(get_table(engine, 'aggregate_metadata').insert(), [ + {'aggregate_id': 1, + 'key': 'availability_zone', + 'value': 'custom_az'}]) + + engine.execute(get_table(engine, 'aggregate_hosts').insert(), [ + {'aggregate_id': 1, + 'host': 'compute-host3'}]) + + engine.execute(get_table(engine, 'services').insert(), [ + {'id': 99, 'host': 'compute-host3', + 'binary': 'nova-compute', 'topic': 'compute', + 'report_count': 0, 'availability_zone': 'custom_az'}]) + def _check_147(self, engine, data): aggregate_md = get_table(engine, 'aggregate_metadata') aggregate_hosts = get_table(engine, 'aggregate_hosts') @@ -612,6 +638,15 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): ).execute().first() self.assertEqual(host, None) + self._check_147_no_duplicate_aggregate_hosts(engine, data) + + def _check_147_no_duplicate_aggregate_hosts(self, engine, data): + aggregate_hosts = get_table(engine, 'aggregate_hosts') + agg1_hosts = [h['host'] for h in aggregate_hosts.select( + aggregate_hosts.c.aggregate_id == 1 + ).execute().fetchall()] + self.assertEqual(['compute-host3'], agg1_hosts) + # migration 149, changes IPAddr storage format def _pre_upgrade_149(self, engine): provider_fw_rules = get_table(engine, 'provider_fw_rules') @@ -814,7 +849,6 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): meta.reflect(engine) table_names = set(meta.tables.keys()) for table_name in table_names: - print table_name if table_name.startswith("shadow_"): shadow_name = table_name base_name = table_name.replace("shadow_", "") @@ -901,11 +935,108 @@ class TestNovaMigrations(BaseMigrationTestCase, CommonTestsMixIn): fetchall() self.assertEqual(len(rows), 1) + def _pre_upgrade_159(self, engine): + data = { + 'provider_fw_rules': + [ + {'protocol': 'tcp', 'from_port': 1234, + 'to_port': 1234, 'cidr': "127.0.0.1/30"}, + {'protocol': 'tcp', 'from_port': 1234, + 'to_port': 1234, 'cidr': "128.128.128.128/16"}, + {'protocol': 'tcp', 'from_port': 1234, + 'to_port': 1234, 'cidr': "128.128.128.128/32"}, + {'protocol': 'tcp', 'from_port': 1234, + 'to_port': 1234, 'cidr': "2001:db8::1:2/48"}, + {'protocol': 'tcp', 'from_port': 1234, + 'to_port': 1234, 'cidr': "::1/64"}, + {'protocol': 'tcp', 'from_port': 1234, 'to_port': 1234, + 'cidr': "0000:0000:0000:2013:0000:6535:abcd:ef11/64"}, + {'protocol': 'tcp', 'from_port': 1234, 'to_port': 1234, + 'cidr': "0000:1020:0000:2013:0000:6535:abcd:ef11/128"}, + ], + 'console_pools': + [ + {'address': '10.10.10.10'}, + {'address': '128.100.100.100'}, + {'address': '2002:2002:2002:2002:2002:2002:2002:2002'}, + {'address': '::1'}, + {'address': '0000:0000:0000:2013:0000:6535:abcd:ef11'} + ] + } + return data + + # migration 159 - revert ip column size + def _check_159(self, engine, data): + dialect = engine.url.get_dialect() + # NOTE(maurosr): check if column length is 39 again (it currently makes + # sense only for mysql) + if dialect not in [postgresql.dialect, sqlite.dialect]: + console_pools = get_table(engine, 'console_pools') + self.assertEqual(console_pools.columns['address'].type.length, 39) + # recheck the 149 data + self._check_149(engine, data) + + def _post_downgrade_159(self, engine): + dialect = engine.url.get_dialect() + # NOTE(maurosr): check if column length is 43 again (it currently makes + # sense only for mysql) + if dialect not in [postgresql.dialect, sqlite.dialect]: + console_pools = get_table(engine, 'console_pools') + self.assertEqual(console_pools.columns['address'].type.length, 43) + + # migration 160, fix system_metadata NULL deleted entries to be 0 + def _pre_upgrade_160(self, engine): + fake_instances = [ + dict(uuid='m160-uuid1'), + dict(uuid='m160-uuid2'), + dict(uuid='m160-uuid3'), + ] + fake_sys_meta = [ + dict(instance_uuid='m160-uuid1', key='foo', value='bar'), + dict(instance_uuid='m160-uuid2', key='foo2', value='bar2'), + dict(instance_uuid='m160-uuid3', key='foo3', value='bar3')] + + instances = get_table(engine, 'instances') + sys_meta = get_table(engine, 'instance_system_metadata') + engine.execute(instances.insert(), fake_instances) + + # Create the metadata entries + data = {} + for sm in fake_sys_meta: + result = sys_meta.insert().values(sm).execute() + sm['id'] = result.inserted_primary_key[0] + data[sm['id']] = sm + + # Make sure the entries in the DB for 'deleted' are None. + our_ids = data.keys() + results = sys_meta.select().where(sys_meta.c.id.in_(our_ids)).\ + execute() + results = list(results) + self.assertEqual(len(our_ids), len(results)) + for result in results: + self.assertEqual(result['deleted'], None) + return data + + def _check_160(self, engine, data): + our_ids = data.keys() + sys_meta = get_table(engine, 'instance_system_metadata') + results = sys_meta.select().where(sys_meta.c.id.in_(our_ids)).\ + execute() + results = list(results) + self.assertEqual(len(our_ids), len(results)) + for result in results: + the_id = result['id'] + # Make sure this is now 0. + self.assertEqual(result['deleted'], 0) + # Make sure nothing else changed. + for key, value in data[the_id].items(): + self.assertEqual(value, result[key]) + class TestBaremetalMigrations(BaseMigrationTestCase, CommonTestsMixIn): """Test sqlalchemy-migrate migrations.""" - USER = "openstack_baremetal_citest" - PASSWD = "openstack_baremetal_citest" + USER = "openstack_citest" + PASSWD = "openstack_citest" DATABASE = "openstack_baremetal_citest" def __init__(self, *args, **kwargs): @@ -945,3 +1076,7 @@ class TestBaremetalMigrations(BaseMigrationTestCase, CommonTestsMixIn): def _check_002(self, engine, data): self.assertRaises(sqlalchemy.exc.NoSuchTableError, get_table, engine, 'bm_deployments') + + def _post_downgrade_004(self, engine): + bm_nodes = get_table(engine, 'bm_nodes') + self.assertNotIn(u'instance_name', [c.name for c in bm_nodes.columns]) diff --git a/nova/tests/test_misc.py b/nova/tests/test_misc.py index 6732c4007..6744a2a6a 100644 --- a/nova/tests/test_misc.py +++ b/nova/tests/test_misc.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py index 9b38756c8..c9c80818a 100644 --- a/nova/tests/test_notifications.py +++ b/nova/tests/test_notifications.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index ff316826a..b1d1958f0 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # Copyright 2011 Ilya Alekseyev # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -372,3 +372,13 @@ class ProjectCommandsTestCase(test.TestCase): self.assertRaises(SystemExit, self.commands.quota, 'admin', 'volumes1', '10' ) + + +class DBCommandsTestCase(test.TestCase): + def setUp(self): + super(DBCommandsTestCase, self).setUp() + self.commands = nova_manage.DbCommands() + + def test_archive_deleted_rows_negative(self): + self.assertRaises(SystemExit, + self.commands.archive_deleted_rows, -1) diff --git a/nova/tests/test_periodic_tasks.py b/nova/tests/test_periodic_tasks.py index 621e86b3a..2539332a9 100644 --- a/nova/tests/test_periodic_tasks.py +++ b/nova/tests/test_periodic_tasks.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_pipelib.py b/nova/tests/test_pipelib.py index 4b76581a4..99d840a83 100644 --- a/nova/tests/test_pipelib.py +++ b/nova/tests/test_pipelib.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_plugin_api_extensions.py b/nova/tests/test_plugin_api_extensions.py index 77985854a..3aac638c6 100644 --- a/nova/tests/test_plugin_api_extensions.py +++ b/nova/tests/test_plugin_api_extensions.py @@ -1,4 +1,4 @@ -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_powervm.py b/nova/tests/test_powervm.py index 640497fb0..6fd3fa035 100644 --- a/nova/tests/test_powervm.py +++ b/nova/tests/test_powervm.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -23,9 +23,11 @@ from nova import db from nova import test from nova.compute import power_state +from nova.compute import task_states from nova.network import model as network_model from nova.openstack.common import log as logging from nova.tests import fake_network_cache_model +from nova.tests.image import fake from nova.virt import images from nova.virt.powervm import blockdev as powervm_blockdev from nova.virt.powervm import common @@ -58,7 +60,7 @@ class FakeIVMOperator(object): def start_lpar(self, instance_name): pass - def stop_lpar(self, instance_name): + def stop_lpar(self, instance_name, time_out=30): pass def remove_lpar(self, instance_name): @@ -96,6 +98,9 @@ class FakeIVMOperator(object): def get_hostname(self): return 'fake-powervm' + def rename_lpar(self, old, new): + pass + class FakeBlockAdapter(powervm_blockdev.PowerVMLocalVolumeAdapter): @@ -112,10 +117,20 @@ class FakeBlockAdapter(powervm_blockdev.PowerVMLocalVolumeAdapter): pass def _copy_image_file(self, sourcePath, remotePath, decompress=False): - finalPath = '/home/images/rhel62.raw.7e358754160433febd6f3318b7c9e335' + finalPath = '/tmp/rhel62.raw.7e358754160433febd6f3318b7c9e335' size = 4294967296 return finalPath, size + def _copy_device_to_file(self, device_name, file_path): + pass + + def _copy_image_file_from_host(self, remote_source_path, local_dest_dir, + compress=False): + snapshot_file = '/tmp/rhel62.raw.7e358754160433febd6f3318b7c9e335' + snap_ref = open(snapshot_file, 'w+') + snap_ref.close() + return snapshot_file + def fake_get_powervm_operator(): return FakeIVMOperator() @@ -134,12 +149,14 @@ class PowerVMDriverTestCase(test.TestCase): self.instance = self._create_instance() def _create_instance(self): + fake.stub_out_image_service(self.stubs) return db.instance_create(context.get_admin_context(), - {'user_id': 'fake', - 'project_id': 'fake', - 'instance_type_id': 1, - 'memory_mb': 1024, - 'vcpus': 2}) + {'user_id': 'fake', + 'project_id': 'fake', + 'instance_type_id': 1, + 'memory_mb': 1024, + 'image_ref': '155d900f-4e14-4e4c-a73d-069cbf4541e6', + 'vcpus': 2}) def test_list_instances(self): instances = self.powervm_connection.list_instances() @@ -189,6 +206,27 @@ class PowerVMDriverTestCase(test.TestCase): self.instance, {'id': 'ANY_ID'}, [], 's3cr3t', fake_net_info) + def test_snapshot(self): + + def update_task_state(task_state, expected_state=None): + self._loc_task_state = task_state + self._loc_expected_task_state = expected_state + + loc_context = context.get_admin_context() + properties = {'instance_id': self.instance['id'], + 'user_id': str(loc_context.user_id)} + sent_meta = {'name': 'fake_snap', 'is_public': False, + 'status': 'creating', 'properties': properties} + image_service = fake.FakeImageService() + recv_meta = image_service.create(loc_context, sent_meta) + + self.powervm_connection.snapshot(loc_context, + self.instance, recv_meta['id'], + update_task_state) + + self.assertTrue(self._loc_task_state == task_states.IMAGE_UPLOADING and + self._loc_expected_task_state == task_states.IMAGE_PENDING_UPLOAD) + def test_destroy(self): self.powervm_connection.destroy(self.instance, None) self.stubs.Set(FakeIVMOperator, 'get_lpar', lambda x, y: None) @@ -230,3 +268,36 @@ class PowerVMDriverTestCase(test.TestCase): joined_path = common.aix_path_join(path_one, path_two) expected_path = '/some/file/path/filename' self.assertEqual(joined_path, expected_path) + + def _test_finish_revert_migration_after_crash(self, backup_made, new_made): + inst = {'name': 'foo'} + + self.mox.StubOutWithMock(self.powervm_connection, 'instance_exists') + self.mox.StubOutWithMock(self.powervm_connection._powervm, 'destroy') + self.mox.StubOutWithMock(self.powervm_connection._powervm._operator, + 'rename_lpar') + self.mox.StubOutWithMock(self.powervm_connection._powervm, 'power_on') + + self.powervm_connection.instance_exists('rsz_foo').AndReturn( + backup_made) + + if backup_made: + self.powervm_connection.instance_exists('foo').AndReturn(new_made) + if new_made: + self.powervm_connection._powervm.destroy('foo') + self.powervm_connection._powervm._operator.rename_lpar('rsz_foo', + 'foo') + self.powervm_connection._powervm.power_on('foo') + + self.mox.ReplayAll() + + self.powervm_connection.finish_revert_migration(inst, []) + + def test_finish_revert_migration_after_crash(self): + self._test_finish_revert_migration_after_crash(True, True) + + def test_finish_revert_migration_after_crash_before_new(self): + self._test_finish_revert_migration_after_crash(True, False) + + def test_finish_revert_migration_after_crash_before_backup(self): + self._test_finish_revert_migration_after_crash(False, False) diff --git a/nova/tests/test_safeutils.py b/nova/tests/test_safeutils.py new file mode 100644 index 000000000..430e2f020 --- /dev/null +++ b/nova/tests/test_safeutils.py @@ -0,0 +1,100 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2011 Justin Santa Barbara +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from nova import safe_utils +from nova import test + + +class GetCallArgsTestCase(test.TestCase): + def _test_func(self, instance, red=None, blue=None): + pass + + def test_all_kwargs(self): + args = () + kwargs = {'instance': {'uuid': 1}, 'red': 3, 'blue': 4} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + #implicit self counts as an arg + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(4, callargs['blue']) + + def test_all_args(self): + args = ({'uuid': 1}, 3, 4) + kwargs = {} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + #implicit self counts as an arg + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(4, callargs['blue']) + + def test_mixed_args(self): + args = ({'uuid': 1}, 3) + kwargs = {'blue': 4} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + #implicit self counts as an arg + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(4, callargs['blue']) + + def test_partial_kwargs(self): + args = () + kwargs = {'instance': {'uuid': 1}, 'red': 3} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + #implicit self counts as an arg + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(None, callargs['blue']) + + def test_partial_args(self): + args = ({'uuid': 1}, 3) + kwargs = {} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + #implicit self counts as an arg + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(None, callargs['blue']) + + def test_partial_mixed_args(self): + args = (3,) + kwargs = {'instance': {'uuid': 1}} + callargs = safe_utils.getcallargs(self._test_func, *args, **kwargs) + self.assertEqual(4, len(callargs)) + self.assertTrue('instance' in callargs) + self.assertEqual({'uuid': 1}, callargs['instance']) + self.assertTrue('red' in callargs) + self.assertEqual(3, callargs['red']) + self.assertTrue('blue' in callargs) + self.assertEqual(None, callargs['blue']) diff --git a/nova/tests/test_test_utils.py b/nova/tests/test_test_utils.py index 722377aa5..ef3a6fb68 100644 --- a/nova/tests/test_test_utils.py +++ b/nova/tests/test_test_utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_utils.py b/nova/tests/test_utils.py index 940ddf6ec..d22fb12ea 100644 --- a/nova/tests/test_utils.py +++ b/nova/tests/test_utils.py @@ -23,6 +23,7 @@ import os import os.path import StringIO import tempfile +from xml.dom import minidom import mox import netaddr @@ -514,6 +515,8 @@ class GenericUtilsTestCase(test.TestCase): self.assertTrue(utils.is_valid_ipv4('127.0.0.1')) self.assertFalse(utils.is_valid_ipv4('::1')) self.assertFalse(utils.is_valid_ipv4('bacon')) + self.assertFalse(utils.is_valid_ipv4("")) + self.assertFalse(utils.is_valid_ipv4(10)) def test_is_valid_ipv6(self): self.assertTrue(utils.is_valid_ipv6("::1")) @@ -523,6 +526,8 @@ class GenericUtilsTestCase(test.TestCase): "0000:0000:0000:0000:0000:0000:0000:0001")) self.assertFalse(utils.is_valid_ipv6("foo")) self.assertFalse(utils.is_valid_ipv6("127.0.0.1")) + self.assertFalse(utils.is_valid_ipv6("")) + self.assertFalse(utils.is_valid_ipv6(10)) def test_is_valid_ipv6_cidr(self): self.assertTrue(utils.is_valid_ipv6_cidr("2600::/64")) @@ -964,88 +969,6 @@ class WrappedCodeTestCase(test.TestCase): self.assertTrue('blue' in func_code.co_varnames) -class GetCallArgsTestCase(test.TestCase): - def _test_func(self, instance, red=None, blue=None): - pass - - def test_all_kwargs(self): - args = () - kwargs = {'instance': {'uuid': 1}, 'red': 3, 'blue': 4} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - #implicit self counts as an arg - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(4, callargs['blue']) - - def test_all_args(self): - args = ({'uuid': 1}, 3, 4) - kwargs = {} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - #implicit self counts as an arg - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(4, callargs['blue']) - - def test_mixed_args(self): - args = ({'uuid': 1}, 3) - kwargs = {'blue': 4} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - #implicit self counts as an arg - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(4, callargs['blue']) - - def test_partial_kwargs(self): - args = () - kwargs = {'instance': {'uuid': 1}, 'red': 3} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - #implicit self counts as an arg - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(None, callargs['blue']) - - def test_partial_args(self): - args = ({'uuid': 1}, 3) - kwargs = {} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - #implicit self counts as an arg - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(None, callargs['blue']) - - def test_partial_mixed_args(self): - args = (3,) - kwargs = {'instance': {'uuid': 1}} - callargs = utils.getcallargs(self._test_func, *args, **kwargs) - self.assertEqual(4, len(callargs)) - self.assertTrue('instance' in callargs) - self.assertEqual({'uuid': 1}, callargs['instance']) - self.assertTrue('red' in callargs) - self.assertEqual(3, callargs['red']) - self.assertTrue('blue' in callargs) - self.assertEqual(None, callargs['blue']) - - class StringLengthTestCase(test.TestCase): def test_check_string_length(self): self.assertIsNone(utils.check_string_length( @@ -1059,3 +982,47 @@ class StringLengthTestCase(test.TestCase): self.assertRaises(exception.InvalidInput, utils.check_string_length, 'a' * 256, 'name', max_length=255) + + +class SafeParserTestCase(test.TestCase): + def test_external_dtd(self): + xml_string = ("""<?xml version="1.0" encoding="utf-8"?> + <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> + <html> + <head/> + <body>html with dtd</body> + </html>""") + + parser = utils.ProtectedExpatParser(forbid_dtd=False, + forbid_entities=True) + self.assertRaises(ValueError, + minidom.parseString, + xml_string, parser) + + def test_external_file(self): + xml_string = """<!DOCTYPE external [ + <!ENTITY ee SYSTEM "file:///PATH/TO/root.xml"> + ]> + <root>ⅇ</root>""" + + parser = utils.ProtectedExpatParser(forbid_dtd=False, + forbid_entities=True) + self.assertRaises(ValueError, + minidom.parseString, + xml_string, parser) + + def test_notation(self): + xml_string = """<?xml version="1.0" standalone="no"?> + <!-- comment data --> + <!DOCTYPE x [ + <!NOTATION notation SYSTEM "notation.jpeg"> + ]> + <root attr1="value1"> + </root>""" + + parser = utils.ProtectedExpatParser(forbid_dtd=False, + forbid_entities=True) + self.assertRaises(ValueError, + minidom.parseString, + xml_string, parser) diff --git a/nova/tests/test_virt_disk_vfs_localfs.py b/nova/tests/test_virt_disk_vfs_localfs.py index 096a75964..5bbac670e 100644 --- a/nova/tests/test_virt_disk_vfs_localfs.py +++ b/nova/tests/test_virt_disk_vfs_localfs.py @@ -148,10 +148,6 @@ class VirtDiskVFSLocalFSTestPaths(test.TestCase): class VirtDiskVFSLocalFSTest(test.TestCase): - - def setUp(self): - super(VirtDiskVFSLocalFSTest, self).setUp() - def test_makepath(self): global dirs, commands dirs = [] diff --git a/nova/tests/test_virt_drivers.py b/nova/tests/test_virt_drivers.py index f6e0bca38..395663600 100644 --- a/nova/tests/test_virt_drivers.py +++ b/nova/tests/test_virt_drivers.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2010 OpenStack LLC +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -192,9 +192,6 @@ class _VirtDriverTestCase(_FakeDriverBackendTestCase): self.ctxt = test_utils.get_test_admin_context() self.image_service = fake_image.FakeImageService() - def tearDown(self): - super(_VirtDriverTestCase, self).tearDown() - def _get_running_instance(self): instance_ref = test_utils.get_test_instance() network_info = test_utils.get_test_network_info() diff --git a/nova/tests/test_vmwareapi.py b/nova/tests/test_vmwareapi.py index e20a5a7b7..a5f08041b 100644 --- a/nova/tests/test_vmwareapi.py +++ b/nova/tests/test_vmwareapi.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/test_vmwareapi_vmops.py b/nova/tests/test_vmwareapi_vmops.py index ad83cd21d..f1806273c 100644 --- a/nova/tests/test_vmwareapi_vmops.py +++ b/nova/tests/test_vmwareapi_vmops.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/test_xenapi.py b/nova/tests/test_xenapi.py index 84c3caa63..6714161f1 100644 --- a/nova/tests/test_xenapi.py +++ b/nova/tests/test_xenapi.py @@ -176,6 +176,15 @@ def stub_vm_utils_with_vdi_attached_here(function, should_return=True): return decorated_function +def create_instance_with_system_metadata(context, instance_values): + instance_type = db.instance_type_get(context, + instance_values['instance_type_id']) + sys_meta = instance_types.save_instance_type_info({}, + instance_type) + instance_values['system_metadata'] = sys_meta + return db.instance_create(context, instance_values) + + class XenAPIVolumeTestCase(stubs.XenAPITestBase): """Unit tests for Volume operations.""" def setUp(self): @@ -635,7 +644,8 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): 'os_type': os_type, 'hostname': hostname, 'architecture': architecture} - instance = db.instance_create(self.context, instance_values) + instance = create_instance_with_system_metadata(self.context, + instance_values) else: instance = db.instance_get(self.context, instance_id) @@ -1093,7 +1103,9 @@ class XenAPIVMTestCase(stubs.XenAPITestBase): 'os_type': 'linux', 'vm_mode': 'hvm', 'architecture': 'x86-64'} - instance = db.instance_create(self.context, instance_values) + + instance = create_instance_with_system_metadata(self.context, + instance_values) network_info = fake_network.fake_get_instance_nw_info(self.stubs, spectacular=True) image_meta = {'id': IMAGE_VHD, @@ -1252,7 +1264,8 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): '127.0.0.1', instance_type, None) def test_revert_migrate(self): - instance = db.instance_create(self.context, self.instance_values) + instance = create_instance_with_system_metadata(self.context, + self.instance_values) self.called = False self.fake_vm_start_called = False self.fake_finish_revert_migration_called = False @@ -1293,7 +1306,8 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): self.assertEqual(self.fake_finish_revert_migration_called, True) def test_finish_migrate(self): - instance = db.instance_create(self.context, self.instance_values) + instance = create_instance_with_system_metadata(self.context, + self.instance_values) self.called = False self.fake_vm_start_called = False @@ -1325,7 +1339,8 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): tiny_type_id = tiny_type['id'] self.instance_values.update({'instance_type_id': tiny_type_id, 'root_gb': 0}) - instance = db.instance_create(self.context, self.instance_values) + instance = create_instance_with_system_metadata(self.context, + self.instance_values) def fake_vdi_resize(*args, **kwargs): raise Exception("This shouldn't be called") @@ -1341,7 +1356,8 @@ class XenAPIMigrateInstance(stubs.XenAPITestBase): network_info, image_meta, resize_instance=True) def test_finish_migrate_no_resize_vdi(self): - instance = db.instance_create(self.context, self.instance_values) + instance = create_instance_with_system_metadata(self.context, + self.instance_values) def fake_vdi_resize(*args, **kwargs): raise Exception("This shouldn't be called") @@ -1616,7 +1632,8 @@ class XenAPIAutoDiskConfigTestCase(stubs.XenAPITestBase): fake.FakeVirtAPI()) disk_image_type = vm_utils.ImageType.DISK_VHD - instance = db.instance_create(self.context, self.instance_values) + instance = create_instance_with_system_metadata(self.context, + self.instance_values) vm_ref = xenapi_fake.create_vm(instance['name'], 'Halted') vdi_ref = xenapi_fake.create_vdi(instance['name'], 'fake') @@ -1716,14 +1733,9 @@ class XenAPIGenerateLocal(stubs.XenAPITestBase): def test_generate_swap(self): # Test swap disk generation. - instance = db.instance_create(self.context, self.instance_values) - instance = db.instance_update(self.context, instance['uuid'], - {'instance_type_id': 5}) - - # NOTE(danms): because we're stubbing out the instance_types from - # the database, our instance['instance_type'] doesn't get properly - # filled out here, so put what we need into it - instance['instance_type']['swap'] = 1024 + instance_values = dict(self.instance_values, instance_type_id=5) + instance = create_instance_with_system_metadata(self.context, + instance_values) def fake_generate_swap(*args, **kwargs): self.called = True @@ -1733,14 +1745,9 @@ class XenAPIGenerateLocal(stubs.XenAPITestBase): def test_generate_ephemeral(self): # Test ephemeral disk generation. - instance = db.instance_create(self.context, self.instance_values) - instance = db.instance_update(self.context, instance['uuid'], - {'instance_type_id': 4}) - - # NOTE(danms): because we're stubbing out the instance_types from - # the database, our instance['instance_type'] doesn't get properly - # filled out here, so put what we need into it - instance['instance_type']['ephemeral_gb'] = 160 + instance_values = dict(self.instance_values, instance_type_id=4) + instance = create_instance_with_system_metadata(self.context, + instance_values) def fake_generate_ephemeral(*args): self.called = True @@ -2068,8 +2075,10 @@ class XenAPIDom0IptablesFirewallTestCase(stubs.XenAPITestBase): ipv6 = self.fw.iptables.ipv6['filter'].rules ipv4_network_rules = len(ipv4) - len(inst_ipv4) - ipv4_len ipv6_network_rules = len(ipv6) - len(inst_ipv6) - ipv6_len - self.assertEquals(ipv4_network_rules, - ipv4_rules_per_addr * ipv4_addr_per_network * networks_count) + # Extra rules are for the DHCP request + rules = (ipv4_rules_per_addr * ipv4_addr_per_network * + networks_count) + 2 + self.assertEquals(ipv4_network_rules, rules) self.assertEquals(ipv6_network_rules, ipv6_rules_per_addr * ipv6_addr_per_network * networks_count) @@ -3112,6 +3121,42 @@ class VMOpsTestCase(test.TestCase): 'VDI.resize', ops.check_resize_func_name()) + def _test_finish_revert_migration_after_crash(self, backup_made, new_made): + instance = {'name': 'foo', + 'task_state': task_states.RESIZE_MIGRATING} + session = self._get_mock_session(None, None) + ops = vmops.VMOps(session, fake.FakeVirtAPI()) + + self.mox.StubOutWithMock(vm_utils, 'lookup') + self.mox.StubOutWithMock(ops, '_destroy') + self.mox.StubOutWithMock(vm_utils, 'set_vm_name_label') + self.mox.StubOutWithMock(ops, '_attach_mapped_block_devices') + self.mox.StubOutWithMock(ops, '_start') + + vm_utils.lookup(session, 'foo-orig').AndReturn( + backup_made and 'foo' or None) + vm_utils.lookup(session, 'foo').AndReturn( + (not backup_made or new_made) and 'foo' or None) + if backup_made: + if new_made: + ops._destroy(instance, 'foo') + vm_utils.set_vm_name_label(session, 'foo', 'foo') + ops._attach_mapped_block_devices(instance, []) + ops._start(instance, 'foo') + + self.mox.ReplayAll() + + ops.finish_revert_migration(instance, []) + + def test_finish_revert_migration_after_crash(self): + self._test_finish_revert_migration_after_crash(True, True) + + def test_finish_revert_migration_after_crash_before_new(self): + self._test_finish_revert_migration_after_crash(True, False) + + def test_finish_revert_migration_after_crash_before_backup(self): + self._test_finish_revert_migration_after_crash(False, False) + class XenAPISessionTestCase(test.TestCase): def _get_mock_xapisession(self, software_version): diff --git a/nova/tests/utils.py b/nova/tests/utils.py index 9daa72f34..755d49be1 100644 --- a/nova/tests/utils.py +++ b/nova/tests/utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/virt/disk/test_api.py b/nova/tests/virt/disk/test_api.py index 15fb2fc2f..772c8cb1b 100644 --- a/nova/tests/virt/disk/test_api.py +++ b/nova/tests/virt/disk/test_api.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/virt/xenapi/imageupload/test_glance.py b/nova/tests/virt/xenapi/imageupload/test_glance.py index b0518228d..34e95ab80 100644 --- a/nova/tests/virt/xenapi/imageupload/test_glance.py +++ b/nova/tests/virt/xenapi/imageupload/test_glance.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack LLC. +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -30,9 +30,6 @@ class TestGlanceStore(test.TestCase): self.store = glance.GlanceStore() self.mox = mox.Mox() - def tearDown(self): - super(TestGlanceStore, self).tearDown() - def test_upload_image(self): glance_host = '0.1.2.3' glance_port = 8143 diff --git a/nova/tests/virt/xenapi/test_vm_utils.py b/nova/tests/virt/xenapi/test_vm_utils.py index 633e6f835..f757a57ad 100644 --- a/nova/tests/virt/xenapi/test_vm_utils.py +++ b/nova/tests/virt/xenapi/test_vm_utils.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack LLC +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/tests/vmwareapi/__init__.py b/nova/tests/vmwareapi/__init__.py index 228186621..d22b919f3 100644 --- a/nova/tests/vmwareapi/__init__.py +++ b/nova/tests/vmwareapi/__init__.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/vmwareapi/db_fakes.py b/nova/tests/vmwareapi/db_fakes.py index f3191670d..54e3cf43b 100644 --- a/nova/tests/vmwareapi/db_fakes.py +++ b/nova/tests/vmwareapi/db_fakes.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/vmwareapi/stubs.py b/nova/tests/vmwareapi/stubs.py index 0330246e2..dc87b2355 100644 --- a/nova/tests/vmwareapi/stubs.py +++ b/nova/tests/vmwareapi/stubs.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/tests/volume/__init__.py b/nova/tests/volume/__init__.py index 4549abf92..efbc9063d 100644 --- a/nova/tests/volume/__init__.py +++ b/nova/tests/volume/__init__.py @@ -1,4 +1,4 @@ -# Copyright 2012 OpenStack LLC +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/utils.py b/nova/utils.py index 2c7d0b427..eb6c44106 100644 --- a/nova/utils.py +++ b/nova/utils.py @@ -672,19 +672,33 @@ class ProtectedExpatParser(expatreader.ExpatParser): def entity_decl(self, entityName, is_parameter_entity, value, base, systemId, publicId, notationName): - raise ValueError("<!ENTITY> forbidden") + raise ValueError("<!ENTITY> entity declaration forbidden") def unparsed_entity_decl(self, name, base, sysid, pubid, notation_name): # expat 1.2 - raise ValueError("<!ENTITY> forbidden") + raise ValueError("<!ENTITY> unparsed entity forbidden") + + def external_entity_ref(self, context, base, systemId, publicId): + raise ValueError("<!ENTITY> external entity forbidden") + + def notation_decl(self, name, base, sysid, pubid): + raise ValueError("<!ENTITY> notation forbidden") def reset(self): expatreader.ExpatParser.reset(self) if self.forbid_dtd: self._parser.StartDoctypeDeclHandler = self.start_doctype_decl + self._parser.EndDoctypeDeclHandler = None if self.forbid_entities: self._parser.EntityDeclHandler = self.entity_decl self._parser.UnparsedEntityDeclHandler = self.unparsed_entity_decl + self._parser.ExternalEntityRefHandler = self.external_entity_ref + self._parser.NotationDeclHandler = self.notation_decl + try: + self._parser.SkippedEntityHandler = None + except AttributeError: + # some pyexpat versions do not support SkippedEntity + pass def safe_minidom_parse_string(xml_string): @@ -931,14 +945,16 @@ def is_valid_boolstr(val): def is_valid_ipv4(address): """Verify that address represents a valid IPv4 address.""" try: - addr = netaddr.IPAddress(address) - return addr.version == 4 + return netaddr.valid_ipv4(address) except Exception: return False def is_valid_ipv6(address): - return netaddr.valid_ipv6(address) + try: + return netaddr.valid_ipv6(address) + except Exception: + return False def is_valid_ipv6_cidr(address): @@ -1367,39 +1383,6 @@ def get_wrapped_function(function): return _get_wrapped_function(function) -def getcallargs(function, *args, **kwargs): - """This is a simplified inspect.getcallargs (2.7+). - - It should be replaced when python >= 2.7 is standard. - """ - keyed_args = {} - argnames, varargs, keywords, defaults = inspect.getargspec(function) - - keyed_args.update(kwargs) - - #NOTE(alaski) the implicit 'self' or 'cls' argument shows up in - # argnames but not in args or kwargs. Uses 'in' rather than '==' because - # some tests use 'self2'. - if 'self' in argnames[0] or 'cls' == argnames[0]: - # The function may not actually be a method or have im_self. - # Typically seen when it's stubbed with mox. - if inspect.ismethod(function) and hasattr(function, 'im_self'): - keyed_args[argnames[0]] = function.im_self - else: - keyed_args[argnames[0]] = None - - remaining_argnames = filter(lambda x: x not in keyed_args, argnames) - keyed_args.update(dict(zip(remaining_argnames, args))) - - if defaults: - num_defaults = len(defaults) - for argname, value in zip(argnames[-num_defaults:], defaults): - if argname not in keyed_args: - keyed_args[argname] = value - - return keyed_args - - class ExceptionHelper(object): """Class to wrap another and translate the ClientExceptions raised by its function calls to the actual ones""" diff --git a/nova/version.py b/nova/version.py index d54c112be..6f2cbbb28 100644 --- a/nova/version.py +++ b/nova/version.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/baremetal/baremetal_states.py b/nova/virt/baremetal/baremetal_states.py index 115ed091c..c669b4116 100644 --- a/nova/virt/baremetal/baremetal_states.py +++ b/nova/virt/baremetal/baremetal_states.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 NTT DOCOMO, INC. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/virt/baremetal/base.py b/nova/virt/baremetal/base.py index 8cd9e9b3c..2029400ba 100644 --- a/nova/virt/baremetal/base.py +++ b/nova/virt/baremetal/base.py @@ -21,8 +21,8 @@ from nova.virt.baremetal import baremetal_states class NodeDriver(object): - def __init__(self): - pass + def __init__(self, virtapi): + self.virtapi = virtapi def cache_images(self, context, node, instance, **kwargs): raise NotImplementedError() diff --git a/nova/virt/baremetal/db/sqlalchemy/api.py b/nova/virt/baremetal/db/sqlalchemy/api.py index d64bc4872..d117ad46d 100644 --- a/nova/virt/baremetal/db/sqlalchemy/api.py +++ b/nova/virt/baremetal/db/sqlalchemy/api.py @@ -28,6 +28,7 @@ from sqlalchemy.sql.expression import literal_column import nova.context from nova.db.sqlalchemy import api as sqlalchemy_api from nova import exception +from nova.openstack.common.db import exception as db_exc from nova.openstack.common import log as logging from nova.openstack.common import timeutils from nova.openstack.common import uuidutils @@ -399,7 +400,7 @@ def bm_interface_set_vif_uuid(context, if_id, vif_uuid): try: session.add(bm_interface) session.flush() - except db_session.DBError, e: + except db_exc.DBError, e: # TODO(deva): clean up when db layer raises DuplicateKeyError if str(e).find('IntegrityError') != -1: raise exception.NovaException(_("Baremetal interface %s " diff --git a/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/001_init.py b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/001_init.py index 2d899406c..fad83e21b 100644 --- a/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/001_init.py +++ b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/001_init.py @@ -120,4 +120,4 @@ def upgrade(migrate_engine): def downgrade(migrate_engine): - pass + raise NotImplementedError('Downgrade from 001_init is unsupported.') diff --git a/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/004_add_instance_name_to_bm_nodes.py b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/004_add_instance_name_to_bm_nodes.py index 68fbe0960..6f85b9cec 100644 --- a/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/004_add_instance_name_to_bm_nodes.py +++ b/nova/virt/baremetal/db/sqlalchemy/migrate_repo/versions/004_add_instance_name_to_bm_nodes.py @@ -32,6 +32,4 @@ def downgrade(migrate_engine): meta.bind = migrate_engine t = Table('bm_nodes', meta, autoload=True) - name_col = Column('instance_name', String(length=255)) - - t.drop_column(name_col) + t.drop_column('instance_name') diff --git a/nova/virt/baremetal/db/sqlalchemy/session.py b/nova/virt/baremetal/db/sqlalchemy/session.py index 585096c94..fc045d5ca 100644 --- a/nova/virt/baremetal/db/sqlalchemy/session.py +++ b/nova/virt/baremetal/db/sqlalchemy/session.py @@ -44,8 +44,6 @@ CONF.import_opt('sqlite_db', 'nova.openstack.common.db.sqlalchemy.session') _ENGINE = None _MAKER = None -DBError = nova_session.DBError - def get_session(autocommit=True, expire_on_commit=False): """Return a SQLAlchemy session.""" diff --git a/nova/virt/baremetal/driver.py b/nova/virt/baremetal/driver.py index 8dff0a785..94d3f0a92 100755 --- a/nova/virt/baremetal/driver.py +++ b/nova/virt/baremetal/driver.py @@ -122,7 +122,7 @@ class BareMetalDriver(driver.ComputeDriver): super(BareMetalDriver, self).__init__(virtapi) self.driver = importutils.import_object( - CONF.baremetal.driver) + CONF.baremetal.driver, virtapi) self.vif_driver = importutils.import_object( CONF.baremetal.vif_driver) self.firewall_driver = firewall.load_driver( @@ -410,9 +410,13 @@ class BareMetalDriver(driver.ComputeDriver): def get_available_resource(self, nodename): context = nova_context.get_admin_context() - node = db.bm_node_get_by_node_uuid(context, nodename) - dic = self._node_resource(node) - return dic + resource = {} + try: + node = db.bm_node_get_by_node_uuid(context, nodename) + resource = self._node_resource(node) + except exception.NodeNotFoundByUUID: + pass + return resource def ensure_filtering_rules_for_instance(self, instance_ref, network_info): self.firewall_driver.setup_basic_filtering(instance_ref, network_info) diff --git a/nova/virt/baremetal/pxe.py b/nova/virt/baremetal/pxe.py index 813f95c05..5d97298ca 100644 --- a/nova/virt/baremetal/pxe.py +++ b/nova/virt/baremetal/pxe.py @@ -27,7 +27,7 @@ from oslo.config import cfg from nova.compute import instance_types from nova import exception -from nova.openstack.common.db.sqlalchemy import session as db_session +from nova.openstack.common.db import exception as db_exc from nova.openstack.common import fileutils from nova.openstack.common import log as logging from nova.openstack.common import timeutils @@ -148,14 +148,14 @@ def build_network_config(network_info): return network_config -def get_deploy_aki_id(instance): - return instance.get('extra_specs', {}).\ - get('deploy_kernel_id', CONF.baremetal.deploy_kernel) +def get_deploy_aki_id(instance_type): + return instance_type.get('extra_specs', {}).\ + get('baremetal:deploy_kernel_id', CONF.baremetal.deploy_kernel) -def get_deploy_ari_id(instance): - return instance.get('extra_specs', {}).\ - get('deploy_ramdisk_id', CONF.baremetal.deploy_ramdisk) +def get_deploy_ari_id(instance_type): + return instance_type.get('extra_specs', {}).\ + get('baremetal:deploy_ramdisk_id', CONF.baremetal.deploy_ramdisk) def get_image_dir_path(instance): @@ -196,13 +196,13 @@ def get_pxe_mac_path(mac): ) -def get_tftp_image_info(instance): +def get_tftp_image_info(instance, instance_type): """Generate the paths for tftp files for this instance Raises NovaException if - instance does not contain kernel_id or ramdisk_id - deploy_kernel_id or deploy_ramdisk_id can not be read from - instance['extra_specs'] and defaults are not set + instance_type['extra_specs'] and defaults are not set """ image_info = { @@ -214,8 +214,8 @@ def get_tftp_image_info(instance): try: image_info['kernel'][0] = str(instance['kernel_id']) image_info['ramdisk'][0] = str(instance['ramdisk_id']) - image_info['deploy_kernel'][0] = get_deploy_aki_id(instance) - image_info['deploy_ramdisk'][0] = get_deploy_ari_id(instance) + image_info['deploy_kernel'][0] = get_deploy_aki_id(instance_type) + image_info['deploy_ramdisk'][0] = get_deploy_ari_id(instance_type) except KeyError as e: pass @@ -237,8 +237,8 @@ def get_tftp_image_info(instance): class PXE(base.NodeDriver): """PXE bare metal driver.""" - def __init__(self): - super(PXE, self).__init__() + def __init__(self, virtapi): + super(PXE, self).__init__(virtapi) def _collect_mac_addresses(self, context, node): macs = set() @@ -341,7 +341,9 @@ class PXE(base.NodeDriver): def cache_images(self, context, node, instance, admin_password, image_meta, injected_files, network_info): """Prepare all the images for this instance.""" - tftp_image_info = get_tftp_image_info(instance) + instance_type = self.virtapi.instance_type_get( + context, instance['instance_type_id']) + tftp_image_info = get_tftp_image_info(instance, instance_type) self._cache_tftp_images(context, instance, tftp_image_info) self._cache_image(context, instance, image_meta) @@ -374,7 +376,9 @@ class PXE(base.NodeDriver): ./pxelinux.cfg/ {mac} -> ../{uuid}/config """ - image_info = get_tftp_image_info(instance) + instance_type = self.virtapi.instance_type_get( + context, instance['instance_type_id']) + image_info = get_tftp_image_info(instance, instance_type) (root_mb, swap_mb) = get_partition_sizes(instance) pxe_config_file_path = get_pxe_config_file_path(instance) image_file_path = get_image_file_path(instance) @@ -416,8 +420,14 @@ class PXE(base.NodeDriver): except exception.NodeNotFound: pass + # NOTE(danms): the instance_type extra_specs do not need to be + # present/correct at deactivate time, so pass something empty + # to avoid an extra lookup + instance_type = dict(extra_specs={ + 'baremetal:deploy_ramdisk_id': 'ignore', + 'baremetal:deploy_kernel_id': 'ignore'}) try: - image_info = get_tftp_image_info(instance) + image_info = get_tftp_image_info(instance, instance_type) except exception.NovaException: pass else: @@ -428,7 +438,7 @@ class PXE(base.NodeDriver): bm_utils.unlink_without_raise(get_pxe_config_file_path(instance)) try: macs = self._collect_mac_addresses(context, node) - except db_session.DBError: + except db_exc.DBError: pass else: for mac in macs: diff --git a/nova/virt/baremetal/virtual_power_driver.py b/nova/virt/baremetal/virtual_power_driver.py index a18a2f9d3..d3f612ddd 100644 --- a/nova/virt/baremetal/virtual_power_driver.py +++ b/nova/virt/baremetal/virtual_power_driver.py @@ -31,8 +31,11 @@ opts = [ cfg.StrOpt('virtual_power_ssh_host', default='', help='ip or name to virtual power host'), + cfg.StrOpt('virtual_power_ssh_port', + default='22', + help='Port to use for ssh to virtual power host'), cfg.StrOpt('virtual_power_type', - default='vbox', + default='virsh', help='base command to use for virtual power(vbox,virsh)'), cfg.StrOpt('virtual_power_host_user', default='', @@ -40,6 +43,10 @@ opts = [ cfg.StrOpt('virtual_power_host_pass', default='', help='password for virtual power host_user'), + cfg.StrOpt('virtual_power_host_key', + default=None, + help='ssh key for virtual power host_user'), + ] baremetal_vp = cfg.OptGroup(name='baremetal', @@ -101,13 +108,17 @@ class VirtualPowerManager(base.PowerManager): _('virtual_power_host_user not defined. Can not Start')) if not CONF.baremetal.virtual_power_host_pass: - raise exception.NovaException( - _('virtual_power_host_pass not defined. Can not Start')) + # it is ok to not have a password if you have a keyfile + if CONF.baremetal.virtual_power_host_key is None: + raise exception.NovaException( + _('virtual_power_host_pass/key not set. Can not Start')) _conn = connection.Connection( CONF.baremetal.virtual_power_ssh_host, CONF.baremetal.virtual_power_host_user, - CONF.baremetal.virtual_power_host_pass) + CONF.baremetal.virtual_power_host_pass, + CONF.baremetal.virtual_power_ssh_port, + CONF.baremetal.virtual_power_host_key) return _conn def _set_connection(self): diff --git a/nova/virt/disk/vfs/guestfs.py b/nova/virt/disk/vfs/guestfs.py index 11cf9d098..985858a0d 100644 --- a/nova/virt/disk/vfs/guestfs.py +++ b/nova/virt/disk/vfs/guestfs.py @@ -14,6 +14,7 @@ # License for the specific language governing permissions and limitations # under the License. +from eventlet import tpool import guestfs from nova import exception @@ -93,7 +94,7 @@ class VFSGuestFS(vfs.VFS): def setup(self): LOG.debug(_("Setting up appliance for %(imgfile)s %(imgfmt)s") % {'imgfile': self.imgfile, 'imgfmt': self.imgfmt}) - self.handle = guestfs.GuestFS() + self.handle = tpool.Proxy(guestfs.GuestFS()) try: self.handle.add_drive_opts(self.imgfile, format=self.imgfmt) diff --git a/nova/virt/driver.py b/nova/virt/driver.py index bc53aa88a..11c65519c 100755 --- a/nova/virt/driver.py +++ b/nova/virt/driver.py @@ -36,7 +36,7 @@ driver_opts = [ help='Driver to use for controlling virtualization. Options ' 'include: libvirt.LibvirtDriver, xenapi.XenAPIDriver, ' 'fake.FakeDriver, baremetal.BareMetalDriver, ' - 'vmwareapi.VMWareESXDriver'), + 'vmwareapi.VMwareESXDriver, vmwareapi.VMwareVCDriver'), cfg.StrOpt('default_ephemeral_format', default=None, help='The default format an ephemeral_volume will be ' diff --git a/nova/virt/fake.py b/nova/virt/fake.py index 5545dcf96..58f303efc 100755 --- a/nova/virt/fake.py +++ b/nova/virt/fake.py @@ -321,7 +321,7 @@ class FakeDriver(driver.ComputeDriver): disk and ram. """ if nodename not in _FAKE_NODES: - raise exception.NovaException("node %s is not found" % nodename) + return {} dic = {'vcpus': 1, 'memory_mb': 8192, @@ -470,3 +470,6 @@ class FakeVirtAPI(virtapi.VirtAPI): def agent_build_get_by_triple(self, context, hypervisor, os, architecture): return db.agent_build_get_by_triple(context, hypervisor, os, architecture) + + def instance_type_get(self, context, instance_type_id): + return db.instance_type_get(context, instance_type_id) diff --git a/nova/virt/firewall.py b/nova/virt/firewall.py index a36beb7f0..7e133135d 100644 --- a/nova/virt/firewall.py +++ b/nova/virt/firewall.py @@ -149,6 +149,10 @@ class IptablesFirewallDriver(FirewallDriver): self.network_infos = {} self.basically_filtered = False + # Flags for DHCP request rule + self.dhcp_create = False + self.dhcp_created = False + self.iptables.ipv4['filter'].add_chain('sg-fallback') self.iptables.ipv4['filter'].add_rule('sg-fallback', '-j DROP') self.iptables.ipv6['filter'].add_chain('sg-fallback') @@ -191,6 +195,17 @@ class IptablesFirewallDriver(FirewallDriver): LOG.debug(_('Filters added to instance'), instance=instance) self.refresh_provider_fw_rules() LOG.debug(_('Provider Firewall Rules refreshed'), instance=instance) + # Ensure that DHCP request rule is updated if necessary + if (self.dhcp_create and not self.dhcp_created): + self.iptables.ipv4['filter'].add_rule( + 'INPUT', + '-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-p udp -m udp --sport 68 --dport 67 -j ACCEPT') + self.iptables.ipv4['filter'].add_rule( + 'FORWARD', + '-s 0.0.0.0/32 -d 255.255.255.255/32 ' + '-p udp -m udp --sport 68 --dport 67 -j ACCEPT') + self.dhcp_created = True self.iptables.apply() def _create_filter(self, ips, chain_name): @@ -272,6 +287,7 @@ class IptablesFirewallDriver(FirewallDriver): if dhcp_server: ipv4_rules.append('-s %s -p udp --sport 67 --dport 68 ' '-j ACCEPT' % (dhcp_server,)) + self.dhcp_create = True def _do_project_network_rules(self, ipv4_rules, ipv6_rules, network_info): # make sure this is legacy nw_info diff --git a/nova/virt/hyperv/driver.py b/nova/virt/hyperv/driver.py index aac47deef..289f3c4b6 100755 --- a/nova/virt/hyperv/driver.py +++ b/nova/virt/hyperv/driver.py @@ -57,9 +57,10 @@ class HyperVDriver(driver.ComputeDriver): block_device_info=None): self._vmops.reboot(instance, network_info, reboot_type) - def destroy(self, instance, network_info=None, cleanup=True, + def destroy(self, instance, network_info, block_device_info=None, destroy_disks=True): - self._vmops.destroy(instance, network_info, cleanup, destroy_disks) + self._vmops.destroy(instance, network_info, block_device_info, + destroy_disks) def get_info(self, instance): return self._vmops.get_info(instance) @@ -112,9 +113,6 @@ class HyperVDriver(driver.ComputeDriver): post_method, recover_method, block_migration, migrate_data) - def compare_cpu(self, cpu_info): - return self._livemigrationops.compare_cpu(cpu_info) - def pre_live_migration(self, context, instance, block_device_info, network_info, migrate_data=None): self._livemigrationops.pre_live_migration(context, instance, @@ -134,14 +132,19 @@ class HyperVDriver(driver.ComputeDriver): src_compute_info, dst_compute_info, block_migration=False, disk_over_commit=False): - pass + return self._livemigrationops.check_can_live_migrate_destination( + ctxt, instance_ref, src_compute_info, dst_compute_info, + block_migration, disk_over_commit) def check_can_live_migrate_destination_cleanup(self, ctxt, dest_check_data): - pass + self._livemigrationops.check_can_live_migrate_destination_cleanup( + ctxt, dest_check_data) - def check_can_live_migrate_source(self, ctxt, instance, dest_check_data): - pass + def check_can_live_migrate_source(self, ctxt, instance_ref, + dest_check_data): + return self._livemigrationops.check_can_live_migrate_source( + ctxt, instance_ref, dest_check_data) def plug_vifs(self, instance, network_info): LOG.debug(_("plug_vifs called"), instance=instance) diff --git a/nova/virt/hyperv/imagecache.py b/nova/virt/hyperv/imagecache.py index 93ea32b25..5d68bab61 100644 --- a/nova/virt/hyperv/imagecache.py +++ b/nova/virt/hyperv/imagecache.py @@ -19,15 +19,21 @@ Image caching and management. """ import os +from nova.compute import instance_types +from nova.openstack.common import excutils from nova.openstack.common import lockutils from nova.openstack.common import log as logging from nova.virt.hyperv import pathutils from nova.virt.hyperv import vhdutils from nova.virt.hyperv import vmutils from nova.virt import images +from oslo.config import cfg LOG = logging.getLogger(__name__) +CONF = cfg.CONF +CONF.import_opt('use_cow_images', 'nova.virt.driver') + class ImageCache(object): def __init__(self): @@ -36,12 +42,59 @@ class ImageCache(object): def _validate_vhd_image(self, vhd_path): try: - self._vhdutils.get_vhd_info(vhd_path) + self._vhdutils.validate_vhd(vhd_path) except Exception as ex: LOG.exception(ex) raise vmutils.HyperVException(_('The image is not a valid VHD: %s') % vhd_path) + def _get_root_vhd_size_gb(self, instance): + try: + # In case of resizes we need the old root disk size + old_instance_type = instance_types.extract_instance_type( + instance, prefix='old_') + return old_instance_type['root_gb'] + except KeyError: + return instance['root_gb'] + + def _resize_and_cache_vhd(self, instance, vhd_path): + vhd_info = self._vhdutils.get_vhd_info(vhd_path) + vhd_size = vhd_info['MaxInternalSize'] + + root_vhd_size_gb = self._get_root_vhd_size_gb(instance) + root_vhd_size = root_vhd_size_gb * 1024 ** 3 + + if root_vhd_size < vhd_size: + raise vmutils.HyperVException(_("Cannot resize the image to a " + "size smaller than the VHD max. " + "internal size: %(vhd_size)s. " + "Requested disk size: " + "%(root_vhd_size)s") % locals()) + if root_vhd_size > vhd_size: + path_parts = os.path.splitext(vhd_path) + resized_vhd_path = '%s_%s%s' % (path_parts[0], + root_vhd_size_gb, + path_parts[1]) + + @lockutils.synchronized(resized_vhd_path, 'nova-') + def copy_and_resize_vhd(): + if not self._pathutils.exists(resized_vhd_path): + try: + LOG.debug(_("Copying VHD %(vhd_path)s to " + "%(resized_vhd_path)s") % locals()) + self._pathutils.copyfile(vhd_path, resized_vhd_path) + LOG.debug(_("Resizing VHD %(resized_vhd_path)s to new " + "size %(root_vhd_size)s") % locals()) + self._vhdutils.resize_vhd(resized_vhd_path, + root_vhd_size) + except Exception: + with excutils.save_and_reraise_exception(): + if self._pathutils.exists(resized_vhd_path): + self._pathutils.remove(resized_vhd_path) + + copy_and_resize_vhd() + return resized_vhd_path + def get_cached_image(self, context, instance): image_id = instance['image_ref'] @@ -51,10 +104,22 @@ class ImageCache(object): @lockutils.synchronized(vhd_path, 'nova-') def fetch_image_if_not_existing(): if not self._pathutils.exists(vhd_path): - images.fetch(context, image_id, vhd_path, - instance['user_id'], - instance['project_id']) - self._validate_vhd_image(vhd_path) + try: + images.fetch(context, image_id, vhd_path, + instance['user_id'], + instance['project_id']) + except Exception: + with excutils.save_and_reraise_exception(): + if self._pathutils.exists(vhd_path): + self._pathutils.remove(vhd_path) fetch_image_if_not_existing() + + if CONF.use_cow_images: + # Resize the base VHD image as it's not possible to resize a + # differencing VHD. + resized_vhd_path = self._resize_and_cache_vhd(instance, vhd_path) + if resized_vhd_path: + return resized_vhd_path + return vhd_path diff --git a/nova/virt/hyperv/livemigrationops.py b/nova/virt/hyperv/livemigrationops.py index dca5de0cc..94f6f74d8 100644 --- a/nova/virt/hyperv/livemigrationops.py +++ b/nova/virt/hyperv/livemigrationops.py @@ -76,6 +76,18 @@ class LiveMigrationOps(object): LOG.debug(_("post_live_migration_at_destination called"), instance=instance_ref) - def compare_cpu(self, cpu_info): - LOG.debug(_("compare_cpu called %s"), cpu_info) - return True + def check_can_live_migrate_destination(self, ctxt, instance_ref, + src_compute_info, dst_compute_info, + block_migration=False, + disk_over_commit=False): + LOG.debug(_("check_can_live_migrate_destination called"), instance_ref) + return {} + + def check_can_live_migrate_destination_cleanup(self, ctxt, + dest_check_data): + LOG.debug(_("check_can_live_migrate_destination_cleanup called")) + + def check_can_live_migrate_source(self, ctxt, instance_ref, + dest_check_data): + LOG.debug(_("check_can_live_migrate_source called"), instance_ref) + return dest_check_data diff --git a/nova/virt/hyperv/migrationops.py b/nova/virt/hyperv/migrationops.py index 8d5b5e90c..07bf453e5 100644 --- a/nova/virt/hyperv/migrationops.py +++ b/nova/virt/hyperv/migrationops.py @@ -137,16 +137,15 @@ class MigrationOps(object): self._revert_migration_files(instance_name) if self._volumeops.ebs_root_in_block_devices(block_device_info): - boot_vhd_path = None + root_vhd_path = None else: - boot_vhd_path = self._pathutils.get_vhd_path(instance_name) + root_vhd_path = self._pathutils.get_vhd_path(instance_name) self._vmops.create_instance(instance, network_info, block_device_info, - boot_vhd_path) + root_vhd_path) self._vmops.power_on(instance) def _merge_base_vhd(self, diff_vhd_path, base_vhd_path): - base_vhd_copy_path = os.path.join(os.path.dirname(diff_vhd_path), os.path.basename(base_vhd_path)) try: @@ -183,10 +182,6 @@ class MigrationOps(object): def _check_base_disk(self, context, instance, diff_vhd_path, src_base_disk_path): - base_disk_file_name = os.path.basename(src_base_disk_path) - if os.path.splitext(base_disk_file_name)[0] != instance["image_ref"]: - raise vmutils.HyperVException(_("Unexpected base VHD path")) - base_vhd_path = self._imagecache.get_cached_image(context, instance) # If the location of the base host differs between source @@ -206,28 +201,28 @@ class MigrationOps(object): instance_name = instance['name'] if self._volumeops.ebs_root_in_block_devices(block_device_info): - boot_vhd_path = None + root_vhd_path = None else: - boot_vhd_path = self._pathutils.get_vhd_path(instance_name) - if not self._pathutils.exists(boot_vhd_path): + root_vhd_path = self._pathutils.get_vhd_path(instance_name) + if not self._pathutils.exists(root_vhd_path): raise vmutils.HyperVException(_("Cannot find boot VHD " - "file: %s") % boot_vhd_path) + "file: %s") % root_vhd_path) - vhd_info = self._vhdutils.get_vhd_info(boot_vhd_path) + vhd_info = self._vhdutils.get_vhd_info(root_vhd_path) src_base_disk_path = vhd_info.get("ParentPath") if src_base_disk_path: - self._check_base_disk(context, instance, boot_vhd_path, + self._check_base_disk(context, instance, root_vhd_path, src_base_disk_path) if resize_instance: curr_size = vhd_info['MaxInternalSize'] - new_size = instance['root_gb'] * 1024 * 1024 * 1024 + new_size = instance['root_gb'] * 1024 ** 3 if new_size < curr_size: raise vmutils.HyperVException(_("Cannot resize a VHD to a " "smaller size")) elif new_size > curr_size: - self._resize_vhd(boot_vhd_path, new_size) + self._resize_vhd(root_vhd_path, new_size) self._vmops.create_instance(instance, network_info, block_device_info, - boot_vhd_path) + root_vhd_path) self._vmops.power_on(instance) diff --git a/nova/virt/hyperv/pathutils.py b/nova/virt/hyperv/pathutils.py index 1297cd1ed..6c57b8f82 100644 --- a/nova/virt/hyperv/pathutils.py +++ b/nova/virt/hyperv/pathutils.py @@ -18,9 +18,9 @@ import os import shutil -from oslo.config import cfg - +from eventlet.green import subprocess from nova.openstack.common import log as logging +from oslo.config import cfg LOG = logging.getLogger(__name__) @@ -35,7 +35,7 @@ hyperv_opts = [ ] CONF = cfg.CONF -CONF.register_opts(hyperv_opts, 'HYPERV') +CONF.register_opts(hyperv_opts, 'hyperv') CONF.import_opt('instances_path', 'nova.compute.manager') @@ -58,10 +58,17 @@ class PathUtils(object): os.rename(src, dest) def copyfile(self, src, dest): - shutil.copyfile(src, dest) + self.copy(src, dest) def copy(self, src, dest): - shutil.copy(src, dest) + # With large files this is 2x-3x faster than shutil.copy(src, dest), + # especially when copying to a UNC target. + # shutil.copyfileobj(...) with a proper buffer is better than + # shutil.copy(...) but still 20% slower than a shell copy. + # It can be replaced with Win32 API calls to avoid the process + # spawning overhead. + if subprocess.call(['cmd.exe', '/C', 'copy', '/Y', src, dest]): + raise IOError(_('The file copy from %(src)s to %(dest)s failed')) def rmtree(self, path): shutil.rmtree(path) @@ -70,8 +77,8 @@ class PathUtils(object): local_instance_path = os.path.normpath(CONF.instances_path) if remote_server: - if CONF.HYPERV.instances_path_share: - path = CONF.HYPERV.instances_path_share + if CONF.hyperv.instances_path_share: + path = CONF.hyperv.instances_path_share else: # Use an administrative share path = local_instance_path.replace(':', '$') diff --git a/nova/virt/hyperv/vhdutils.py b/nova/virt/hyperv/vhdutils.py index 1e529807d..c21799051 100644 --- a/nova/virt/hyperv/vhdutils.py +++ b/nova/virt/hyperv/vhdutils.py @@ -31,6 +31,13 @@ class VHDUtils(object): if sys.platform == 'win32': self._conn = wmi.WMI(moniker='//./root/virtualization') + def validate_vhd(self, vhd_path): + image_man_svc = self._conn.Msvm_ImageManagementService()[0] + + (job_path, ret_val) = image_man_svc.ValidateVirtualHardDisk( + Path=vhd_path) + self._vmutils.check_ret_val(ret_val, job_path) + def create_differencing_vhd(self, path, parent_path): image_man_svc = self._conn.Msvm_ImageManagementService()[0] diff --git a/nova/virt/hyperv/vif.py b/nova/virt/hyperv/vif.py index d49441cee..8cf401908 100644 --- a/nova/virt/hyperv/vif.py +++ b/nova/virt/hyperv/vif.py @@ -29,11 +29,12 @@ hyperv_opts = [ default=None, help='External virtual switch Name, ' 'if not provided, the first external virtual ' - 'switch is used'), + 'switch is used', + deprecated_group='DEFAULT'), ] CONF = cfg.CONF -CONF.register_opts(hyperv_opts) +CONF.register_opts(hyperv_opts, 'hyperv') LOG = logging.getLogger(__name__) @@ -69,7 +70,7 @@ class HyperVNovaNetworkVIFDriver(HyperVBaseVIFDriver): def plug(self, instance, vif): vswitch_path = self._netutils.get_external_vswitch( - CONF.vswitch_name) + CONF.hyperv.vswitch_name) vm_name = instance['name'] LOG.debug(_('Creating vswitch port for instance: %s') % vm_name) diff --git a/nova/virt/hyperv/vmops.py b/nova/virt/hyperv/vmops.py index c7a4e5468..230c5ea40 100644 --- a/nova/virt/hyperv/vmops.py +++ b/nova/virt/hyperv/vmops.py @@ -44,22 +44,26 @@ hyperv_opts = [ cfg.BoolOpt('limit_cpu_features', default=False, help='Required for live migration among ' - 'hosts with different CPU features'), + 'hosts with different CPU features', + deprecated_group='DEFAULT'), cfg.BoolOpt('config_drive_inject_password', default=False, - help='Sets the admin password in the config drive image'), + help='Sets the admin password in the config drive image', + deprecated_group='DEFAULT'), cfg.StrOpt('qemu_img_cmd', default="qemu-img.exe", help='qemu-img is used to convert between ' - 'different image types'), + 'different image types', + deprecated_group='DEFAULT'), cfg.BoolOpt('config_drive_cdrom', default=False, help='Attaches the Config Drive image as a cdrom drive ' - 'instead of a disk drive') + 'instead of a disk drive', + deprecated_group='DEFAULT') ] CONF = cfg.CONF -CONF.register_opts(hyperv_opts) +CONF.register_opts(hyperv_opts, 'hyperv') CONF.import_opt('use_cow_images', 'nova.virt.driver') CONF.import_opt('network_api_class', 'nova.network') @@ -111,19 +115,39 @@ class VMOps(object): 'num_cpu': info['NumberOfProcessors'], 'cpu_time': info['UpTime']} - def _create_boot_vhd(self, context, instance): + def _create_root_vhd(self, context, instance): base_vhd_path = self._imagecache.get_cached_image(context, instance) - boot_vhd_path = self._pathutils.get_vhd_path(instance['name']) - - if CONF.use_cow_images: - LOG.debug(_("Creating differencing VHD. Parent: " - "%(base_vhd_path)s, Target: %(boot_vhd_path)s") - % locals()) - self._vhdutils.create_differencing_vhd(boot_vhd_path, - base_vhd_path) - else: - self._pathutils.copyfile(base_vhd_path, boot_vhd_path) - return boot_vhd_path + root_vhd_path = self._pathutils.get_vhd_path(instance['name']) + + try: + if CONF.use_cow_images: + LOG.debug(_("Creating differencing VHD. Parent: " + "%(base_vhd_path)s, Target: %(root_vhd_path)s") + % locals()) + self._vhdutils.create_differencing_vhd(root_vhd_path, + base_vhd_path) + else: + LOG.debug(_("Copying VHD image %(base_vhd_path)s to target: " + "%(root_vhd_path)s") % locals()) + self._pathutils.copyfile(base_vhd_path, root_vhd_path) + + base_vhd_info = self._vhdutils.get_vhd_info(base_vhd_path) + base_vhd_size = base_vhd_info['MaxInternalSize'] + root_vhd_size = instance['root_gb'] * 1024 ** 3 + + if root_vhd_size < base_vhd_size: + raise vmutils.HyperVException(_("Cannot resize a VHD to a " + "smaller size")) + elif root_vhd_size > base_vhd_size: + LOG.debug(_("Resizing VHD %(root_vhd_path)s to new " + "size %(root_vhd_size)s") % locals()) + self._vhdutils.resize_vhd(root_vhd_path, root_vhd_size) + except Exception: + with excutils.save_and_reraise_exception(): + if self._pathutils.exists(root_vhd_path): + self._pathutils.remove(root_vhd_path) + + return root_vhd_path def spawn(self, context, instance, image_meta, injected_files, admin_password, network_info, block_device_info=None): @@ -135,13 +159,13 @@ class VMOps(object): raise exception.InstanceExists(name=instance_name) if self._volumeops.ebs_root_in_block_devices(block_device_info): - boot_vhd_path = None + root_vhd_path = None else: - boot_vhd_path = self._create_boot_vhd(context, instance) + root_vhd_path = self._create_root_vhd(context, instance) try: self.create_instance(instance, network_info, block_device_info, - boot_vhd_path) + root_vhd_path) if configdrive.required_by(instance): self._create_config_drive(instance, injected_files, @@ -154,17 +178,17 @@ class VMOps(object): raise vmutils.HyperVException(_('Spawn instance failed')) def create_instance(self, instance, network_info, - block_device_info, boot_vhd_path): + block_device_info, root_vhd_path): instance_name = instance['name'] self._vmutils.create_vm(instance_name, instance['memory_mb'], instance['vcpus'], - CONF.limit_cpu_features) + CONF.hyperv.limit_cpu_features) - if boot_vhd_path: + if root_vhd_path: self._vmutils.attach_ide_drive(instance_name, - boot_vhd_path, + root_vhd_path, 0, 0, constants.IDE_DISK) @@ -173,7 +197,7 @@ class VMOps(object): self._volumeops.attach_volumes(block_device_info, instance_name, - boot_vhd_path is None) + root_vhd_path is None) for vif in network_info: LOG.debug(_('Creating nic for instance: %s'), instance_name) @@ -190,7 +214,7 @@ class VMOps(object): LOG.info(_('Using config drive for instance: %s'), instance=instance) extra_md = {} - if admin_password and CONF.config_drive_inject_password: + if admin_password and CONF.hyperv.config_drive_inject_password: extra_md['admin_pass'] = admin_password inst_md = instance_metadata.InstanceMetadata(instance, @@ -211,11 +235,11 @@ class VMOps(object): LOG.error(_('Creating config drive failed with error: %s'), e, instance=instance) - if not CONF.config_drive_cdrom: + if not CONF.hyperv.config_drive_cdrom: drive_type = constants.IDE_DISK configdrive_path = os.path.join(instance_path, 'configdrive.vhd') - utils.execute(CONF.qemu_img_cmd, + utils.execute(CONF.hyperv.qemu_img_cmd, 'convert', '-f', 'raw', @@ -238,10 +262,10 @@ class VMOps(object): def _delete_disk_files(self, instance_name): self._pathutils.get_instance_dir(instance_name, - create_dir=False, - remove_dir=True) + create_dir=False, + remove_dir=True) - def destroy(self, instance, network_info=None, cleanup=True, + def destroy(self, instance, network_info=None, block_device_info=None, destroy_disks=True): instance_name = instance['name'] LOG.info(_("Got request to destroy instance: %s"), instance_name) diff --git a/nova/virt/hyperv/volumeops.py b/nova/virt/hyperv/volumeops.py index 0d12b93a2..3542a6194 100644 --- a/nova/virt/hyperv/volumeops.py +++ b/nova/virt/hyperv/volumeops.py @@ -33,20 +33,24 @@ from nova.virt.hyperv import volumeutilsv2 LOG = logging.getLogger(__name__) hyper_volumeops_opts = [ - cfg.IntOpt('hyperv_attaching_volume_retry_count', + cfg.IntOpt('volume_attach_retry_count', default=10, - help='The number of times we retry on attaching volume '), - cfg.IntOpt('hyperv_wait_between_attach_retry', + help='The number of times to retry to attach a volume', + deprecated_name='hyperv_attaching_volume_retry_count', + deprecated_group='DEFAULT'), + cfg.IntOpt('volume_attach_retry_interval', default=5, - help='The seconds to wait between an volume ' - 'attachment attempt'), + help='Interval between volume attachment attempts, in seconds', + deprecated_name='hyperv_wait_between_attach_retry', + deprecated_group='DEFAULT'), cfg.BoolOpt('force_volumeutils_v1', default=False, - help='Force volumeutils v1'), + help='Force volumeutils v1', + deprecated_group='DEFAULT'), ] CONF = cfg.CONF -CONF.register_opts(hyper_volumeops_opts) +CONF.register_opts(hyper_volumeops_opts, 'hyperv') CONF.import_opt('my_ip', 'nova.netconf') @@ -63,7 +67,7 @@ class VolumeOps(object): self._default_root_device = 'vda' def _get_volume_utils(self): - if(not CONF.force_volumeutils_v1 and + if(not CONF.hyperv.force_volumeutils_v1 and self._hostutils.get_windows_version() >= 6.2): return volumeutilsv2.VolumeUtilsV2() else: @@ -171,12 +175,12 @@ class VolumeOps(object): LOG.debug(_('Device number: %(device_number)s, ' 'target lun: %(target_lun)s') % locals()) #Finding Mounted disk drive - for i in range(1, CONF.hyperv_attaching_volume_retry_count): + for i in range(1, CONF.hyperv.volume_attach_retry_count): mounted_disk_path = self._vmutils.get_mounted_disk_by_drive_number( device_number) if mounted_disk_path: break - time.sleep(CONF.hyperv_wait_between_attach_retry) + time.sleep(CONF.hyperv.volume_attach_retry_interval) if not mounted_disk_path: raise vmutils.HyperVException(_('Unable to find a mounted disk ' diff --git a/nova/virt/hyperv/volumeutils.py b/nova/virt/hyperv/volumeutils.py index 6d623fca7..e77b463fe 100644 --- a/nova/virt/hyperv/volumeutils.py +++ b/nova/virt/hyperv/volumeutils.py @@ -66,8 +66,10 @@ class VolumeUtils(basevolumeutils.BaseVolumeUtils): self.execute('iscsicli.exe ' + 'LisTargets') #Sending login self.execute('iscsicli.exe ' + 'qlogintarget ' + target_iqn) - #Waiting the disk to be mounted. Research this to avoid sleep - time.sleep(CONF.hyperv_wait_between_attach_retry) + #Waiting the disk to be mounted. + #TODO(pnavarro): Check for the operation to end instead of + #relying on a timeout + time.sleep(CONF.hyperv.volume_attach_retry_interval) def logout_storage_target(self, target_iqn): """Logs out storage target through its session id.""" diff --git a/nova/virt/hyperv/volumeutilsv2.py b/nova/virt/hyperv/volumeutilsv2.py index 2dc86c2e0..79d2d1876 100644 --- a/nova/virt/hyperv/volumeutilsv2.py +++ b/nova/virt/hyperv/volumeutilsv2.py @@ -56,8 +56,10 @@ class VolumeUtilsV2(basevolumeutils.BaseVolumeUtils): target = self._conn_storage.MSFT_iSCSITarget target.Connect(NodeAddress=target_iqn, IsPersistent=True) - #Waiting the disk to be mounted. Research this - time.sleep(CONF.hyperv_wait_between_attach_retry) + #Waiting the disk to be mounted. + #TODO(pnavarro): Check for the operation to end instead of + #relying on a timeout + time.sleep(CONF.hyperv.volume_attach_retry_interval) def logout_storage_target(self, target_iqn): """Logs out storage target through its session id.""" diff --git a/nova/virt/libvirt/__init__.py b/nova/virt/libvirt/__init__.py index 535d6c729..784cf92d3 100644 --- a/nova/virt/libvirt/__init__.py +++ b/nova/virt/libvirt/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/libvirt/blockinfo.py b/nova/virt/libvirt/blockinfo.py index 09e3809d9..3e4b3995c 100644 --- a/nova/virt/libvirt/blockinfo.py +++ b/nova/virt/libvirt/blockinfo.py @@ -201,7 +201,7 @@ def get_disk_bus_for_device_type(virt_type, # Prefer a disk bus set against the image first of all if image_meta: - key = device_type + "_bus" + key = "hw_" + device_type + "_bus" disk_bus = image_meta.get('properties', {}).get(key) if disk_bus is not None: if not is_disk_bus_valid_for_virt(virt_type, disk_bus): diff --git a/nova/virt/libvirt/driver.py b/nova/virt/libvirt/driver.py index 5ba97a8a4..9858e0af2 100755 --- a/nova/virt/libvirt/driver.py +++ b/nova/virt/libvirt/driver.py @@ -714,10 +714,10 @@ class LibvirtDriver(driver.ComputeDriver): is_okay = True if not is_okay: - LOG.error(_("Error from libvirt during destroy. " - "Code=%(errcode)s Error=%(e)s") % - locals(), instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_("Error from libvirt during destroy. " + "Code=%(errcode)s Error=%(e)s") % + locals(), instance=instance) def _wait_for_destroy(expected_domid): """Called at an interval until the VM is gone.""" @@ -787,11 +787,11 @@ class LibvirtDriver(driver.ComputeDriver): pass virt_dom.undefine() except libvirt.libvirtError as e: - errcode = e.get_error_code() - LOG.error(_("Error from libvirt during undefine. " - "Code=%(errcode)s Error=%(e)s") % - locals(), instance=instance) - raise + with excutils.save_and_reraise_exception(): + errcode = e.get_error_code() + LOG.error(_("Error from libvirt during undefine. " + "Code=%(errcode)s Error=%(e)s") % + locals(), instance=instance) def _cleanup(self, instance, network_info, block_device_info, destroy_disks): @@ -1667,13 +1667,14 @@ class LibvirtDriver(driver.ComputeDriver): "'%(ex)s'") % {'path': dirpath, 'ex': str(e)}) hasDirectIO = False else: + with excutils.save_and_reraise_exception(): + LOG.error(_("Error on '%(path)s' while checking " + "direct I/O: '%(ex)s'") % + {'path': dirpath, 'ex': str(e)}) + except Exception, e: + with excutils.save_and_reraise_exception(): LOG.error(_("Error on '%(path)s' while checking direct I/O: " "'%(ex)s'") % {'path': dirpath, 'ex': str(e)}) - raise - except Exception, e: - LOG.error(_("Error on '%(path)s' while checking direct I/O: " - "'%(ex)s'") % {'path': dirpath, 'ex': str(e)}) - raise finally: try: os.unlink(testfile) @@ -1850,9 +1851,10 @@ class LibvirtDriver(driver.ComputeDriver): try: cdb.make_drive(configdrive_path) except exception.ProcessExecutionError, e: - LOG.error(_('Creating config drive failed with error: %s'), - e, instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_('Creating config drive failed ' + 'with error: %s'), + e, instance=instance) # File injection elif CONF.libvirt_inject_partition != -2: @@ -1892,10 +1894,10 @@ class LibvirtDriver(driver.ComputeDriver): use_cow=CONF.use_cow_images, mandatory=('files',)) except Exception as e: - LOG.error(_('Error injecting data into image ' - '%(img_id)s (%(e)s)') % locals(), - instance=instance) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_('Error injecting data into image ' + '%(img_id)s (%(e)s)') % locals(), + instance=instance) if CONF.libvirt_type == 'uml': libvirt_utils.chown(image('disk').path, 'root') @@ -1986,7 +1988,7 @@ class LibvirtDriver(driver.ComputeDriver): return cpu - def get_guest_disk_config(self, instance, name, disk_mapping, + def get_guest_disk_config(self, instance, name, disk_mapping, inst_type, image_type=None): image = self.image_backend.image(instance, name, @@ -1996,7 +1998,7 @@ class LibvirtDriver(driver.ComputeDriver): disk_info['dev'], disk_info['type'], self.disk_cachemode, - instance['extra_specs']) + inst_type['extra_specs']) def get_guest_storage_config(self, instance, image_meta, disk_info, @@ -2019,24 +2021,28 @@ class LibvirtDriver(driver.ComputeDriver): if rescue: diskrescue = self.get_guest_disk_config(instance, 'disk.rescue', - disk_mapping) + disk_mapping, + inst_type) devices.append(diskrescue) diskos = self.get_guest_disk_config(instance, 'disk', - disk_mapping) + disk_mapping, + inst_type) devices.append(diskos) else: if 'disk' in disk_mapping: diskos = self.get_guest_disk_config(instance, 'disk', - disk_mapping) + disk_mapping, + inst_type) devices.append(diskos) if 'disk.local' in disk_mapping: disklocal = self.get_guest_disk_config(instance, 'disk.local', - disk_mapping) + disk_mapping, + inst_type) devices.append(disklocal) self.virtapi.instance_update( nova_context.get_admin_context(), instance['uuid'], @@ -2048,13 +2054,14 @@ class LibvirtDriver(driver.ComputeDriver): diskeph = self.get_guest_disk_config( instance, blockinfo.get_eph_disk(eph), - disk_mapping) + disk_mapping, inst_type) devices.append(diskeph) if 'disk.swap' in disk_mapping: diskswap = self.get_guest_disk_config(instance, 'disk.swap', - disk_mapping) + disk_mapping, + inst_type) devices.append(diskswap) self.virtapi.instance_update( nova_context.get_admin_context(), instance['uuid'], @@ -2072,6 +2079,7 @@ class LibvirtDriver(driver.ComputeDriver): diskconfig = self.get_guest_disk_config(instance, 'disk.config', disk_mapping, + inst_type, 'raw') devices.append(diskconfig) @@ -2100,7 +2108,10 @@ class LibvirtDriver(driver.ComputeDriver): 'ramdisk_id' if a ramdisk is needed for the rescue image and 'kernel_id' if a kernel is needed for the rescue image. """ - inst_type = instance['instance_type'] + + inst_type = self.virtapi.instance_type_get( + nova_context.get_admin_context(read_deleted='yes'), + instance['instance_type_id']) inst_path = libvirt_utils.get_instance_path(instance) disk_mapping = disk_info['mapping'] @@ -2112,7 +2123,7 @@ class LibvirtDriver(driver.ComputeDriver): guest.vcpus = inst_type['vcpus'] quota_items = ['cpu_shares', 'cpu_period', 'cpu_quota'] - for key, value in instance['extra_specs'].iteritems(): + for key, value in inst_type['extra_specs'].iteritems(): if key in quota_items: setattr(guest, key, value) @@ -2941,9 +2952,9 @@ class LibvirtDriver(driver.ComputeDriver): try: ret = self._conn.compareCPU(cpu.to_xml(), 0) except libvirt.libvirtError, e: - ret = e.message - LOG.error(m % locals()) - raise + with excutils.save_and_reraise_exception(): + ret = e.message + LOG.error(m % locals()) if ret <= 0: LOG.error(m % locals()) @@ -3496,6 +3507,11 @@ class LibvirtDriver(driver.ComputeDriver): instance) timer.start(interval=0.5).wait() + def _cleanup_failed_migration(self, inst_base): + """Make sure that a failed migrate doesn't prevent us from rolling + back in a revert.""" + shutil.rmtree(inst_base) + def finish_revert_migration(self, instance, network_info, block_device_info=None): LOG.debug(_("Starting finish_revert_migration"), @@ -3503,7 +3519,15 @@ class LibvirtDriver(driver.ComputeDriver): inst_base = libvirt_utils.get_instance_path(instance) inst_base_resize = inst_base + "_resize" - utils.execute('mv', inst_base_resize, inst_base) + + # NOTE(danms): if we're recovering from a failed migration, + # make sure we don't have a left-over same-host base directory + # that would conflict. Also, don't fail on the rename if the + # failure happened early. + if os.path.exists(inst_base_resize): + if os.path.exists(inst_base): + self._cleanup_failed_migration(inst_base) + utils.execute('mv', inst_base_resize, inst_base) disk_info = blockinfo.get_disk_info(CONF.libvirt_type, instance, diff --git a/nova/virt/libvirt/utils.py b/nova/virt/libvirt/utils.py index cf3fd9d26..808560b54 100755 --- a/nova/virt/libvirt/utils.py +++ b/nova/virt/libvirt/utils.py @@ -5,7 +5,7 @@ # All Rights Reserved. # Copyright (c) 2010 Citrix Systems, Inc. # Copyright (c) 2011 Piston Cloud Computing, Inc -# Copyright (c) 2011 OpenStack LLC +# Copyright (c) 2011 OpenStack Foundation # (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 8d9664751..68b0505aa 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -2,7 +2,7 @@ # Copyright (C) 2011 Midokura KK # Copyright (C) 2011 Nicira, Inc -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -101,7 +101,8 @@ class LibvirtBaseVIFDriver(object): # If the user has specified a 'vif_model' against the # image then honour that model if image_meta: - vif_model = image_meta.get('properties', {}).get('vif_model') + vif_model = image_meta.get('properties', + {}).get('hw_vif_model') if vif_model is not None: model = vif_model diff --git a/nova/virt/libvirt/volume.py b/nova/virt/libvirt/volume.py index 1af29fa56..81ac0ac42 100644 --- a/nova/virt/libvirt/volume.py +++ b/nova/virt/libvirt/volume.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # (c) Copyright 2013 Hewlett-Packard Development Company, L.P. # All Rights Reserved. # diff --git a/nova/virt/powervm/__init__.py b/nova/virt/powervm/__init__.py index 1b63f8310..88f3adc91 100644 --- a/nova/virt/powervm/__init__.py +++ b/nova/virt/powervm/__init__.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/powervm/blockdev.py b/nova/virt/powervm/blockdev.py index 6c8e4b9a5..75f90e327 100644 --- a/nova/virt/powervm/blockdev.py +++ b/nova/virt/powervm/blockdev.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -20,6 +20,7 @@ import re from oslo.config import cfg +from nova.compute import task_states from nova.image import glance from nova.openstack.common import excutils from nova.openstack.common import log as logging @@ -69,13 +70,15 @@ class PowerVMDiskAdapter(object): pass def create_image_from_volume(self, device_name, context, - image_id, image_meta): + image_id, image_meta, update_task_state): """Capture the contents of a volume and upload to glance :param device_name: device in /dev/ to capture :param context: nova context for operation :param image_id: image reference to pre-created image in glance :param image_meta: metadata for new image + :param update_task_state: Function reference that allows for updates + to the instance task state """ pass @@ -196,14 +199,18 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): return {'device_name': disk_name} def create_image_from_volume(self, device_name, context, - image_id, image_meta): + image_id, image_meta, update_task_state): """Capture the contents of a volume and upload to glance :param device_name: device in /dev/ to capture :param context: nova context for operation :param image_id: image reference to pre-created image in glance :param image_meta: metadata for new image + :param update_task_state: Function reference that allows for updates + to the instance task state. """ + # Updating instance task state before capturing instance as a file + update_task_state(task_state=task_states.IMAGE_PENDING_UPLOAD) # do the disk copy dest_file_path = common.aix_path_join(CONF.powervm_img_remote_path, @@ -219,6 +226,12 @@ class PowerVMLocalVolumeAdapter(PowerVMDiskAdapter): glance_service, image_id = glance.get_remote_image_service( context, image_id) + # Updating instance task state before uploading image + # Snapshot will complete but instance state will not change + # to none in compute manager if expected state is not correct + update_task_state(task_state=task_states.IMAGE_UPLOADING, + expected_state=task_states.IMAGE_PENDING_UPLOAD) + # upload snapshot file to glance with open(snapshot_file_path, 'r') as img_file: glance_service.update(context, diff --git a/nova/virt/powervm/command.py b/nova/virt/powervm/command.py index 25cc2c6cd..eec7fc2d3 100644 --- a/nova/virt/powervm/command.py +++ b/nova/virt/powervm/command.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/powervm/common.py b/nova/virt/powervm/common.py index d98d4ae89..b36fa57f3 100644 --- a/nova/virt/powervm/common.py +++ b/nova/virt/powervm/common.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -31,11 +31,12 @@ LOG = logging.getLogger(__name__) class Connection(object): - def __init__(self, host, username, password, port=22): + def __init__(self, host, username, password, port=22, keyfile=None): self.host = host self.username = username self.password = password self.port = port + self.keyfile = keyfile def ssh_connect(connection): @@ -51,7 +52,8 @@ def ssh_connect(connection): ssh.connect(connection.host, username=connection.username, password=connection.password, - port=connection.port) + port=connection.port, + key_filename=connection.keyfile) return ssh except Exception: LOG.exception(_('Connection error connecting PowerVM manager')) diff --git a/nova/virt/powervm/constants.py b/nova/virt/powervm/constants.py index 0d1e0892e..9c691352d 100644 --- a/nova/virt/powervm/constants.py +++ b/nova/virt/powervm/constants.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/powervm/driver.py b/nova/virt/powervm/driver.py index 892ac34ef..7484e91b6 100755 --- a/nova/virt/powervm/driver.py +++ b/nova/virt/powervm/driver.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -41,11 +41,13 @@ powervm_opts = [ help='PowerVM manager user password', secret=True), cfg.StrOpt('powervm_img_remote_path', - default=None, - help='PowerVM image remote path'), + default='/home/padmin', + help='PowerVM image remote path where images will be moved.' + ' Make sure this path can fit your biggest image in glance'), cfg.StrOpt('powervm_img_local_path', - default=None, - help='Local directory to download glance images to') + default='/tmp', + help='Local directory to download glance images to.' + ' Make sure this path can fit your biggest image in glance') ] CONF = cfg.CONF @@ -124,13 +126,15 @@ class PowerVMDriver(driver.ComputeDriver): {'hostname': hostname, 'ip_addr': ip_addr}) return ip_addr - def snapshot(self, context, instance, image_id): + def snapshot(self, context, instance, image_id, update_task_state): """Snapshots the specified instance. :param context: security context :param instance: Instance object as returned by DB layer. :param image_id: Reference to a pre-created image that will hold the snapshot. + :param update_task_state: Function reference that allows for updates + to the instance task state. """ snapshot_start = time.time() @@ -159,7 +163,7 @@ class PowerVMDriver(driver.ComputeDriver): # disk capture and glance upload self._powervm.capture_image(context, instance, image_id, - new_snapshot_meta) + new_snapshot_meta, update_task_state) snapshot_time = time.time() - snapshot_start inst_name = instance['name'] @@ -296,7 +300,13 @@ class PowerVMDriver(driver.ComputeDriver): block_device_info=None): """Finish reverting a resize, powering back on the instance.""" - # undo instance rename and start new_name = self._get_resize_name(instance['name']) - self._powervm._operator.rename_lpar(new_name, instance['name']) + + # Make sure we don't have a failed same-host migration still + # hanging around + if self.instance_exists(new_name): + if self.instance_exists(instance['name']): + self._powervm.destroy(instance['name']) + # undo instance rename and start + self._powervm._operator.rename_lpar(new_name, instance['name']) self._powervm.power_on(instance['name']) diff --git a/nova/virt/powervm/exception.py b/nova/virt/powervm/exception.py index 50e08eaea..ae9a2be72 100644 --- a/nova/virt/powervm/exception.py +++ b/nova/virt/powervm/exception.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/powervm/lpar.py b/nova/virt/powervm/lpar.py index 907818ca8..66d5df6f5 100644 --- a/nova/virt/powervm/lpar.py +++ b/nova/virt/powervm/lpar.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/powervm/operator.py b/nova/virt/powervm/operator.py index 87f596765..08db2d18a 100644 --- a/nova/virt/powervm/operator.py +++ b/nova/virt/powervm/operator.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 IBM +# Copyright 2012 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -251,13 +251,16 @@ class PowerVMOperator(object): LOG.warn(_("During destroy, LPAR instance '%s' was not found on " "PowerVM system.") % instance_name) - def capture_image(self, context, instance, image_id, image_meta): + def capture_image(self, context, instance, image_id, image_meta, + update_task_state): """Capture the root disk for a snapshot :param context: nova context for this operation :param instance: instance information to capture the image from :param image_id: uuid of pre-created snapshot image :param image_meta: metadata to upload with captured image + :param update_task_state: Function reference that allows for updates + to the instance task state. """ lpar = self._operator.get_lpar(instance['name']) previous_state = lpar['state'] @@ -275,7 +278,7 @@ class PowerVMOperator(object): # do capture and upload self._disk_adapter.create_image_from_volume( - disk_name, context, image_id, image_meta) + disk_name, context, image_id, image_meta, update_task_state) # restart instance if it was running before if previous_state == 'Running': diff --git a/nova/virt/virtapi.py b/nova/virt/virtapi.py index 53cbabc30..963b3c788 100644 --- a/nova/virt/virtapi.py +++ b/nova/virt/virtapi.py @@ -97,3 +97,10 @@ class VirtAPI(object): :param architecture: agent architecture """ raise NotImplementedError() + + def instance_type_get(self, context, instance_type_id): + """Get information about an instance type + :param context: security context + :param instance_type_id: the id of the instance type in question + """ + raise NotImplementedError() diff --git a/nova/virt/vmwareapi/__init__.py b/nova/virt/vmwareapi/__init__.py index 1b9732b44..3e3a35a68 100644 --- a/nova/virt/vmwareapi/__init__.py +++ b/nova/virt/vmwareapi/__init__.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/driver.py b/nova/virt/vmwareapi/driver.py index 5e48f4cd3..eeec4c5c2 100755 --- a/nova/virt/vmwareapi/driver.py +++ b/nova/virt/vmwareapi/driver.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/error_util.py b/nova/virt/vmwareapi/error_util.py index aff890b0c..9527c51d1 100644 --- a/nova/virt/vmwareapi/error_util.py +++ b/nova/virt/vmwareapi/error_util.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/fake.py b/nova/virt/vmwareapi/fake.py index 692e5f253..45d4702e2 100644 --- a/nova/virt/vmwareapi/fake.py +++ b/nova/virt/vmwareapi/fake.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/host.py b/nova/virt/vmwareapi/host.py index 9d11901d6..95d86311c 100644 --- a/nova/virt/vmwareapi/host.py +++ b/nova/virt/vmwareapi/host.py @@ -1,5 +1,5 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 - +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # Copyright (c) 2012 VMware, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -135,6 +135,8 @@ class HostState(object): data["hypervisor_type"] = summary.config.product.name data["hypervisor_version"] = summary.config.product.version data["hypervisor_hostname"] = self._host_name + data["supported_instances"] = [('i686', 'vmware', 'hvm'), + ('x86_64', 'vmware', 'hvm')] self._stats = data return data diff --git a/nova/virt/vmwareapi/io_util.py b/nova/virt/vmwareapi/io_util.py index 6a50c4d6e..9a4c2c1f7 100644 --- a/nova/virt/vmwareapi/io_util.py +++ b/nova/virt/vmwareapi/io_util.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/network_util.py b/nova/virt/vmwareapi/network_util.py index c353e66fd..b2b774cc6 100644 --- a/nova/virt/vmwareapi/network_util.py +++ b/nova/virt/vmwareapi/network_util.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/read_write_util.py b/nova/virt/vmwareapi/read_write_util.py index 5dcdc6fdb..89f5f6908 100644 --- a/nova/virt/vmwareapi/read_write_util.py +++ b/nova/virt/vmwareapi/read_write_util.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vif.py b/nova/virt/vmwareapi/vif.py index 1a28ca35e..4479a926f 100644 --- a/nova/virt/vmwareapi/vif.py +++ b/nova/virt/vmwareapi/vif.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vim.py b/nova/virt/vmwareapi/vim.py index f3a47315b..2b6829d54 100644 --- a/nova/virt/vmwareapi/vim.py +++ b/nova/virt/vmwareapi/vim.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vim_util.py b/nova/virt/vmwareapi/vim_util.py index 7b138d716..e131e007d 100644 --- a/nova/virt/vmwareapi/vim_util.py +++ b/nova/virt/vmwareapi/vim_util.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vm_util.py b/nova/virt/vmwareapi/vm_util.py index bc3bd8a9c..9fb8e9bd5 100644 --- a/nova/virt/vmwareapi/vm_util.py +++ b/nova/virt/vmwareapi/vm_util.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vmops.py b/nova/virt/vmwareapi/vmops.py index 9b136f351..911edbe97 100644 --- a/nova/virt/vmwareapi/vmops.py +++ b/nova/virt/vmwareapi/vmops.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/vmwareapi/vmware_images.py b/nova/virt/vmwareapi/vmware_images.py index e8510b36e..e789b508a 100644 --- a/nova/virt/vmwareapi/vmware_images.py +++ b/nova/virt/vmwareapi/vmware_images.py @@ -2,7 +2,7 @@ # Copyright (c) 2012 VMware, Inc. # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/agent.py b/nova/virt/xenapi/agent.py index 0be26a241..1fe6dff7e 100644 --- a/nova/virt/xenapi/agent.py +++ b/nova/virt/xenapi/agent.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright 2010-2012 OpenStack LLC. +# Copyright 2010-2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/driver.py b/nova/virt/xenapi/driver.py index 347d36255..decaed2b0 100755 --- a/nova/virt/xenapi/driver.py +++ b/nova/virt/xenapi/driver.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/host.py b/nova/virt/xenapi/host.py index 6ddc76494..0abcf7444 100644 --- a/nova/virt/xenapi/host.py +++ b/nova/virt/xenapi/host.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 Citrix Systems, Inc. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/imageupload/glance.py b/nova/virt/xenapi/imageupload/glance.py index 5ea75db16..d306e06b0 100644 --- a/nova/virt/xenapi/imageupload/glance.py +++ b/nova/virt/xenapi/imageupload/glance.py @@ -1,4 +1,4 @@ -# Copyright 2013 OpenStack, LLC +# Copyright 2013 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -13,8 +13,11 @@ # License for the specific language governing permissions and limitations # under the License. +import time + from oslo.config import cfg +from nova import exception from nova.image import glance import nova.openstack.common.log as logging from nova.virt.xenapi import vm_utils @@ -22,6 +25,7 @@ from nova.virt.xenapi import vm_utils LOG = logging.getLogger(__name__) CONF = cfg.CONF +CONF.import_opt('glance_num_retries', 'nova.image.glance') class GlanceStore(object): @@ -32,24 +36,49 @@ class GlanceStore(object): """ # NOTE(sirp): Currently we only support uploading images as VHD, there # is no RAW equivalent (yet) - LOG.debug(_("Asking xapi to upload to glance %(vdi_uuids)s as" - " ID %(image_id)s"), locals(), instance=instance) - + max_attempts = CONF.glance_num_retries + 1 + sleep_time = 0.5 glance_api_servers = glance.get_api_servers() - glance_host, glance_port, glance_use_ssl = glance_api_servers.next() - properties = { 'auto_disk_config': instance['auto_disk_config'], 'os_type': instance['os_type'] or CONF.default_os_type, } - params = {'vdi_uuids': vdi_uuids, - 'image_id': image_id, - 'glance_host': glance_host, - 'glance_port': glance_port, - 'glance_use_ssl': glance_use_ssl, - 'sr_path': vm_utils.get_sr_path(session), - 'auth_token': getattr(context, 'auth_token', None), - 'properties': properties} + for attempt_num in xrange(1, max_attempts + 1): + + (glance_host, + glance_port, + glance_use_ssl) = glance_api_servers.next() + + try: + + params = {'vdi_uuids': vdi_uuids, + 'image_id': image_id, + 'glance_host': glance_host, + 'glance_port': glance_port, + 'glance_use_ssl': glance_use_ssl, + 'sr_path': vm_utils.get_sr_path(session), + 'auth_token': getattr(context, 'auth_token', None), + 'properties': properties} + + LOG.debug(_("Asking xapi to upload to glance %(vdi_uuids)s as" + " ID %(image_id)s" + " glance server: %(glance_host)s:%(glance_port)d" + " attempt %(attempt_num)d/%(max_attempts)d"), + locals(), instance=instance) + + return session.call_plugin_serialized('glance', + 'upload_vhd', + **params) + + except session.XenAPI.Failure as exc: + _type, _method, error = exc.details[:3] + if error == 'RetryableError': + LOG.error(_('upload_vhd failed: %r') % + (exc.details[3:],)) + else: + raise + time.sleep(sleep_time) + sleep_time = min(2 * sleep_time, 15) - session.call_plugin_serialized('glance', 'upload_vhd', **params) + raise exception.CouldNotUploadImage(image_id=image_id) diff --git a/nova/virt/xenapi/pool.py b/nova/virt/xenapi/pool.py index ee39fb2da..5080d8308 100644 --- a/nova/virt/xenapi/pool.py +++ b/nova/virt/xenapi/pool.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2012 Citrix Systems, Inc. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/pool_states.py b/nova/virt/xenapi/pool_states.py index 138f84831..f2ec02c1d 100644 --- a/nova/virt/xenapi/pool_states.py +++ b/nova/virt/xenapi/pool_states.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/virt/xenapi/vif.py b/nova/virt/xenapi/vif.py index f0b9eebbe..66c418e85 100644 --- a/nova/virt/xenapi/vif.py +++ b/nova/virt/xenapi/vif.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright (C) 2011 Nicira, Inc # All Rights Reserved. # diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 28e83198f..26bd9d268 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -2,7 +2,7 @@ # Copyright (c) 2010 Citrix Systems, Inc. # Copyright 2011 Piston Cloud Computing, Inc. -# Copyright 2012 OpenStack, LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -37,6 +37,7 @@ from oslo.config import cfg from nova.api.metadata import base as instance_metadata from nova import block_device +from nova.compute import instance_types from nova.compute import power_state from nova.compute import task_states from nova import exception @@ -208,7 +209,7 @@ def create_vm(session, instance, name_label, kernel, ramdisk, 3. Using hardware virtualization """ - instance_type = instance['instance_type'] + instance_type = instance_types.extract_instance_type(instance) mem = str(long(instance_type['memory_mb']) * 1024 * 1024) vcpus = str(instance_type['vcpus']) @@ -321,8 +322,7 @@ def _is_vm_shutdown(session, vm_ref): def ensure_free_mem(session, instance): - inst_type_id = instance['instance_type_id'] - instance_type = instance['instance_type'] + instance_type = instance_types.extract_instance_type(instance) mem = long(instance_type['memory_mb']) * 1024 * 1024 host = session.get_xenapi_host() host_free_mem = long(session.call_xenapi("host.compute_free_memory", @@ -1143,7 +1143,7 @@ def _check_vdi_size(context, session, instance, vdi_uuid): # FIXME(jk0): this was copied directly from compute.manager.py, let's # refactor this to a common area - instance_type = instance['instance_type'] + instance_type = instance_types.extract_instance_type(instance) allowed_size_gb = instance_type['root_gb'] allowed_size_bytes = allowed_size_gb * 1024 * 1024 * 1024 diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index bf3f631b3..56dd5bd3d 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain @@ -29,6 +29,7 @@ from oslo.config import cfg from nova import block_device from nova.compute import api as compute +from nova.compute import instance_types from nova.compute import power_state from nova.compute import task_states from nova.compute import vm_mode @@ -214,12 +215,22 @@ class VMOps(object): name_label = self._get_orig_vm_name_label(instance) vm_ref = vm_utils.lookup(self._session, name_label) - # Remove the '-orig' suffix (which was added in case the resized VM - # ends up on the source host, common during testing) - name_label = instance['name'] - vm_utils.set_vm_name_label(self._session, vm_ref, name_label) - - self._attach_mapped_block_devices(instance, block_device_info) + # NOTE(danms): if we're reverting migration in the failure case, + # make sure we don't have a conflicting vm still running here, + # as might be the case in a failed migrate-to-same-host situation + new_ref = vm_utils.lookup(self._session, instance['name']) + if vm_ref is not None: + if new_ref is not None: + self._destroy(instance, new_ref) + # Remove the '-orig' suffix (which was added in case the + # resized VM ends up on the source host, common during + # testing) + name_label = instance['name'] + vm_utils.set_vm_name_label(self._session, vm_ref, name_label) + self._attach_mapped_block_devices(instance, block_device_info) + elif new_ref is not None: + # We crashed before the -orig backup was made + vm_ref = new_ref self._start(instance, vm_ref) @@ -511,7 +522,7 @@ class VMOps(object): def _attach_disks(self, instance, vm_ref, name_label, vdis, disk_image_type, admin_password=None, files=None): ctx = nova_context.get_admin_context() - instance_type = instance['instance_type'] + instance_type = instance_types.extract_instance_type(instance) # Attach (required) root disk if disk_image_type == vm_utils.ImageType.DISK_ISO: @@ -638,7 +649,8 @@ class VMOps(object): agent.resetnetwork() # Set VCPU weight - vcpu_weight = instance['instance_type']['vcpu_weight'] + instance_type = instance_types.extract_instance_type(instance) + vcpu_weight = instance_type['vcpu_weight'] if vcpu_weight is not None: LOG.debug(_("Setting VCPU weight"), instance=instance) self._session.call_xenapi('VM.add_to_VCPUs_params', vm_ref, diff --git a/nova/virt/xenapi/volume_utils.py b/nova/virt/xenapi/volume_utils.py index edf92cee9..7c77b5e0f 100644 --- a/nova/virt/xenapi/volume_utils.py +++ b/nova/virt/xenapi/volume_utils.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright (c) 2013 Openstack, LLC. +# Copyright (c) 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/virt/xenapi/volumeops.py b/nova/virt/xenapi/volumeops.py index 88119e10d..d3c3046b7 100644 --- a/nova/virt/xenapi/volumeops.py +++ b/nova/virt/xenapi/volumeops.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright (c) 2013 Openstack, LLC. +# Copyright (c) 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/nova/vnc/__init__.py b/nova/vnc/__init__.py index 6a4c2eb4a..f8256beef 100644 --- a/nova/vnc/__init__.py +++ b/nova/vnc/__init__.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010 OpenStack, LLC. +# Copyright (c) 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/vnc/xvp_proxy.py b/nova/vnc/xvp_proxy.py index 3efa23f8b..4331e5b40 100644 --- a/nova/vnc/xvp_proxy.py +++ b/nova/vnc/xvp_proxy.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2012 OpenStack, LLC. +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/nova/weights.py b/nova/weights.py index 981171b3e..7dca2e40d 100644 --- a/nova/weights.py +++ b/nova/weights.py @@ -1,4 +1,4 @@ -# Copyright (c) 2011-2012 OpenStack, LLC. +# Copyright (c) 2011-2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/nova/wsgi.py b/nova/wsgi.py index 7b85d0a5b..72e464919 100644 --- a/nova/wsgi.py +++ b/nova/wsgi.py @@ -2,7 +2,7 @@ # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -34,6 +34,7 @@ import webob.dec import webob.exc from nova import exception +from nova.openstack.common import excutils from nova.openstack.common import log as logging wsgi_opts = [ @@ -175,9 +176,9 @@ class Server(object): CONF.tcp_keepidle) except Exception: - LOG.error(_("Failed to start %(name)s on %(host)s" - ":%(port)s with SSL support") % self.__dict__) - raise + with excutils.save_and_reraise_exception(): + LOG.error(_("Failed to start %(name)s on %(host)s" + ":%(port)s with SSL support") % self.__dict__) wsgi_kwargs = { 'func': eventlet.wsgi.server, diff --git a/openstack-common.conf b/openstack-common.conf index 36abed038..a2688fa45 100644 --- a/openstack-common.conf +++ b/openstack-common.conf @@ -1,7 +1,7 @@ [DEFAULT] # The list of modules to copy from openstack-common -modules=cliutils,context,db,db.api,db.sqlalchemy,excutils,eventlet_backdoor,fileutils,gettextutils,importutils,jsonutils,local,lockutils,log,network_utils,notifier,plugin,policy,rootwrap,setup,timeutils,rpc,uuidutils,install_venv_common,flakes,version,processutils +modules=cliutils,context,db,excutils,eventlet_backdoor,fileutils,gettextutils,importutils,jsonutils,local,lockutils,log,network_utils,notifier,plugin,policy,rootwrap,setup,timeutils,rpc,uuidutils,install_venv_common,flakes,version,processutils # The base module to hold the copy of openstack.common base=nova diff --git a/plugins/xenserver/networking/etc/init.d/host-rules b/plugins/xenserver/networking/etc/init.d/host-rules index 798da9552..7f8134c91 100755 --- a/plugins/xenserver/networking/etc/init.d/host-rules +++ b/plugins/xenserver/networking/etc/init.d/host-rules @@ -5,7 +5,7 @@ # chkconfig: 2345 85 15 # description: Networking Host Rules for Multi Tenancy Protections -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/networking/etc/init.d/openvswitch-nova b/plugins/xenserver/networking/etc/init.d/openvswitch-nova index 5f5249d9c..096426b2e 100755 --- a/plugins/xenserver/networking/etc/init.d/openvswitch-nova +++ b/plugins/xenserver/networking/etc/init.d/openvswitch-nova @@ -6,7 +6,7 @@ # description: Apply initial OVS flows for Nova # Copyright 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright (C) 2009, 2010, 2011 Nicira Networks, Inc. # All Rights Reserved. # diff --git a/plugins/xenserver/networking/etc/xensource/scripts/novalib.py b/plugins/xenserver/networking/etc/xensource/scripts/novalib.py index 0f88e52bb..9189c601f 100644 --- a/plugins/xenserver/networking/etc/xensource/scripts/novalib.py +++ b/plugins/xenserver/networking/etc/xensource/scripts/novalib.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_base_flows.py b/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_base_flows.py index dabc5be6b..039cda172 100755 --- a/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_base_flows.py +++ b/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_base_flows.py @@ -2,7 +2,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_vif_flows.py b/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_vif_flows.py index 6e41e1e19..0aea079ff 100755 --- a/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_vif_flows.py +++ b/plugins/xenserver/networking/etc/xensource/scripts/ovs_configure_vif_flows.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py index 106525a16..26bcd16ce 100755 --- a/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py +++ b/plugins/xenserver/networking/etc/xensource/scripts/vif_rules.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2010-2011 OpenStack LLC. +# Copyright 2010-2011 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/_bittorrent_seeder b/plugins/xenserver/xenapi/etc/xapi.d/plugins/_bittorrent_seeder index 88262139e..3e566a988 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/_bittorrent_seeder +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/_bittorrent_seeder @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 Openstack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent index c83cb1ace..261edd406 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/agent @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2011 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/bandwidth b/plugins/xenserver/xenapi/etc/xapi.d/plugins/bandwidth index 4c4538fa4..c488b07bd 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/bandwidth +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/bandwidth @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/bittorrent b/plugins/xenserver/xenapi/etc/xapi.d/plugins/bittorrent index fef1862b1..8ae93698d 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/bittorrent +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/bittorrent @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 Openstack, LLC +# Copyright (c) 2012 Openstack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance index 924bf10d7..7902f8791 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/glance @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # Copyright (c) 2010 Citrix Systems, Inc. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. @@ -126,14 +126,18 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, url = '%s://%s:%s/v1/images/%s' % (scheme, glance_host, glance_port, image_id) logging.info("Writing image data to %s" % url) - if glance_use_ssl: - conn = httplib.HTTPSConnection(glance_host, glance_port) - else: - conn = httplib.HTTPConnection(glance_host, glance_port) - # NOTE(sirp): httplib under python2.4 won't accept a file-like object - # to request - conn.putrequest('PUT', '/v1/images/%s' % image_id) + try: + if glance_use_ssl: + conn = httplib.HTTPSConnection(glance_host, glance_port) + else: + conn = httplib.HTTPConnection(glance_host, glance_port) + + # NOTE(sirp): httplib under python2.4 won't accept a file-like object + # to request + conn.putrequest('PUT', '/v1/images/%s' % image_id) + except Exception, error: + raise RetryableError(error) # NOTE(sirp): There is some confusion around OVF. Here's a summary of # where we currently stand: @@ -172,12 +176,18 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, def send_chunked_transfer_encoded(chunk): chunk_len = len(chunk) callback_data['bytes_written'] += chunk_len - conn.send("%x\r\n%s\r\n" % (chunk_len, chunk)) + try: + conn.send("%x\r\n%s\r\n" % (chunk_len, chunk)) + except Exception, error: + raise RetryableError(error) utils.create_tarball( None, staging_path, callback=send_chunked_transfer_encoded) - conn.send("0\r\n\r\n") # Chunked-Transfer terminator + try: + conn.send("0\r\n\r\n") # Chunked-Transfer terminator + except Exception, error: + raise RetryableError(error) bytes_written = callback_data['bytes_written'] logging.info("Wrote %d bytes to %s" % (bytes_written, url)) @@ -187,9 +197,11 @@ def _upload_tarball(staging_path, image_id, glance_host, glance_port, logging.error("Unexpected response while writing image data to %s: " "Response Status: %i, Response body: %s" % (url, resp.status, resp.read())) - raise Exception("Unexpected response [%i] while uploading image [%s] " + raise RetryableError("Unexpected response [%i] while uploading " + "image [%s] " "to glance host [%s:%s]" % (resp.status, image_id, glance_host, glance_port)) + conn.close() diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel b/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel index 32e253cde..3aa5a443e 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/kernel @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # Copyright (c) 2010 Citrix Systems, Inc. # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration index 4b6bf8811..6fa95c5e6 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/migration @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py index 510687d7b..2a5d3d9ae 100644 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/utils.py @@ -1,4 +1,4 @@ -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds index 244939f00..1a11416f1 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/workarounds @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright (c) 2012 OpenStack, LLC +# Copyright (c) 2012 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost index 0319af4d2..9f61b79a9 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenhost @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # Copyright 2011 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenstore.py b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenstore.py index be873a7e8..9c86b7cb7 100755 --- a/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenstore.py +++ b/plugins/xenserver/xenapi/etc/xapi.d/plugins/xenstore.py @@ -1,7 +1,7 @@ #!/usr/bin/env python # Copyright (c) 2010 Citrix Systems, Inc. -# Copyright 2010 OpenStack LLC. +# Copyright 2010 OpenStack Foundation # Copyright 2010 United States Government as represented by the # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. diff --git a/run_tests.sh b/run_tests.sh index 2b6eda900..29e723c7f 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -127,10 +127,6 @@ function run_tests { fi if [ $coverage -eq 1 ]; then - # Do not test test_coverage_ext when gathering coverage. - if [ "x$testrargs" = "x" ]; then - testrargs="^(?!.*test.*coverage).*$" - fi TESTRTESTS="$TESTRTESTS --coverage" else TESTRTESTS="$TESTRTESTS --slowest" diff --git a/tools/conf/extract_opts.py b/tools/conf/extract_opts.py index 83d99dd19..89f335d9b 100644 --- a/tools/conf/extract_opts.py +++ b/tools/conf/extract_opts.py @@ -20,6 +20,7 @@ """Extracts OpenStack config option info from module(s).""" +import imp import os import re import socket @@ -98,7 +99,11 @@ def main(srcfiles): def _import_module(mod_str): try: - return importutils.import_module(mod_str) + if mod_str.startswith('bin.'): + imp.load_source(mod_str[4:], os.path.join('bin', mod_str[4:])) + return sys.modules[mod_str[4:]] + else: + return importutils.import_module(mod_str) except (ValueError, AttributeError), err: return None except ImportError, ie: @@ -141,9 +146,9 @@ def _guess_groups(opt, mod_obj): return 'DEFAULT' if group is None: - sys.stderr("Unable to guess what group " + opt.dest + - " in " + mod_obj.__name__ + - " is in out of " + ','.join(groups) + "\n") + sys.stderr.write("Unable to guess what group " + opt.dest + + " in " + mod_obj.__name__ + + " is in out of " + ','.join(groups) + "\n") sys.exit(1) sys.stderr.write("Guessing that " + opt.dest + @@ -154,13 +159,17 @@ def _guess_groups(opt, mod_obj): def _list_opts(obj): + def is_opt(o): + return (isinstance(o, cfg.Opt) and + not isinstance(o, cfg.SubCommandOpt)) + opts = list() for attr_str in dir(obj): attr_obj = getattr(obj, attr_str) - if isinstance(attr_obj, cfg.Opt): + if is_opt(attr_obj): opts.append(attr_obj) elif (isinstance(attr_obj, list) and - all(map(lambda x: isinstance(x, cfg.Opt), attr_obj))): + all(map(lambda x: is_opt(x), attr_obj))): opts.extend(attr_obj) ret = {} @@ -199,6 +208,8 @@ def _sanitize_default(s): """Set up a reasonably sensible default for pybasedir, my_ip and host.""" if s.startswith(BASEDIR): return s.replace(BASEDIR, '/usr/lib/python/site-packages') + elif BASEDIR in s: + return s.replace(BASEDIR, '') elif s == _get_my_ip(): return '10.0.0.1' elif s == socket.getfqdn(): @@ -241,6 +252,8 @@ def _print_opt(opt): print '#%s=%s' % (opt_name, ','.join(opt_default)) elif opt_type == MULTISTROPT: assert(isinstance(opt_default, list)) + if not opt_default: + opt_default = [''] for default in opt_default: print '#%s=%s' % (opt_name, default) print diff --git a/tools/conf/generate_sample.sh b/tools/conf/generate_sample.sh index 25462caa2..283d7a654 100755 --- a/tools/conf/generate_sample.sh +++ b/tools/conf/generate_sample.sh @@ -19,7 +19,13 @@ FILES=$(find nova -type f -name "*.py" ! -path "nova/tests/*" -exec \ grep -l "Opt(" {} \; | sort -u) +BINS=$(echo bin/nova-*) PYTHONPATH=./:${PYTHONPATH} \ - python $(dirname "$0")/extract_opts.py ${FILES} > \ + python $(dirname "$0")/extract_opts.py ${FILES} ${BINS} > \ etc/nova/nova.conf.sample + +# Remove compiled files created by imp.import_source() +for bin in ${BINS}; do + [ -f ${bin}c ] && rm ${bin}c +done diff --git a/tools/db/schema_diff.py b/tools/db/schema_diff.py index a4bcfeaa8..406a2b665 100755 --- a/tools/db/schema_diff.py +++ b/tools/db/schema_diff.py @@ -2,7 +2,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2012 OpenStack LLC. +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tools/enable-pre-commit-hook.sh b/tools/enable-pre-commit-hook.sh index f4f73ee77..be1ed27d1 100755 --- a/tools/enable-pre-commit-hook.sh +++ b/tools/enable-pre-commit-hook.sh @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright 2011 OpenStack LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tools/esx/guest_tool.py b/tools/esx/guest_tool.py index 9876be7a4..2c2793010 100644 --- a/tools/esx/guest_tool.py +++ b/tools/esx/guest_tool.py @@ -1,7 +1,7 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2011 Citrix Systems, Inc. -# Copyright 2011 OpenStack LLC. +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain diff --git a/tools/hacking.py b/tools/hacking.py index 1279e87e9..4e2331054 100755 --- a/tools/hacking.py +++ b/tools/hacking.py @@ -29,6 +29,7 @@ import re import subprocess import sys import tokenize +import traceback import pep8 @@ -176,9 +177,12 @@ def nova_import_rules(logical_line): Examples: Okay: from os import path + Okay: from os import path as p + Okay: from os import (path as p) Okay: import os.path Okay: from nova.compute import rpcapi N302: from os.path import dirname as dirname2 + N302: from os.path import (dirname as dirname2) N303: from os.path import * N304: from .compute import rpcapi """ @@ -186,6 +190,7 @@ def nova_import_rules(logical_line): # pass the doctest, since the relativity depends on the file's locality def is_module_for_sure(mod, search_path=sys.path): + mod = mod.replace('(', '') # Ignore parentheses try: mod_name = mod while '.' in mod_name: @@ -201,10 +206,16 @@ def nova_import_rules(logical_line): # NOTE(vish): the import error might be due # to a missing dependency missing = str(exc).split()[-1] - if missing != mod.split('.')[-1]: + if (missing != mod.split('.')[-1] or + "cannot import" in str(exc)): _missingImport.add(missing) return True return False + except Exception, exc: + # NOTE(jogo) don't stack trace if unexpected import error, + # log and continue. + traceback.print_exc() + return False return True def is_module(mod): @@ -302,9 +313,22 @@ def nova_import_no_db_in_virt(logical_line, filename): yield (0, "N307: nova.db import not allowed in nova/virt/*") -def in_docstring_position(previous_logical): - return (previous_logical.startswith("def ") or - previous_logical.startswith("class ")) +def is_docstring(physical_line, previous_logical): + """Return True if found docstring + 'A docstring is a string literal that occurs as the first statement in a + module, function, class,' + http://www.python.org/dev/peps/pep-0257/#what-is-a-docstring + """ + line = physical_line.lstrip() + start = max([line.find(i) for i in START_DOCSTRING_TRIPLE]) + end = max([line[-4:-1] == i for i in END_DOCSTRING_TRIPLE]) + if (previous_logical.startswith("def ") or + previous_logical.startswith("class ")): + if start is 0: + return True + else: + # Handle multi line comments + return end and start in (-1, len(line) - 4) def nova_docstring_start_space(physical_line, previous_logical): @@ -314,6 +338,8 @@ def nova_docstring_start_space(physical_line, previous_logical): Docstring should not start with space Okay: def foo():\n '''This is good.''' + Okay: def foo():\n a = ''' This is not a docstring.''' + Okay: def foo():\n pass\n ''' This is not.''' N401: def foo():\n ''' This is not.''' """ # short circuit so that we don't fail on our own fail test @@ -324,30 +350,32 @@ def nova_docstring_start_space(physical_line, previous_logical): # it's important that we determine this is actually a docstring, # and not a doc block used somewhere after the first line of a # function def - if in_docstring_position(previous_logical): + if is_docstring(physical_line, previous_logical): pos = max([physical_line.find(i) for i in START_DOCSTRING_TRIPLE]) - if pos != -1 and len(physical_line) > pos + 4: - if physical_line[pos + 3] == ' ': - return (pos, "N401: docstring should not start with" - " a space") + if physical_line[pos + 3] == ' ': + return (pos, "N401: docstring should not start with" + " a space") -def nova_docstring_one_line(physical_line): +def nova_docstring_one_line(physical_line, previous_logical): r"""Check one line docstring end. nova HACKING guide recommendation for one line docstring: A one line docstring looks like this and ends in punctuation. - Okay: '''This is good.''' - Okay: '''This is good too!''' - Okay: '''How about this?''' - N402: '''This is not''' - N402: '''Bad punctuation,''' + Okay: def foo():\n '''This is good.''' + Okay: def foo():\n '''This is good too!''' + Okay: def foo():\n '''How about this?''' + Okay: def foo():\n a = '''This is not a docstring''' + Okay: def foo():\n pass\n '''This is not a docstring''' + Okay: class Foo:\n pass\n '''This is not a docstring''' + N402: def foo():\n '''This is not''' + N402: def foo():\n '''Bad punctuation,''' + N402: class Foo:\n '''Bad punctuation,''' """ #TODO(jogo) make this apply to multi line docstrings as well line = physical_line.lstrip() - - if line.startswith('"') or line.startswith("'"): + if is_docstring(physical_line, previous_logical): pos = max([line.find(i) for i in START_DOCSTRING_TRIPLE]) # start end = max([line[-4:-1] == i for i in END_DOCSTRING_TRIPLE]) # end @@ -356,20 +384,27 @@ def nova_docstring_one_line(physical_line): return pos, "N402: one line docstring needs punctuation." -def nova_docstring_multiline_end(physical_line, previous_logical): +def nova_docstring_multiline_end(physical_line, previous_logical, tokens): r"""Check multi line docstring end. nova HACKING guide recommendation for docstring: Docstring should end on a new line Okay: '''foobar\nfoo\nbar\n''' - N403: def foo():\n'''foobar\nfoo\nbar\n d'''\n\n + Okay: def foo():\n '''foobar\nfoo\nbar\n''' + Okay: class Foo:\n '''foobar\nfoo\nbar\n''' + Okay: def foo():\n a = '''not\na\ndocstring''' + Okay: def foo():\n pass\n'''foobar\nfoo\nbar\n d''' + N403: def foo():\n '''foobar\nfoo\nbar\ndocstring''' + N403: class Foo:\n '''foobar\nfoo\nbar\ndocstring'''\n\n """ - if in_docstring_position(previous_logical): + # if find OP tokens, not a docstring + ops = [t for t, _, _, _, _ in tokens if t == tokenize.OP] + if (is_docstring(physical_line, previous_logical) and len(tokens) > 0 and + len(ops) == 0): pos = max(physical_line.find(i) for i in END_DOCSTRING_TRIPLE) - if pos != -1 and len(physical_line) == pos + 4: - if physical_line.strip() not in START_DOCSTRING_TRIPLE: - return (pos, "N403: multi line docstring end on new line") + if physical_line.strip() not in START_DOCSTRING_TRIPLE: + return (pos, "N403: multi line docstring end on new line") def nova_docstring_multiline_start(physical_line, previous_logical, tokens): @@ -379,9 +414,10 @@ def nova_docstring_multiline_start(physical_line, previous_logical, tokens): Docstring should start with A multi line docstring has a one-line summary Okay: '''foobar\nfoo\nbar\n''' - N404: def foo():\n'''\nfoo\nbar\n''' \n\n + Okay: def foo():\n a = '''\nnot\na docstring\n''' + N404: def foo():\n'''\nfoo\nbar\n'''\n\n """ - if in_docstring_position(previous_logical): + if is_docstring(physical_line, previous_logical): pos = max([physical_line.find(i) for i in START_DOCSTRING_TRIPLE]) # start of docstring when len(tokens)==0 if len(tokens) == 0 and pos != -1 and len(physical_line) == pos + 4: @@ -391,7 +427,7 @@ def nova_docstring_multiline_start(physical_line, previous_logical, tokens): def nova_no_cr(physical_line): - r"""Check that we only use newlines not cariage returns. + r"""Check that we only use newlines not carriage returns. Okay: import os\nimport sys # pep8 doesn't yet replace \r in strings, will work on an @@ -560,7 +596,7 @@ def once_git_check_commit_title(): nova HACKING recommends not referencing a bug or blueprint in first line, it should provide an accurate description of the change N801 - N802 Title limited to 50 chars + N802 Title limited to 72 chars """ #Get title of most recent commit @@ -585,6 +621,8 @@ def once_git_check_commit_title(): "description of the change, not just a reference to a bug " "or blueprint" % title.strip()) error = True + # HACKING.rst recommends commit titles 50 chars or less, but enforces + # a 72 character limit if len(title.decode('utf-8')) > 72: print ("N802: git commit title ('%s') should be under 50 chars" % title.strip()) diff --git a/tools/install_venv.py b/tools/install_venv.py index 17a0be205..dbc7333ec 100644 --- a/tools/install_venv.py +++ b/tools/install_venv.py @@ -4,7 +4,7 @@ # Administrator of the National Aeronautics and Space Administration. # All Rights Reserved. # -# Copyright 2010 OpenStack, LLC +# Copyright 2010 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may diff --git a/tools/install_venv_common.py b/tools/install_venv_common.py index fd9076f0e..413065640 100644 --- a/tools/install_venv_common.py +++ b/tools/install_venv_common.py @@ -1,6 +1,6 @@ # vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright 2013 OpenStack, LLC +# Copyright 2013 OpenStack Foundation # Copyright 2013 IBM Corp. # # Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -185,7 +185,8 @@ class Fedora(Distro): self.run_command(['sudo', 'yum', 'install', '-y', pkg], **kwargs) def apply_patch(self, originalfile, patchfile): - self.run_command(['patch', originalfile, patchfile]) + self.run_command(['patch', '-N', originalfile, patchfile], + check_exit_code=False) def install_virtualenv(self): if self.check_cmd('virtualenv'): diff --git a/tools/patch_tox_venv.py b/tools/patch_tox_venv.py new file mode 100644 index 000000000..399acbcfc --- /dev/null +++ b/tools/patch_tox_venv.py @@ -0,0 +1,38 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2013 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import os +import sys + +import install_venv_common as install_venv + + +def main(argv): + root = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + + venv = os.environ['VIRTUAL_ENV'] + + pip_requires = os.path.join(root, 'tools', 'pip-requires') + test_requires = os.path.join(root, 'tools', 'test-requires') + py_version = "python%s.%s" % (sys.version_info[0], sys.version_info[1]) + project = 'Nova' + install = install_venv.InstallVenv(root, venv, pip_requires, test_requires, + py_version, project) + #NOTE(dprince): For Tox we only run post_process (which patches files, etc) + install.post_process() + +if __name__ == '__main__': + main(sys.argv) diff --git a/tools/pip-requires b/tools/pip-requires index bb4eb7119..d8b836a29 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,5 +1,5 @@ SQLAlchemy>=0.7.8,<=0.7.9 -Cheetah==2.4.4 +Cheetah>=2.4.4 amqplib>=0.6.1 anyjson>=0.2.4 argparse @@ -7,14 +7,14 @@ boto eventlet>=0.9.17 kombu>=1.0.4 lxml>=2.3 -routes==1.12.3 +routes>=1.12.3 WebOb==1.2.3 greenlet>=0.3.1 -PasteDeploy==1.5.0 +PasteDeploy>=1.5.0 paste sqlalchemy-migrate>=0.7.2 netaddr -suds==0.4 +suds>=0.4 paramiko pyasn1 Babel>=0.9.6 @@ -22,9 +22,9 @@ iso8601>=0.1.4 httplib2 setuptools_git>=0.4 python-cinderclient>=1.0.1 -python-quantumclient>=2.1 +python-quantumclient>=2.1.2 python-glanceclient>=0.5.0,<2 python-keystoneclient>=0.2.0 stevedore>=0.7 websockify -http://tarballs.openstack.org/oslo-config/oslo-config-2013.1b4.tar.gz#egg=oslo-config +http://tarballs.openstack.org/oslo-config/oslo.config-1.1.0b1.tar.gz#egg=oslo.config diff --git a/tools/xenserver/cleanup_sm_locks.py b/tools/xenserver/cleanup_sm_locks.py index de455b076..5ccb6e0dd 100755 --- a/tools/xenserver/cleanup_sm_locks.py +++ b/tools/xenserver/cleanup_sm_locks.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2013 OpenStack, LLC +# Copyright 2013 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tools/xenserver/vdi_chain_cleanup.py b/tools/xenserver/vdi_chain_cleanup.py index de1744c5b..b2baca059 100644 --- a/tools/xenserver/vdi_chain_cleanup.py +++ b/tools/xenserver/vdi_chain_cleanup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2012 OpenStack, LLC +# Copyright 2012 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/tools/xenserver/vm_vdi_cleaner.py b/tools/xenserver/vm_vdi_cleaner.py index a842282fa..d2137b8e9 100755 --- a/tools/xenserver/vm_vdi_cleaner.py +++ b/tools/xenserver/vm_vdi_cleaner.py @@ -1,6 +1,6 @@ #!/usr/bin/env python -# Copyright 2011 OpenStack, LLC +# Copyright 2011 OpenStack Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -8,7 +8,9 @@ setenv = VIRTUAL_ENV={envdir} LC_ALL=C deps = -r{toxinidir}/tools/pip-requires -r{toxinidir}/tools/test-requires -commands = python setup.py testr --slowest --testr-args='{posargs}' +commands = + python tools/patch_tox_venv.py + python setup.py testr --slowest --testr-args='{posargs}' [tox:jenkins] sitepackages = True @@ -30,7 +32,9 @@ commands = python tools/flakes.py nova [testenv:cover] # Also do not run test_coverage_ext tests while gathering coverage as those # tests conflict with coverage. +setenv = VIRTUAL_ENV={envdir} commands = + python tools/patch_tox_venv.py python setup.py testr --coverage \ --testr-args='^(?!.*test.*coverage).*$' |