summaryrefslogtreecommitdiff
path: root/nova/compute
diff options
context:
space:
mode:
authorMohammed Naser <mnaser@vexxhost.com>2018-07-27 21:09:22 -0400
committermelanie witt <melwittt@gmail.com>2019-04-30 14:22:03 +0000
commit22cd12dbb7fa5a7e0b98e4c42a73b4e7d34b0851 (patch)
treec027b135048281d8fed4e4750c8f7294e2e49f5f /nova/compute
parent32c10fadb96b92b6402752dbf1d6405008fc7f34 (diff)
downloadnova-22cd12dbb7fa5a7e0b98e4c42a73b4e7d34b0851.tar.gz
Create request spec, build request and mappings in one transaction
The transaction context is currently not shared when creating the RequestSpec, BuildRequest and InstanceMapping. Because of this, it is possible that the database ends in an inconsistent state due to the fact that one of these was created and the system crashed afterwards. This patch adds a function which handles the creation of all those resources in a single transaction. Co-Authored-By: melanie witt <melwittt@gmail.com> Closes-Bug: #1784093 Change-Id: If897a0d721180152ebdceb7a0c23e8f283ce6d10 (cherry picked from commit 85f8d033d27b31a6398529e0a25da74eae523b08) (cherry picked from commit 870e5bcfb6a5243a785b66353dda299286274e59) (cherry picked from commit dc0ded897b5e5df89166c318f8bed3dbb6553fce)
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/api.py26
1 files changed, 23 insertions, 3 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 43055f5675..bc3cc6df95 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -57,6 +57,7 @@ from nova.consoleauth import rpcapi as consoleauth_rpcapi
from nova import context as nova_context
from nova import crypto
from nova.db import base
+from nova.db.sqlalchemy import api as db_api
from nova import exception
from nova import exception_wrapper
from nova import hooks
@@ -886,6 +887,20 @@ class API(base.Base):
# by the network quotas
return base_options, max_network_count, key_pair, security_groups
+ @staticmethod
+ @db_api.api_context_manager.writer
+ def _create_reqspec_buildreq_instmapping(context, rs, br, im):
+ """Create the request spec, build request, and instance mapping in a
+ single database transaction.
+
+ The RequestContext must be passed in to this method so that the
+ database transaction context manager decorator will nest properly and
+ include each create() into the same transaction context.
+ """
+ rs.create()
+ br.create()
+ im.create()
+
def _provision_instances(self, context, instance_type, min_count,
max_count, base_options, boot_meta, security_groups,
block_device_mapping, shutdown_terminate,
@@ -915,7 +930,6 @@ class API(base.Base):
# spec as this is how the conductor knows how many were in this
# batch.
req_spec.num_instances = num_instances
- req_spec.create()
# Create an instance object, but do not store in db yet.
instance = objects.Instance(context=context)
@@ -939,7 +953,6 @@ class API(base.Base):
project_id=instance.project_id,
block_device_mappings=block_device_mapping,
tags=instance_tags)
- build_request.create()
# Create an instance_mapping. The null cell_mapping indicates
# that the instance doesn't yet exist in a cell, and lookups
@@ -951,7 +964,14 @@ class API(base.Base):
inst_mapping.instance_uuid = instance_uuid
inst_mapping.project_id = context.project_id
inst_mapping.cell_mapping = None
- inst_mapping.create()
+
+ # Create the request spec, build request, and instance mapping
+ # records in a single transaction so that if a DBError is
+ # raised from any of them, all INSERTs will be rolled back and
+ # no orphaned records will be left behind.
+ self._create_reqspec_buildreq_instmapping(context, req_spec,
+ build_request,
+ inst_mapping)
instances_to_build.append(
(req_spec, build_request, inst_mapping))