Write out ring.gz's in a safer fashion

Write the ring file to a temporary location first and then move it into
place. This should help prevent issues like reading a partial ring file
while a new instances is being written out.

Change-Id: I28357a2f038a51cb9d823822b92f736dff033a9e
This commit is contained in:
Florian Hines 2014-03-26 13:39:46 -07:00
parent 86668aa1ac
commit c6cebb6e62

View File

@ -24,6 +24,7 @@ import os
from io import BufferedReader from io import BufferedReader
from hashlib import md5 from hashlib import md5
from itertools import chain from itertools import chain
from tempfile import NamedTemporaryFile
from swift.common.utils import hash_path, validate_configuration, json from swift.common.utils import hash_path, validate_configuration, json
from swift.common.ring.utils import tiers_for_dev from swift.common.ring.utils import tiers_for_dev
@ -108,12 +109,18 @@ class RingData(object):
# #
# This only works on Python 2.7; on 2.6, we always get the # This only works on Python 2.7; on 2.6, we always get the
# current time in the gzip output. # current time in the gzip output.
tempf = NamedTemporaryFile(dir=".", prefix=filename, delete=False)
try: try:
gz_file = GzipFile(filename, 'wb', mtime=1300507380.0) gz_file = GzipFile(filename, mode='wb', fileobj=tempf,
mtime=1300507380.0)
except TypeError: except TypeError:
gz_file = GzipFile(filename, 'wb') gz_file = GzipFile(filename, mode='wb', fileobj=tempf)
self.serialize_v1(gz_file) self.serialize_v1(gz_file)
gz_file.close() gz_file.close()
tempf.flush()
os.fsync(tempf.fileno())
tempf.close()
os.rename(tempf.name, filename)
def to_dict(self): def to_dict(self):
return {'devs': self.devs, return {'devs': self.devs,