nova/nova/privsep/path.py
Matthew Booth e65a5275ee Revert "Fixes race condition with privsep utime"
This reverts commit 525631d8dc.

This change could potentially leave us with an empty file in the image
cache, which would result in failure to spawn for any subsequent
instance using the same image and image cache. This situation can only
be recovered by manually deleting the file from the image cache. Until
we can determine the root cause we should do something safer, like
ignoring the utime failure.

Change-Id: I55c072937d648d7840d01d31ed781bf93cfd94ab
2019-03-05 15:26:45 +00:00

126 lines
3.6 KiB
Python

# Copyright 2016 Red Hat, Inc
# Copyright 2017 Rackspace Australia
#
# 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.
"""Routines that bypass file-system checks."""
import errno
import os
from oslo_utils import fileutils
from nova import exception
import nova.privsep
@nova.privsep.sys_admin_pctxt.entrypoint
def readfile(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
with open(path, 'r') as f:
return f.read()
@nova.privsep.sys_admin_pctxt.entrypoint
def writefile(path, mode, content):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
with open(path, mode) as f:
f.write(content)
@nova.privsep.sys_admin_pctxt.entrypoint
def readlink(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
return os.readlink(path)
@nova.privsep.sys_admin_pctxt.entrypoint
def chown(path, uid=-1, gid=-1):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
return os.chown(path, uid, gid)
@nova.privsep.sys_admin_pctxt.entrypoint
def makedirs(path):
fileutils.ensure_tree(path)
@nova.privsep.sys_admin_pctxt.entrypoint
def chmod(path, mode):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
os.chmod(path, mode)
@nova.privsep.sys_admin_pctxt.entrypoint
def utime(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
# NOTE(mikal): the old version of this used execute(touch, ...), which
# would apparently fail on shared storage when multiple instances were
# being launched at the same time. If we see failures here, we might need
# to wrap this in a try / except.
os.utime(path, None)
@nova.privsep.sys_admin_pctxt.entrypoint
def rmdir(path):
if not os.path.exists(path):
raise exception.FileNotFound(file_path=path)
os.rmdir(path)
class path(object):
@staticmethod
@nova.privsep.sys_admin_pctxt.entrypoint
def exists(path):
return os.path.exists(path)
@nova.privsep.sys_admin_pctxt.entrypoint
def last_bytes(path, num):
# NOTE(mikal): this is implemented in this contrived manner because you
# can't mock a decorator in python (they're loaded at file parse time,
# and the mock happens later).
with open(path, 'rb') as f:
return _last_bytes_inner(f, num)
def _last_bytes_inner(file_like_object, num):
"""Return num bytes from the end of the file, and remaining byte count.
:param file_like_object: The file to read
:param num: The number of bytes to return
:returns: (data, remaining)
"""
try:
file_like_object.seek(-num, os.SEEK_END)
except IOError as e:
# seek() fails with EINVAL when trying to go before the start of
# the file. It means that num is larger than the file size, so
# just go to the start.
if e.errno == errno.EINVAL:
file_like_object.seek(0, os.SEEK_SET)
else:
raise
remaining = file_like_object.tell()
return (file_like_object.read(), remaining)