summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/nova/policy.json4
-rw-r--r--nova/api/openstack/compute/contrib/flavorextraspecs.py14
-rw-r--r--nova/api/openstack/compute/contrib/volumes.py14
-rw-r--r--nova/compute/api.py37
-rw-r--r--nova/compute/manager.py13
-rw-r--r--nova/compute/utils.py5
-rw-r--r--nova/conductor/api.py6
-rw-r--r--nova/conductor/manager.py6
-rw-r--r--nova/conductor/rpcapi.py5
-rw-r--r--nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py49
-rw-r--r--nova/exception.py14
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_flavors_extra_specs.py8
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_quota_classes.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_quotas.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_security_groups.py3
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_simple_tenant_usage.py2
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_snapshots.py2
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_virtual_interfaces.py1
-rw-r--r--nova/tests/api/openstack/compute/contrib/test_volumes.py4
-rw-r--r--nova/tests/api/openstack/compute/test_limits.py3
-rw-r--r--nova/tests/api/openstack/compute/test_servers.py6
-rw-r--r--nova/tests/api/openstack/compute/test_versions.py1
-rw-r--r--nova/tests/api/openstack/test_common.py8
-rw-r--r--nova/tests/compute/test_compute.py46
-rw-r--r--nova/tests/conductor/test_conductor.py9
-rw-r--r--nova/tests/fake_policy.py4
-rw-r--r--nova/tests/fake_volume.py2
-rw-r--r--nova/tests/image/test_glance.py1
-rw-r--r--nova/tests/integrated/test_multiprocess_api.py2
-rw-r--r--nova/tests/test_bdm.py1
-rw-r--r--nova/tests/test_imagecache.py1
-rw-r--r--nova/tests/test_libvirt.py1
-rw-r--r--nova/tests/test_migrations.py67
-rw-r--r--nova/tests/test_notifications.py2
-rw-r--r--nova/tests/test_virt_disk_vfs_localfs.py1
-rw-r--r--smoketests/base.py3
-rw-r--r--smoketests/public_network_smoketests.py1
38 files changed, 275 insertions, 74 deletions
diff --git a/etc/nova/policy.json b/etc/nova/policy.json
index 97ae89a38..1a446263f 100644
--- a/etc/nova/policy.json
+++ b/etc/nova/policy.json
@@ -83,6 +83,10 @@
"compute_extension:virtual_interfaces": "",
"compute_extension:virtual_storage_arrays": "",
"compute_extension:volumes": "",
+ "compute_extension:volume_attachments:index": "",
+ "compute_extension:volume_attachments:show": "",
+ "compute_extension:volume_attachments:create": "",
+ "compute_extension:volume_attachments:delete": "",
"compute_extension:volumetypes": "",
"compute_extension:availability_zone:list": "",
"compute_extension:availability_zone:detail": "rule:admin_api",
diff --git a/nova/api/openstack/compute/contrib/flavorextraspecs.py b/nova/api/openstack/compute/contrib/flavorextraspecs.py
index c8deb7b4c..84f157b6a 100644
--- a/nova/api/openstack/compute/contrib/flavorextraspecs.py
+++ b/nova/api/openstack/compute/contrib/flavorextraspecs.py
@@ -34,6 +34,15 @@ class ExtraSpecsTemplate(xmlutil.TemplateBuilder):
return xmlutil.MasterTemplate(xmlutil.make_flat_dict('extra_specs'), 1)
+class ExtraSpecTemplate(xmlutil.TemplateBuilder):
+ def construct(self):
+ sel = xmlutil.Selector(xmlutil.get_items, 0)
+ root = xmlutil.TemplateElement('extra_spec', selector=sel)
+ root.set('key', 0)
+ root.text = 1
+ return xmlutil.MasterTemplate(root, 1)
+
+
class FlavorExtraSpecsController(object):
"""The flavor extra specs API controller for the OpenStack API."""
@@ -70,7 +79,7 @@ class FlavorExtraSpecsController(object):
raise exc.HTTPBadRequest(explanation=unicode(error))
return body
- @wsgi.serializers(xml=ExtraSpecsTemplate)
+ @wsgi.serializers(xml=ExtraSpecTemplate)
def update(self, req, flavor_id, id, body):
context = req.environ['nova.context']
authorize(context)
@@ -87,10 +96,9 @@ class FlavorExtraSpecsController(object):
body)
except exception.MetadataLimitExceeded as error:
raise exc.HTTPBadRequest(explanation=unicode(error))
-
return body
- @wsgi.serializers(xml=ExtraSpecsTemplate)
+ @wsgi.serializers(xml=ExtraSpecTemplate)
def show(self, req, flavor_id, id):
"""Return a single extra spec item."""
context = req.environ['nova.context']
diff --git a/nova/api/openstack/compute/contrib/volumes.py b/nova/api/openstack/compute/contrib/volumes.py
index 47c717495..3fc503217 100644
--- a/nova/api/openstack/compute/contrib/volumes.py
+++ b/nova/api/openstack/compute/contrib/volumes.py
@@ -33,6 +33,15 @@ from nova import volume
LOG = logging.getLogger(__name__)
authorize = extensions.extension_authorizer('compute', 'volumes')
+authorize_attach_index = extensions.extension_authorizer('compute',
+ 'volume_attachments:index')
+authorize_attach_show = extensions.extension_authorizer('compute',
+ 'volume_attachments:show')
+authorize_attach_create = extensions.extension_authorizer('compute',
+ 'volume_attachments:create')
+authorize_attach_delete = extensions.extension_authorizer('compute',
+ 'volume_attachments:delete')
+
def _translate_volume_detail_view(context, vol):
"""Maps keys for volumes details view."""
@@ -329,6 +338,8 @@ class VolumeAttachmentController(wsgi.Controller):
@wsgi.serializers(xml=VolumeAttachmentsTemplate)
def index(self, req, server_id):
"""Returns the list of volume attachments for a given instance."""
+ context = req.environ['nova.context']
+ authorize_attach_index(context)
return self._items(req, server_id,
entity_maker=_translate_attachment_summary_view)
@@ -337,6 +348,7 @@ class VolumeAttachmentController(wsgi.Controller):
"""Return data about the given volume attachment."""
context = req.environ['nova.context']
authorize(context)
+ authorize_attach_show(context)
volume_id = id
try:
@@ -377,6 +389,7 @@ class VolumeAttachmentController(wsgi.Controller):
"""Attach a volume to an instance."""
context = req.environ['nova.context']
authorize(context)
+ authorize_attach_create(context)
if not self.is_valid_body(body, 'volumeAttachment'):
raise exc.HTTPUnprocessableEntity()
@@ -423,6 +436,7 @@ class VolumeAttachmentController(wsgi.Controller):
"""Detach a volume from an instance."""
context = req.environ['nova.context']
authorize(context)
+ authorize_attach_delete(context)
volume_id = id
LOG.audit(_("Detach volume %s"), volume_id, context=context)
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 06ce2e07e..a9d0a1bdd 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -508,6 +508,13 @@ class API(base.Base):
availability_zone, forced_host = self._handle_availability_zone(
availability_zone)
+ system_metadata = {}
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+ for k in instance_type_props:
+ system_metadata["instance_type_%s" % k] = instance_type[k]
+
base_options = {
'reservation_id': reservation_id,
'image_ref': image_href,
@@ -537,7 +544,8 @@ class API(base.Base):
'access_ip_v6': access_ip_v6,
'availability_zone': availability_zone,
'root_device_name': root_device_name,
- 'progress': 0}
+ 'progress': 0,
+ 'system_metadata': system_metadata}
options_from_image = self._inherit_properties_from_image(
image, auto_disk_config)
@@ -558,6 +566,11 @@ class API(base.Base):
security_group, block_device_mapping)
instances.append(instance)
instance_uuids.append(instance['uuid'])
+ self._validate_bdm(context, instance)
+ # send a state update notification for the initial create to
+ # show it going from non-existent to BUILDING
+ notifications.send_update_with_states(context, instance, None,
+ vm_states.BUILDING, None, None, service="api")
# In the case of any exceptions, attempt DB cleanup and rollback the
# quota reservations.
@@ -704,6 +717,23 @@ class API(base.Base):
self.db.block_device_mapping_update_or_create(elevated_context,
values)
+ def _validate_bdm(self, context, instance):
+ for bdm in self.db.block_device_mapping_get_all_by_instance(
+ context, instance['uuid']):
+ # NOTE(vish): For now, just make sure the volumes are accessible.
+ snapshot_id = bdm.get('snapshot_id')
+ volume_id = bdm.get('volume_id')
+ if volume_id is not None:
+ try:
+ self.volume_api.get(context, volume_id)
+ except Exception:
+ raise exception.InvalidBDMVolume(id=volume_id)
+ elif snapshot_id is not None:
+ try:
+ self.volume_api.get_snapshot(context, snapshot_id)
+ except Exception:
+ raise exception.InvalidBDMSnapshot(id=snapshot_id)
+
def _populate_instance_for_bdm(self, context, instance, instance_type,
image, block_device_mapping):
"""Populate instance block device mapping information."""
@@ -818,11 +848,6 @@ class API(base.Base):
self._populate_instance_for_bdm(context, instance,
instance_type, image, block_device_mapping)
- # send a state update notification for the initial create to
- # show it going from non-existent to BUILDING
- notifications.send_update_with_states(context, instance, None,
- vm_states.BUILDING, None, None, service="api")
-
return instance
def _check_create_policies(self, context, availability_zone,
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 9bdab7a25..b52e85440 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -227,7 +227,8 @@ def wrap_instance_fault(function):
with excutils.save_and_reraise_exception():
compute_utils.add_instance_fault_from_exc(context,
- kwargs['instance'], e, sys.exc_info())
+ self.conductor_api, kwargs['instance'],
+ e, sys.exc_info())
return decorated_function
@@ -730,8 +731,8 @@ class ComputeManager(manager.SchedulerDependentManager):
instance_uuid = instance['uuid']
rescheduled = False
- compute_utils.add_instance_fault_from_exc(context, instance,
- exc_info[1], exc_info=exc_info)
+ compute_utils.add_instance_fault_from_exc(context, self.conductor_api,
+ instance, exc_info[1], exc_info=exc_info)
try:
self._deallocate_network(context, instance)
@@ -1463,7 +1464,7 @@ class ComputeManager(manager.SchedulerDependentManager):
LOG.error(_('Cannot reboot instance: %(exc)s'), locals(),
context=context, instance=instance)
compute_utils.add_instance_fault_from_exc(context,
- instance, exc, sys.exc_info())
+ self.conductor_api, instance, exc, sys.exc_info())
# Fall through and reset task_state to None
current_power_state = self._get_power_state(context, instance)
@@ -1993,8 +1994,8 @@ class ComputeManager(manager.SchedulerDependentManager):
rescheduled = False
instance_uuid = instance['uuid']
- compute_utils.add_instance_fault_from_exc(context, instance,
- exc_info[0], exc_info=exc_info)
+ compute_utils.add_instance_fault_from_exc(context, self.conductor_api,
+ instance, exc_info[0], exc_info=exc_info)
try:
scheduler_method = self.scheduler_rpcapi.prep_resize
diff --git a/nova/compute/utils.py b/nova/compute/utils.py
index 1874e886f..daf80874c 100644
--- a/nova/compute/utils.py
+++ b/nova/compute/utils.py
@@ -37,7 +37,8 @@ CONF.import_opt('host', 'nova.netconf')
LOG = log.getLogger(__name__)
-def add_instance_fault_from_exc(context, instance, fault, exc_info=None):
+def add_instance_fault_from_exc(context, conductor,
+ instance, fault, exc_info=None):
"""Adds the specified fault to the database."""
code = 500
@@ -61,7 +62,7 @@ def add_instance_fault_from_exc(context, instance, fault, exc_info=None):
'details': unicode(details),
'host': CONF.host
}
- db.instance_fault_create(context, values)
+ conductor.instance_fault_create(context, values)
def get_device_name_for_instance(context, instance, bdms, device):
diff --git a/nova/conductor/api.py b/nova/conductor/api.py
index d05c94877..b0e5afdcb 100644
--- a/nova/conductor/api.py
+++ b/nova/conductor/api.py
@@ -133,6 +133,9 @@ class LocalAPI(object):
def instance_type_get(self, context, instance_type_id):
return self._manager.instance_type_get(context, instance_type_id)
+ def instance_fault_create(self, context, values):
+ return self._manager.instance_fault_create(context, values)
+
def migration_get(self, context, migration_id):
return self._manager.migration_get(context, migration_id)
@@ -391,6 +394,9 @@ class API(object):
return self.conductor_rpcapi.instance_type_get(context,
instance_type_id)
+ def instance_fault_create(self, context, values):
+ return self.conductor_rpcapi.instance_fault_create(context, values)
+
def migration_get(self, context, migration_id):
return self.conductor_rpcapi.migration_get(context, migration_id)
diff --git a/nova/conductor/manager.py b/nova/conductor/manager.py
index 87b143912..c4ae33622 100644
--- a/nova/conductor/manager.py
+++ b/nova/conductor/manager.py
@@ -43,7 +43,7 @@ datetime_fields = ['launched_at', 'terminated_at']
class ConductorManager(manager.SchedulerDependentManager):
"""Mission: TBD."""
- RPC_API_VERSION = '1.35'
+ RPC_API_VERSION = '1.36'
def __init__(self, *args, **kwargs):
super(ConductorManager, self).__init__(service_name='conductor',
@@ -258,6 +258,10 @@ class ConductorManager(manager.SchedulerDependentManager):
result = self.db.instance_type_get(context, instance_type_id)
return jsonutils.to_primitive(result)
+ def instance_fault_create(self, context, values):
+ result = self.db.instance_fault_create(context, values)
+ return jsonutils.to_primitive(result)
+
def vol_get_usage_by_time(self, context, start_time):
result = self.db.vol_get_usage_by_time(context, start_time)
return jsonutils.to_primitive(result)
diff --git a/nova/conductor/rpcapi.py b/nova/conductor/rpcapi.py
index 1699c85ed..04e576cce 100644
--- a/nova/conductor/rpcapi.py
+++ b/nova/conductor/rpcapi.py
@@ -68,6 +68,7 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
1.33 - Added compute_node_create and compute_node_update
1.34 - Added service_update
1.35 - Added instance_get_active_by_window_joined
+ 1.36 - Added instance_fault_create
"""
BASE_RPC_API_VERSION = '1.0'
@@ -293,6 +294,10 @@ class ConductorAPI(nova.openstack.common.rpc.proxy.RpcProxy):
msg = self.make_msg('instance_get_all_by_host', host=host, node=node)
return self.call(context, msg, version='1.32')
+ def instance_fault_create(self, context, values):
+ msg = self.make_msg('instance_fault_create', values=values)
+ return self.call(context, msg, version='1.36')
+
def action_event_start(self, context, values):
msg = self.make_msg('action_event_start', values=values)
return self.call(context, msg, version='1.25')
diff --git a/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
new file mode 100644
index 000000000..20e75a6eb
--- /dev/null
+++ b/nova/db/sqlalchemy/migrate_repo/versions/153_instance_type_in_system_metadata.py
@@ -0,0 +1,49 @@
+# Copyright 2013 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
+# 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, select, Table
+
+
+def upgrade(migrate_engine):
+ meta = MetaData()
+ meta.bind = migrate_engine
+ instances = Table('instances', meta, autoload=True)
+ instance_types = Table('instance_types', meta, autoload=True)
+ sys_meta = Table('instance_system_metadata', meta, autoload=True)
+
+ # Taken from nova/compute/api.py
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+
+ select_columns = [instances.c.uuid]
+ select_columns += [getattr(instance_types.c, name)
+ for name in instance_type_props]
+
+ q = select(select_columns, from_obj=instances.join(
+ instance_types,
+ instances.c.instance_type_id == instance_types.c.id))
+
+ i = sys_meta.insert()
+ for values in q.execute():
+ for index in range(0, len(instance_type_props)):
+ i.execute({"key": "instance_type_%s" % instance_type_props[index],
+ "value": str(values[index + 1]),
+ "instance_uuid": values[0]})
+
+
+def downgrade(migration_engine):
+ # This migration only touches data, and only metadata at that. No need
+ # to go through and delete old metadata items.
+ pass
diff --git a/nova/exception.py b/nova/exception.py
index bb7749dd7..6915c14bb 100644
--- a/nova/exception.py
+++ b/nova/exception.py
@@ -226,6 +226,20 @@ class Invalid(NovaException):
code = 400
+class InvalidBDM(Invalid):
+ message = _("Block Device Mapping is Invalid.")
+
+
+class InvalidBDMSnapshot(InvalidBDM):
+ message = _("Block Device Mapping is Invalid: "
+ "failed to get snapshot %(id)s.")
+
+
+class InvalidBDMVolume(InvalidBDM):
+ message = _("Block Device Mapping is Invalid: "
+ "failed to get volume %(id)s.")
+
+
class VolumeUnattached(Invalid):
message = _("Volume %(volume_id)s is not attached to anything")
diff --git a/nova/tests/api/openstack/compute/contrib/test_flavors_extra_specs.py b/nova/tests/api/openstack/compute/contrib/test_flavors_extra_specs.py
index bc9f66eb2..5328ec2ee 100644
--- a/nova/tests/api/openstack/compute/contrib/test_flavors_extra_specs.py
+++ b/nova/tests/api/openstack/compute/contrib/test_flavors_extra_specs.py
@@ -172,7 +172,6 @@ class FlavorsExtraSpecsXMLSerializerTest(test.TestCase):
expected = ("<?xml version='1.0' encoding='UTF-8'?>\n"
'<extra_specs><key1>value1</key1></extra_specs>')
text = serializer.serialize(dict(extra_specs={"key1": "value1"}))
- print text
self.assertEqual(text, expected)
def test_deserializer(self):
@@ -182,3 +181,10 @@ class FlavorsExtraSpecsXMLSerializerTest(test.TestCase):
'<extra_specs><key1>value1</key1></extra_specs>')
result = deserializer.deserialize(intext)['body']
self.assertEqual(result, expected)
+
+ def test_show_update_serializer(self):
+ serializer = flavorextraspecs.ExtraSpecTemplate()
+ expected = ("<?xml version='1.0' encoding='UTF-8'?>\n"
+ '<extra_spec key="key1">value1</extra_spec>')
+ text = serializer.serialize(dict({"key1": "value1"}))
+ self.assertEqual(text, expected)
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 a72f5bf0f..0c1378a67 100644
--- a/nova/tests/api/openstack/compute/contrib/test_quota_classes.py
+++ b/nova/tests/api/openstack/compute/contrib/test_quota_classes.py
@@ -138,7 +138,6 @@ class QuotaTemplateXMLSerializerTest(test.TestCase):
cores=90))
text = self.serializer.serialize(exemplar)
- print text
tree = etree.fromstring(text)
self.assertEqual('quota_class_set', tree.tag)
diff --git a/nova/tests/api/openstack/compute/contrib/test_quotas.py b/nova/tests/api/openstack/compute/contrib/test_quotas.py
index dab8c136e..8d518b815 100644
--- a/nova/tests/api/openstack/compute/contrib/test_quotas.py
+++ b/nova/tests/api/openstack/compute/contrib/test_quotas.py
@@ -166,7 +166,6 @@ class QuotaXMLSerializerTest(test.TestCase):
cores=90))
text = self.serializer.serialize(exemplar)
- print text
tree = etree.fromstring(text)
self.assertEqual('quota_set', tree.tag)
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 ccb58f858..231923e6d 100644
--- a/nova/tests/api/openstack/compute/contrib/test_security_groups.py
+++ b/nova/tests/api/openstack/compute/contrib/test_security_groups.py
@@ -1180,7 +1180,6 @@ class TestSecurityGroupXMLSerializer(test.TestCase):
rule = dict(security_group_rule=raw_rule)
text = self.rule_serializer.serialize(rule)
- print text
tree = etree.fromstring(text)
self.assertEqual('security_group_rule', self._tag(tree))
@@ -1212,7 +1211,6 @@ class TestSecurityGroupXMLSerializer(test.TestCase):
sg_group = dict(security_group=raw_group)
text = self.default_serializer.serialize(sg_group)
- print text
tree = etree.fromstring(text)
self._verify_security_group(raw_group, tree)
@@ -1265,7 +1263,6 @@ class TestSecurityGroupXMLSerializer(test.TestCase):
sg_groups = dict(security_groups=groups)
text = self.index_serializer.serialize(sg_groups)
- print text
tree = etree.fromstring(text)
self.assertEqual('security_groups', self._tag(tree))
diff --git a/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py b/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
index ea4565e14..783275ea2 100644
--- a/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
+++ b/nova/tests/api/openstack/compute/contrib/test_server_diagnostics.py
@@ -74,7 +74,6 @@ class TestServerDiagnosticsXMLSerializer(test.TestCase):
exemplar = dict(diag1='foo', diag2='bar')
text = serializer.serialize(exemplar)
- print text
tree = etree.fromstring(text)
self.assertEqual('diagnostics', self._tag(tree))
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 b49a1feb4..13a4e9d61 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
@@ -293,7 +293,6 @@ class SimpleTenantUsageSerializerTest(test.TestCase):
tenant_usage = dict(tenant_usage=raw_usage)
text = serializer.serialize(tenant_usage)
- print text
tree = etree.fromstring(text)
self._verify_tenant_usage(raw_usage, tree)
@@ -378,7 +377,6 @@ class SimpleTenantUsageSerializerTest(test.TestCase):
tenant_usages = dict(tenant_usages=raw_usages)
text = serializer.serialize(tenant_usages)
- print text
tree = etree.fromstring(text)
self.assertEqual('tenant_usages', tree.tag)
diff --git a/nova/tests/api/openstack/compute/contrib/test_snapshots.py b/nova/tests/api/openstack/compute/contrib/test_snapshots.py
index a223178fb..fa0c521fe 100644
--- a/nova/tests/api/openstack/compute/contrib/test_snapshots.py
+++ b/nova/tests/api/openstack/compute/contrib/test_snapshots.py
@@ -271,7 +271,6 @@ class SnapshotSerializerTest(test.TestCase):
)
text = serializer.serialize(dict(snapshot=raw_snapshot))
- print text
tree = etree.fromstring(text)
self._verify_snapshot(raw_snapshot, tree)
@@ -298,7 +297,6 @@ class SnapshotSerializerTest(test.TestCase):
)]
text = serializer.serialize(dict(snapshots=raw_snapshots))
- print text
tree = etree.fromstring(text)
self.assertEqual('snapshots', tree.tag)
diff --git a/nova/tests/api/openstack/compute/contrib/test_virtual_interfaces.py b/nova/tests/api/openstack/compute/contrib/test_virtual_interfaces.py
index 7c61cd51b..cf1c1593f 100644
--- a/nova/tests/api/openstack/compute/contrib/test_virtual_interfaces.py
+++ b/nova/tests/api/openstack/compute/contrib/test_virtual_interfaces.py
@@ -91,7 +91,6 @@ class ServerVirtualInterfaceSerializerTest(test.TestCase):
vifs = dict(virtual_interfaces=raw_vifs)
text = self.serializer.serialize(vifs)
- print text
tree = etree.fromstring(text)
self.assertEqual('virtual_interfaces', self._tag(tree))
diff --git a/nova/tests/api/openstack/compute/contrib/test_volumes.py b/nova/tests/api/openstack/compute/contrib/test_volumes.py
index 3119f55e8..1a8a570e8 100644
--- a/nova/tests/api/openstack/compute/contrib/test_volumes.py
+++ b/nova/tests/api/openstack/compute/contrib/test_volumes.py
@@ -348,7 +348,6 @@ class VolumeSerializerTest(test.TestCase):
device='/foo')
text = serializer.serialize(dict(volumeAttachment=raw_attach))
- print text
tree = etree.fromstring(text)
self.assertEqual('volumeAttachment', tree.tag)
@@ -368,7 +367,6 @@ class VolumeSerializerTest(test.TestCase):
device='/foo2')]
text = serializer.serialize(dict(volumeAttachments=raw_attaches))
- print text
tree = etree.fromstring(text)
self.assertEqual('volumeAttachments', tree.tag)
@@ -401,7 +399,6 @@ class VolumeSerializerTest(test.TestCase):
)
text = serializer.serialize(dict(volume=raw_volume))
- print text
tree = etree.fromstring(text)
self._verify_volume(raw_volume, tree)
@@ -450,7 +447,6 @@ class VolumeSerializerTest(test.TestCase):
)]
text = serializer.serialize(dict(volumes=raw_volumes))
- print text
tree = etree.fromstring(text)
self.assertEqual('volumes', tree.tag)
diff --git a/nova/tests/api/openstack/compute/test_limits.py b/nova/tests/api/openstack/compute/test_limits.py
index 375355a70..e3fff380d 100644
--- a/nova/tests/api/openstack/compute/test_limits.py
+++ b/nova/tests/api/openstack/compute/test_limits.py
@@ -874,7 +874,6 @@ class LimitsXMLSerializationTest(test.TestCase):
"absolute": {}}}
output = serializer.serialize(fixture)
- print output
has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
self.assertTrue(has_dec)
@@ -905,7 +904,6 @@ class LimitsXMLSerializationTest(test.TestCase):
"maxPersonalitySize": 10240}}}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'limits')
@@ -940,7 +938,6 @@ class LimitsXMLSerializationTest(test.TestCase):
"absolute": {}}}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'limits')
diff --git a/nova/tests/api/openstack/compute/test_servers.py b/nova/tests/api/openstack/compute/test_servers.py
index 5456c23af..4bfb1c1e3 100644
--- a/nova/tests/api/openstack/compute/test_servers.py
+++ b/nova/tests/api/openstack/compute/test_servers.py
@@ -4508,7 +4508,6 @@ class ServerXMLSerializationTest(test.TestCase):
}
output = serializer.serialize(fixture)
- print output
has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
self.assertTrue(has_dec)
@@ -4586,7 +4585,6 @@ class ServerXMLSerializationTest(test.TestCase):
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'server')
@@ -4717,7 +4715,6 @@ class ServerXMLSerializationTest(test.TestCase):
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'server')
@@ -4814,7 +4811,6 @@ class ServerXMLSerializationTest(test.TestCase):
]}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'servers_index')
server_elems = root.findall('{0}server'.format(NS))
@@ -4878,7 +4874,6 @@ class ServerXMLSerializationTest(test.TestCase):
]}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'servers_index')
server_elems = root.findall('{0}server'.format(NS))
@@ -5165,7 +5160,6 @@ class ServerXMLSerializationTest(test.TestCase):
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'server')
diff --git a/nova/tests/api/openstack/compute/test_versions.py b/nova/tests/api/openstack/compute/test_versions.py
index 28b109215..bd2e9fa7b 100644
--- a/nova/tests/api/openstack/compute/test_versions.py
+++ b/nova/tests/api/openstack/compute/test_versions.py
@@ -228,7 +228,6 @@ class VersionsTest(test.TestCase):
self.assertEqual(res.content_type, "application/xml")
root = etree.XML(res.body)
- print res.body
xmlutil.validate_schema(root, 'versions')
self.assertTrue(root.xpath('/ns:versions', namespaces=NS))
diff --git a/nova/tests/api/openstack/test_common.py b/nova/tests/api/openstack/test_common.py
index 7e49e4ab8..68a5f0bf4 100644
--- a/nova/tests/api/openstack/test_common.py
+++ b/nova/tests/api/openstack/test_common.py
@@ -377,7 +377,6 @@ class MetadataXMLSerializationTest(test.TestCase):
}
output = serializer.serialize(fixture)
- print output
has_dec = output.startswith("<?xml version='1.0' encoding='UTF-8'?>")
self.assertTrue(has_dec)
@@ -390,7 +389,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
metadata_dict = fixture['metadata']
@@ -409,7 +407,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
metadata_dict = fixture['metadata']
@@ -428,7 +425,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
metadata_dict = fixture['metadata']
@@ -447,7 +443,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
meta_dict = fixture['meta']
(meta_key, meta_value) = meta_dict.items()[0]
@@ -463,7 +458,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
metadata_dict = fixture['metadata']
@@ -482,7 +476,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
meta_dict = fixture['meta']
(meta_key, meta_value) = meta_dict.items()[0]
@@ -499,7 +492,6 @@ class MetadataXMLSerializationTest(test.TestCase):
},
}
output = serializer.serialize(fixture)
- print output
root = etree.XML(output)
xmlutil.validate_schema(root, 'metadata')
metadata_dict = fixture['metadata']
diff --git a/nova/tests/compute/test_compute.py b/nova/tests/compute/test_compute.py
index dc381d800..7b284779e 100644
--- a/nova/tests/compute/test_compute.py
+++ b/nova/tests/compute/test_compute.py
@@ -2722,8 +2722,11 @@ class ComputeTestCase(BaseTestCase):
self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
ctxt = context.get_admin_context()
- compute_utils.add_instance_fault_from_exc(ctxt, instance,
- NotImplementedError('test'), exc_info)
+ compute_utils.add_instance_fault_from_exc(ctxt,
+ self.compute.conductor_api,
+ instance,
+ NotImplementedError('test'),
+ exc_info)
def test_add_instance_fault_with_remote_error(self):
instance = self._create_fake_instance()
@@ -2751,8 +2754,8 @@ class ComputeTestCase(BaseTestCase):
self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
ctxt = context.get_admin_context()
- compute_utils.add_instance_fault_from_exc(ctxt, instance, exc,
- exc_info)
+ compute_utils.add_instance_fault_from_exc(ctxt,
+ self.compute.conductor_api, instance, exc, exc_info)
def test_add_instance_fault_user_error(self):
instance = self._create_fake_instance()
@@ -2779,8 +2782,8 @@ class ComputeTestCase(BaseTestCase):
self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
ctxt = context.get_admin_context()
- compute_utils.add_instance_fault_from_exc(ctxt, instance, user_exc,
- exc_info)
+ compute_utils.add_instance_fault_from_exc(ctxt,
+ self.compute.conductor_api, instance, user_exc, exc_info)
def test_add_instance_fault_no_exc_info(self):
instance = self._create_fake_instance()
@@ -2798,8 +2801,10 @@ class ComputeTestCase(BaseTestCase):
self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
ctxt = context.get_admin_context()
- compute_utils.add_instance_fault_from_exc(ctxt, instance,
- NotImplementedError('test'))
+ compute_utils.add_instance_fault_from_exc(ctxt,
+ self.compute.conductor_api,
+ instance,
+ NotImplementedError('test'))
def test_cleanup_running_deleted_instances(self):
admin_context = context.get_admin_context()
@@ -3780,6 +3785,28 @@ class ComputeAPITestCase(BaseTestCase):
finally:
db.instance_destroy(self.context, ref[0]['uuid'])
+ def test_create_saves_type_in_system_metadata(self):
+ instance_type = instance_types.get_default_instance_type()
+ (ref, resv_id) = self.compute_api.create(
+ self.context,
+ instance_type=instance_type,
+ image_href=None)
+ try:
+ sys_metadata = db.instance_system_metadata_get(self.context,
+ ref[0]['uuid'])
+
+ instance_type_props = ['name', 'memory_mb', 'vcpus', 'root_gb',
+ 'ephemeral_gb', 'flavorid', 'swap',
+ 'rxtx_factor', 'vcpu_weight']
+ for key in instance_type_props:
+ sys_meta_key = "instance_type_%s" % key
+ self.assertTrue(sys_meta_key in sys_metadata)
+ self.assertEqual(str(instance_type[key]),
+ str(sys_metadata[sys_meta_key]))
+
+ finally:
+ db.instance_destroy(self.context, ref[0]['uuid'])
+
def test_create_instance_associates_security_groups(self):
# Make sure create associates security groups.
group = self._create_group()
@@ -6752,6 +6779,7 @@ class ComputeRescheduleOrReraiseTestCase(BaseTestCase):
exc_info = sys.exc_info()
compute_utils.add_instance_fault_from_exc(self.context,
+ self.compute.conductor_api,
self.instance, exc_info[0], exc_info=exc_info)
self.compute._deallocate_network(self.context,
self.instance).AndRaise(InnerTestingException("Error"))
@@ -6802,6 +6830,7 @@ class ComputeRescheduleOrReraiseTestCase(BaseTestCase):
except Exception:
exc_info = sys.exc_info()
compute_utils.add_instance_fault_from_exc(self.context,
+ self.compute.conductor_api,
self.instance, exc_info[0], exc_info=exc_info)
self.compute._deallocate_network(self.context,
self.instance)
@@ -6830,6 +6859,7 @@ class ComputeRescheduleOrReraiseTestCase(BaseTestCase):
exc_info = sys.exc_info()
compute_utils.add_instance_fault_from_exc(self.context,
+ self.compute.conductor_api,
self.instance, exc_info[0], exc_info=exc_info)
self.compute._deallocate_network(self.context,
self.instance)
diff --git a/nova/tests/conductor/test_conductor.py b/nova/tests/conductor/test_conductor.py
index 30d176bbd..c46663e50 100644
--- a/nova/tests/conductor/test_conductor.py
+++ b/nova/tests/conductor/test_conductor.py
@@ -426,6 +426,15 @@ class _BaseTestCase(object):
'fake-values', False)
self.assertEqual(result, 'fake-result')
+ def test_instance_fault_create(self):
+ self.mox.StubOutWithMock(db, 'instance_fault_create')
+ db.instance_fault_create(self.context, 'fake-values').AndReturn(
+ 'fake-result')
+ self.mox.ReplayAll()
+ result = self.conductor.instance_fault_create(self.context,
+ 'fake-values')
+ self.assertEqual(result, 'fake-result')
+
class ConductorTestCase(_BaseTestCase, test.TestCase):
"""Conductor Manager Tests."""
diff --git a/nova/tests/fake_policy.py b/nova/tests/fake_policy.py
index dbf620196..ead43adea 100644
--- a/nova/tests/fake_policy.py
+++ b/nova/tests/fake_policy.py
@@ -157,6 +157,10 @@ policy_data = """
"compute_extension:virtual_interfaces": "",
"compute_extension:virtual_storage_arrays": "",
"compute_extension:volumes": "",
+ "compute_extension:volume_attachments:index": "",
+ "compute_extension:volume_attachments:show": "",
+ "compute_extension:volume_attachments:create": "",
+ "compute_extension:volume_attachments:delete": "",
"compute_extension:volumetypes": "",
"compute_extension:zones": "",
"compute_extension:availability_zone:list": "",
diff --git a/nova/tests/fake_volume.py b/nova/tests/fake_volume.py
index f2aa3ea91..c7430ee6d 100644
--- a/nova/tests/fake_volume.py
+++ b/nova/tests/fake_volume.py
@@ -136,7 +136,6 @@ class API(object):
def create_with_kwargs(self, context, **kwargs):
volume_id = kwargs.get('volume_id', None)
- print volume_id
v = fake_volume(kwargs['size'],
kwargs['name'],
kwargs['description'],
@@ -145,7 +144,6 @@ class API(object):
None,
None,
None)
- print v.vol['id']
if kwargs.get('status', None) is not None:
v.vol['status'] = kwargs['status']
if kwargs['host'] is not None:
diff --git a/nova/tests/image/test_glance.py b/nova/tests/image/test_glance.py
index 9dd9e5121..fb26fa4f1 100644
--- a/nova/tests/image/test_glance.py
+++ b/nova/tests/image/test_glance.py
@@ -339,7 +339,6 @@ class TestGlanceImageService(test.TestCase):
def test_update(self):
fixture = self._make_fixture(name='test image')
image = self.service.create(self.context, fixture)
- print image
image_id = image['id']
fixture['name'] = 'new image name'
self.service.update(self.context, image_id, fixture)
diff --git a/nova/tests/integrated/test_multiprocess_api.py b/nova/tests/integrated/test_multiprocess_api.py
index b2361b13c..ae4fcc32f 100644
--- a/nova/tests/integrated/test_multiprocess_api.py
+++ b/nova/tests/integrated/test_multiprocess_api.py
@@ -63,7 +63,7 @@ class MultiprocessWSGITest(integrated_helpers._IntegratedTestBase):
try:
traceback.print_exc()
except BaseException:
- print "Couldn't print traceback"
+ LOG.error("Couldn't print traceback")
status = 2
# Really exit
diff --git a/nova/tests/test_bdm.py b/nova/tests/test_bdm.py
index 4d62d6bbf..43ca4d7b0 100644
--- a/nova/tests/test_bdm.py
+++ b/nova/tests/test_bdm.py
@@ -246,6 +246,5 @@ class BlockDeviceMappingEc2CloudTestCase(test.TestCase):
result = {}
cloud._format_mappings(properties, result)
- print result
self.assertEqual(result['blockDeviceMapping'].sort(),
expected_result['blockDeviceMapping'].sort())
diff --git a/nova/tests/test_imagecache.py b/nova/tests/test_imagecache.py
index 8142312b9..611519514 100644
--- a/nova/tests/test_imagecache.py
+++ b/nova/tests/test_imagecache.py
@@ -331,7 +331,6 @@ class ImageCacheManagerTestCase(test.TestCase):
base_file1 = os.path.join(base_dir, fingerprint)
base_file2 = os.path.join(base_dir, fingerprint + '_sm')
base_file3 = os.path.join(base_dir, fingerprint + '_10737418240')
- print res
self.assertTrue(res == [(base_file1, False, False),
(base_file2, True, False),
(base_file3, False, True)])
diff --git a/nova/tests/test_libvirt.py b/nova/tests/test_libvirt.py
index f96536893..5a90f3348 100644
--- a/nova/tests/test_libvirt.py
+++ b/nova/tests/test_libvirt.py
@@ -3833,7 +3833,6 @@ class IptablesFirewallTestCase(test.TestCase):
if '*filter' in lines:
self.out6_rules = lines
return '', ''
- print cmd, kwargs
network_model = _fake_network_info(self.stubs, 1, spectacular=True)
diff --git a/nova/tests/test_migrations.py b/nova/tests/test_migrations.py
index 3b67e6439..8c18d5511 100644
--- a/nova/tests/test_migrations.py
+++ b/nova/tests/test_migrations.py
@@ -24,6 +24,7 @@ properly both upgrading and downgrading, and that no data loss occurs
if possible.
"""
+import collections
import commands
import ConfigParser
import os
@@ -452,3 +453,69 @@ class TestMigrations(test.TestCase):
self.assertEqual("", volume.deleted)
volume = volumes.select(volumes.c.id == "second").execute().first()
self.assertEqual(volume.id, volume.deleted)
+
+ # migration 153, copy flavor information into system_metadata
+ def _prerun_153(self, engine):
+ fake_types = [
+ dict(id=10, name='type1', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="1", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=False,
+ is_public=True),
+ dict(id=11, name='type2', memory_mb=512, vcpus=1,
+ root_gb=10, ephemeral_gb=5, flavorid="2", swap=0,
+ rxtx_factor=1.5, vcpu_weight=2, disabled=False,
+ is_public=True),
+ dict(id=12, name='type3', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="3", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=False,
+ is_public=False),
+ dict(id=13, name='type4', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="4", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=True,
+ is_public=True),
+ dict(id=14, name='type5', memory_mb=128, vcpus=1,
+ root_gb=10, ephemeral_gb=0, flavorid="5", swap=0,
+ rxtx_factor=1.0, vcpu_weight=1, disabled=True,
+ is_public=False),
+ ]
+
+ fake_instances = [
+ dict(uuid='m153-uuid1', instance_type_id=10),
+ dict(uuid='m153-uuid2', instance_type_id=11),
+ dict(uuid='m153-uuid3', instance_type_id=12),
+ dict(uuid='m153-uuid4', instance_type_id=13),
+ # NOTE(danms): no use of type5
+ ]
+
+ instances = get_table(engine, 'instances')
+ instance_types = get_table(engine, 'instance_types')
+ engine.execute(instance_types.insert(), fake_types)
+ engine.execute(instances.insert(), fake_instances)
+
+ return fake_types, fake_instances
+
+ def _check_153(self, engine, data):
+ fake_types, fake_instances = data
+ # NOTE(danms): Fetch all the tables and data from scratch after change
+ instances = get_table(engine, 'instances')
+ instance_types = get_table(engine, 'instance_types')
+ sys_meta = get_table(engine, 'instance_system_metadata')
+
+ # Collect all system metadata, indexed by instance_uuid
+ metadata = collections.defaultdict(dict)
+ for values in sys_meta.select().execute():
+ metadata[values['instance_uuid']][values['key']] = values['value']
+
+ # Taken from nova/compute/api.py
+ instance_type_props = ['id', 'name', 'memory_mb', 'vcpus',
+ 'root_gb', 'ephemeral_gb', 'flavorid',
+ 'swap', 'rxtx_factor', 'vcpu_weight']
+
+ for instance in fake_instances:
+ inst_sys_meta = metadata[instance['uuid']]
+ inst_type = fake_types[instance['instance_type_id'] - 10]
+ for prop in instance_type_props:
+ prop_name = 'instance_type_%s' % prop
+ self.assertIn(prop_name, inst_sys_meta)
+ self.assertEqual(str(inst_sys_meta[prop_name]),
+ str(inst_type[prop]))
diff --git a/nova/tests/test_notifications.py b/nova/tests/test_notifications.py
index a300028a0..aec6c8f67 100644
--- a/nova/tests/test_notifications.py
+++ b/nova/tests/test_notifications.py
@@ -187,8 +187,6 @@ class NotificationsTestCase(test.TestCase):
params = {"task_state": task_states.SPAWNING}
(old_ref, new_ref) = db.instance_update_and_get_original(self.context,
self.instance['uuid'], params)
- print old_ref["task_state"]
- print new_ref["task_state"]
notifications.send_update(self.context, old_ref, new_ref)
self.assertEquals(1, len(test_notifier.NOTIFICATIONS))
diff --git a/nova/tests/test_virt_disk_vfs_localfs.py b/nova/tests/test_virt_disk_vfs_localfs.py
index 806ed01d8..af4571dd2 100644
--- a/nova/tests/test_virt_disk_vfs_localfs.py
+++ b/nova/tests/test_virt_disk_vfs_localfs.py
@@ -104,7 +104,6 @@ def fake_execute(*args, **kwargs):
else:
path = args[1]
append = False
- print str(files)
if not path in files:
files[path] = {
"content": "Hello World",
diff --git a/smoketests/base.py b/smoketests/base.py
index 7c7d19838..c90da102c 100644
--- a/smoketests/base.py
+++ b/smoketests/base.py
@@ -169,7 +169,6 @@ class SmokeTestCase(unittest.TestCase):
cmd += ' --kernel true'
status, output = commands.getstatusoutput(cmd)
if status != 0:
- print '%s -> \n %s' % (cmd, output)
raise Exception(output)
return True
@@ -178,7 +177,6 @@ class SmokeTestCase(unittest.TestCase):
cmd += '%s -m %s/%s.manifest.xml' % (bucket_name, tempdir, image)
status, output = commands.getstatusoutput(cmd)
if status != 0:
- print '%s -> \n %s' % (cmd, output)
raise Exception(output)
return True
@@ -186,7 +184,6 @@ class SmokeTestCase(unittest.TestCase):
cmd = 'euca-delete-bundle --clear -b %s' % (bucket_name)
status, output = commands.getstatusoutput(cmd)
if status != 0:
- print '%s -> \n%s' % (cmd, output)
raise Exception(output)
return True
diff --git a/smoketests/public_network_smoketests.py b/smoketests/public_network_smoketests.py
index 4fb843e0f..f20b0923e 100644
--- a/smoketests/public_network_smoketests.py
+++ b/smoketests/public_network_smoketests.py
@@ -97,7 +97,6 @@ class InstanceTestsFromPublic(base.UserSmokeTestCase):
self.data['ip_v6'], TEST_KEY)
conn.close()
except Exception as ex:
- print ex
time.sleep(1)
else:
break