Removed local patches
These patches make assumptions that are a bit too liberal. As these cookbooks are more widely used, these should be moved into a wrapper cookbook. Change-Id: I5348876712418a520659aab606065e5a5b288d99
This commit is contained in:
parent
4a68fb3b78
commit
36e51d8963
|
@ -1,79 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2011 Openstack, LLC.
|
||||
# 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.
|
||||
|
||||
"""Cron script to generate usage notifications for volumes existing during
|
||||
the audit period.
|
||||
|
||||
Together with the notifications generated by volumes
|
||||
create/delete/resize, over that time period, this allows an external
|
||||
system consuming usage notification feeds to calculate volume usage
|
||||
for each tenant.
|
||||
|
||||
Time periods are specified as 'hour', 'month', 'day' or 'year'
|
||||
|
||||
hour = previous hour. If run at 9:07am, will generate usage for 8-9am.
|
||||
month = previous month. If the script is run April 1, it will generate
|
||||
usages for March 1 through March 31.
|
||||
day = previous day. if run on July 4th, it generates usages for July 3rd.
|
||||
year = previous year. If run on Jan 1, it generates usages for
|
||||
Jan 1 through Dec 31 of the previous year.
|
||||
"""
|
||||
|
||||
import gettext
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
# If ../cinder/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]),
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'cinder', '__init__.py')):
|
||||
sys.path.insert(0, POSSIBLE_TOPDIR)
|
||||
|
||||
gettext.install('cinder', unicode=1)
|
||||
from cinder import context
|
||||
from cinder import db
|
||||
from cinder import flags
|
||||
from cinder.openstack.common import log as logging
|
||||
from cinder.openstack.common import rpc
|
||||
from cinder import utils
|
||||
import cinder.volume.utils
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
if __name__ == '__main__':
|
||||
admin_context = context.get_admin_context()
|
||||
flags.parse_args(sys.argv)
|
||||
logging.setup("cinder")
|
||||
begin, end = utils.last_completed_audit_period('day')
|
||||
print "Starting volume usage audit"
|
||||
print "Creating usages for %s until %s" % (str(begin), str(end))
|
||||
volumes = db.volume_get_active_by_window(admin_context,
|
||||
begin,
|
||||
end)
|
||||
print "Found %d volumes" % len(volumes)
|
||||
for volume_ref in volumes:
|
||||
try:
|
||||
cinder.volume.utils.notify_usage_exists(
|
||||
admin_context, volume_ref)
|
||||
except Exception, e:
|
||||
print traceback.format_exc(e)
|
||||
print "Volume usage audit completed"
|
|
@ -1,35 +0,0 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# 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.
|
||||
|
||||
|
||||
import errno
|
||||
import os
|
||||
|
||||
|
||||
def ensure_tree(path):
|
||||
"""Create a directory (and any ancestor directories required)
|
||||
|
||||
:param path: Directory to create
|
||||
"""
|
||||
try:
|
||||
os.makedirs(path)
|
||||
except OSError as exc:
|
||||
if exc.errno == errno.EEXIST:
|
||||
if not os.path.isdir(path):
|
||||
raise
|
||||
else:
|
||||
raise
|
|
@ -1,33 +0,0 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2012 Red Hat, Inc.
|
||||
# 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.
|
||||
|
||||
"""
|
||||
gettext for openstack-common modules.
|
||||
|
||||
Usual usage in an openstack.common module:
|
||||
|
||||
from cinder.openstack.common.gettextutils import _
|
||||
"""
|
||||
|
||||
import gettext
|
||||
|
||||
|
||||
t = gettext.translation('openstack-common', 'locale', fallback=True)
|
||||
|
||||
|
||||
def _(msg):
|
||||
return t.ugettext(msg)
|
|
@ -1,233 +0,0 @@
|
|||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
# 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.
|
||||
|
||||
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import weakref
|
||||
|
||||
from eventlet import semaphore
|
||||
|
||||
from cinder.openstack.common import cfg
|
||||
from cinder.openstack.common import fileutils
|
||||
from cinder.openstack.common.gettextutils import _
|
||||
from cinder.openstack.common import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
util_opts = [
|
||||
cfg.BoolOpt('disable_process_locking', default=False,
|
||||
help='Whether to disable inter-process locks'),
|
||||
cfg.StrOpt('lock_path',
|
||||
default=os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'../')),
|
||||
help='Directory to use for lock files')
|
||||
]
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
CONF.register_opts(util_opts)
|
||||
|
||||
|
||||
class _InterProcessLock(object):
|
||||
"""Lock implementation which allows multiple locks, working around
|
||||
issues like bugs.debian.org/cgi-bin/bugreport.cgi?bug=632857 and does
|
||||
not require any cleanup. Since the lock is always held on a file
|
||||
descriptor rather than outside of the process, the lock gets dropped
|
||||
automatically if the process crashes, even if __exit__ is not executed.
|
||||
|
||||
There are no guarantees regarding usage by multiple green threads in a
|
||||
single process here. This lock works only between processes. Exclusive
|
||||
access between local threads should be achieved using the semaphores
|
||||
in the @synchronized decorator.
|
||||
|
||||
Note these locks are released when the descriptor is closed, so it's not
|
||||
safe to close the file descriptor while another green thread holds the
|
||||
lock. Just opening and closing the lock file can break synchronisation,
|
||||
so lock files must be accessed only using this abstraction.
|
||||
"""
|
||||
|
||||
def __init__(self, name):
|
||||
self.lockfile = None
|
||||
self.fname = name
|
||||
|
||||
def __enter__(self):
|
||||
self.lockfile = open(self.fname, 'w')
|
||||
|
||||
while True:
|
||||
try:
|
||||
# Using non-blocking locks since green threads are not
|
||||
# patched to deal with blocking locking calls.
|
||||
# Also upon reading the MSDN docs for locking(), it seems
|
||||
# to have a laughable 10 attempts "blocking" mechanism.
|
||||
self.trylock()
|
||||
return self
|
||||
except IOError, e:
|
||||
if e.errno in (errno.EACCES, errno.EAGAIN):
|
||||
# external locks synchronise things like iptables
|
||||
# updates - give it some time to prevent busy spinning
|
||||
time.sleep(0.01)
|
||||
else:
|
||||
raise
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
try:
|
||||
self.unlock()
|
||||
self.lockfile.close()
|
||||
except IOError:
|
||||
LOG.exception(_("Could not release the acquired lock `%s`"),
|
||||
self.fname)
|
||||
|
||||
def trylock(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
def unlock(self):
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class _WindowsLock(_InterProcessLock):
|
||||
def trylock(self):
|
||||
msvcrt.locking(self.lockfile, msvcrt.LK_NBLCK, 1)
|
||||
|
||||
def unlock(self):
|
||||
msvcrt.locking(self.lockfile, msvcrt.LK_UNLCK, 1)
|
||||
|
||||
|
||||
class _PosixLock(_InterProcessLock):
|
||||
def trylock(self):
|
||||
fcntl.lockf(self.lockfile, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||
|
||||
def unlock(self):
|
||||
fcntl.lockf(self.lockfile, fcntl.LOCK_UN)
|
||||
|
||||
|
||||
if os.name == 'nt':
|
||||
import msvcrt
|
||||
InterProcessLock = _WindowsLock
|
||||
else:
|
||||
import fcntl
|
||||
InterProcessLock = _PosixLock
|
||||
|
||||
_semaphores = weakref.WeakValueDictionary()
|
||||
|
||||
|
||||
def synchronized(name, lock_file_prefix, external=False, lock_path=None):
|
||||
"""Synchronization decorator.
|
||||
|
||||
Decorating a method like so::
|
||||
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
ensures that only one thread will execute the bar method at a time.
|
||||
|
||||
Different methods can share the same lock::
|
||||
|
||||
@synchronized('mylock')
|
||||
def foo(self, *args):
|
||||
...
|
||||
|
||||
@synchronized('mylock')
|
||||
def bar(self, *args):
|
||||
...
|
||||
|
||||
This way only one of either foo or bar can be executing at a time.
|
||||
|
||||
The lock_file_prefix argument is used to provide lock files on disk with a
|
||||
meaningful prefix. The prefix should end with a hyphen ('-') if specified.
|
||||
|
||||
The external keyword argument denotes whether this lock should work across
|
||||
multiple processes. This means that if two different workers both run a
|
||||
a method decorated with @synchronized('mylock', external=True), only one
|
||||
of them will execute at a time.
|
||||
|
||||
The lock_path keyword argument is used to specify a special location for
|
||||
external lock files to live. If nothing is set, then CONF.lock_path is
|
||||
used as a default.
|
||||
"""
|
||||
|
||||
def wrap(f):
|
||||
@functools.wraps(f)
|
||||
def inner(*args, **kwargs):
|
||||
# NOTE(soren): If we ever go natively threaded, this will be racy.
|
||||
# See http://stackoverflow.com/questions/5390569/dyn
|
||||
# amically-allocating-and-destroying-mutexes
|
||||
sem = _semaphores.get(name, semaphore.Semaphore())
|
||||
if name not in _semaphores:
|
||||
# this check is not racy - we're already holding ref locally
|
||||
# so GC won't remove the item and there was no IO switch
|
||||
# (only valid in greenthreads)
|
||||
_semaphores[name] = sem
|
||||
|
||||
with sem:
|
||||
LOG.debug(_('Got semaphore "%(lock)s" for method '
|
||||
'"%(method)s"...'), {'lock': name,
|
||||
'method': f.__name__})
|
||||
if external and not CONF.disable_process_locking:
|
||||
LOG.debug(_('Attempting to grab file lock "%(lock)s" for '
|
||||
'method "%(method)s"...'),
|
||||
{'lock': name, 'method': f.__name__})
|
||||
cleanup_dir = False
|
||||
|
||||
# We need a copy of lock_path because it is non-local
|
||||
local_lock_path = lock_path
|
||||
if not local_lock_path:
|
||||
local_lock_path = CONF.lock_path
|
||||
|
||||
if not local_lock_path:
|
||||
cleanup_dir = True
|
||||
local_lock_path = tempfile.mkdtemp()
|
||||
|
||||
if not os.path.exists(local_lock_path):
|
||||
cleanup_dir = True
|
||||
fileutils.ensure_tree(local_lock_path)
|
||||
|
||||
# NOTE(mikal): the lock name cannot contain directory
|
||||
# separators
|
||||
safe_name = name.replace(os.sep, '_')
|
||||
lock_file_name = '%s%s' % (lock_file_prefix, safe_name)
|
||||
lock_file_path = os.path.join(local_lock_path,
|
||||
lock_file_name)
|
||||
|
||||
try:
|
||||
lock = InterProcessLock(lock_file_path)
|
||||
with lock:
|
||||
LOG.debug(_('Got file lock "%(lock)s" at %(path)s '
|
||||
'for method "%(method)s"...'),
|
||||
{'lock': name,
|
||||
'path': lock_file_path,
|
||||
'method': f.__name__})
|
||||
retval = f(*args, **kwargs)
|
||||
finally:
|
||||
# NOTE(vish): This removes the tempdir if we needed
|
||||
# to create one. This is used to cleanup
|
||||
# the locks left behind by unit tests.
|
||||
if cleanup_dir:
|
||||
shutil.rmtree(local_lock_path)
|
||||
else:
|
||||
retval = f(*args, **kwargs)
|
||||
|
||||
return retval
|
||||
return inner
|
||||
return wrap
|
File diff suppressed because it is too large
Load Diff
|
@ -54,30 +54,6 @@ service "cinder-scheduler" do
|
|||
action [ :enable, :start ]
|
||||
end
|
||||
|
||||
cookbook_file "/usr/local/bin/cinder-volume-usage-audit" do
|
||||
source "cinder-volume-usage-audit"
|
||||
mode 00755
|
||||
owner "root"
|
||||
group "root"
|
||||
end
|
||||
|
||||
# run cronjob only on one node
|
||||
cron_cmd = "/usr/local/bin/cinder-volume-usage-audit > /var/log/cinder/audit.log 2>&1"
|
||||
node_search = search(:node, "roles:openstack-volume-scheduler AND chef_environment:#{node.chef_environment}")
|
||||
cron_node = node_search.collect{|a| a.name}.sort[0]
|
||||
if node.name == cron_node
|
||||
cron "cinder-volume-usage-audit" do
|
||||
action :create
|
||||
minute node["cinder"]["cron"]["minute"]
|
||||
command cron_cmd
|
||||
end
|
||||
else
|
||||
cron "cinder-volume-usage-audit" do
|
||||
action :delete
|
||||
command cron_cmd
|
||||
end
|
||||
end
|
||||
|
||||
template "/etc/cinder/cinder.conf" do
|
||||
source "cinder.conf.erb"
|
||||
group node["cinder"]["group"]
|
||||
|
|
|
@ -100,40 +100,3 @@ template "/etc/tgt/targets.conf" do
|
|||
|
||||
notifies :restart, "service[iscsitarget]", :immediately
|
||||
end
|
||||
|
||||
cookbook_file "/usr/share/pyshared/cinder/openstack/common/fileutils.py" do
|
||||
source "fileutils_new-b322585613c21067571442aaf9e4e6feb167832b.py"
|
||||
mode 00644
|
||||
owner "root"
|
||||
group "root"
|
||||
end
|
||||
|
||||
link "/usr/lib/python2.7/dist-packages/cinder/openstack/common/fileutils.py" do
|
||||
to "/usr/share/pyshared/cinder/openstack/common/fileutils.py"
|
||||
end
|
||||
|
||||
cookbook_file "/usr/share/pyshared/cinder/openstack/common/gettextutils.py" do
|
||||
source "gettextutils_new-8e450aaa6ba1a2a88f6326c2e8d285d00fd28691.py"
|
||||
mode 00644
|
||||
owner "root"
|
||||
group "root"
|
||||
end
|
||||
|
||||
cookbook_file "/usr/share/pyshared/cinder/openstack/common/lockutils.py" do
|
||||
source "lockutils_new-6dda4af1dd50582a0271fd6c96044ae61af9df7e.py"
|
||||
mode 00644
|
||||
owner "root"
|
||||
group "root"
|
||||
end
|
||||
|
||||
link "/usr/lib/python2.7/dist-packages/cinder/openstack/common/lockutils.py" do
|
||||
to "/usr/share/pyshared/cinder/openstack/common/lockutils.py"
|
||||
end
|
||||
|
||||
cookbook_file node["cinder"]["netapp"]["driver"] do
|
||||
source "netapp_new-42cdc4d947a73ae6a3dbbaab36634e425b57c18c.py"
|
||||
mode 00644
|
||||
owner "root"
|
||||
group "root"
|
||||
notifies :restart, "service[cinder-volume]"
|
||||
end
|
||||
|
|
|
@ -32,29 +32,6 @@ describe "cinder::scheduler" do
|
|||
expect(@chef_run).to set_service_to_start_on_boot "cinder-scheduler"
|
||||
end
|
||||
|
||||
describe "cinder-volume-usage-audit" do
|
||||
before do
|
||||
f = "/usr/local/bin/cinder-volume-usage-audit"
|
||||
@file = @chef_run.cookbook_file f
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "root", "root"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "755"
|
||||
end
|
||||
end
|
||||
|
||||
it "has cinder-volume-usage-audit cronjob" do
|
||||
cron = @chef_run.cron "cinder-volume-usage-audit"
|
||||
cmd = "/usr/local/bin/cinder-volume-usage-audit > " \
|
||||
"/var/log/cinder/audit.log 2>&1"
|
||||
expect(cron.command).to eq cmd
|
||||
expect(cron.minute).to eq '00'
|
||||
end
|
||||
|
||||
expect_creates_cinder_conf "service[cinder-scheduler]"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,6 @@ def cinder_stubs
|
|||
::Chef::Recipe.any_instance.stub(:db_password).and_return String.new
|
||||
::Chef::Recipe.any_instance.stub(:user_password).and_return String.new
|
||||
::Chef::Recipe.any_instance.stub(:service_password).and_return String.new
|
||||
::Chef::Recipe.any_instance.stub(:search).and_return([OpenStruct.new(:name => 'fauxhai.local')])
|
||||
end
|
||||
|
||||
def expect_runs_openstack_common_logging_recipe
|
||||
|
|
|
@ -45,11 +45,11 @@ describe "cinder::volume" do
|
|||
describe "targets.conf" do
|
||||
before do
|
||||
@file = @chef_run.template "/etc/tgt/targets.conf"
|
||||
end
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "600"
|
||||
end
|
||||
end
|
||||
|
||||
it "notifies iscsi restart" do
|
||||
expect(@file).to notify "service[iscsitarget]", :restart
|
||||
|
@ -61,91 +61,6 @@ describe "cinder::volume" do
|
|||
expect(@chef_run).not_to create_file_with_content @file.name,
|
||||
"include /var/lib/cinder/volumes/*"
|
||||
end
|
||||
end
|
||||
|
||||
describe "patches" do
|
||||
before do
|
||||
@os_dir = "/usr/share/pyshared/cinder/openstack/common"
|
||||
@dist_dir = "/usr/lib/python2.7/dist-packages/cinder/openstack/common"
|
||||
end
|
||||
|
||||
describe "fileutils.py" do
|
||||
before do
|
||||
@source = ::File.join @os_dir, "fileutils.py"
|
||||
@file = @chef_run.cookbook_file @source
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "root", "root"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "644"
|
||||
end
|
||||
|
||||
it "symlinks fileutils.py" do
|
||||
ln = ::File.join @dist_dir, "fileutils.py"
|
||||
expect(@chef_run.link(ln)).to link_to @source
|
||||
end
|
||||
end
|
||||
|
||||
describe "gettextutils.py" do
|
||||
before do
|
||||
@source = ::File.join @os_dir, "gettextutils.py"
|
||||
@file = @chef_run.cookbook_file @source
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "root", "root"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "644"
|
||||
end
|
||||
|
||||
it "symlinks gettextutils.py" do
|
||||
pending "TODO: should there be a gettextutils symlink?"
|
||||
end
|
||||
end
|
||||
|
||||
describe "lockutils.py" do
|
||||
before do
|
||||
@source = ::File.join @os_dir, "lockutils.py"
|
||||
@file = @chef_run.cookbook_file @source
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "root", "root"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "644"
|
||||
end
|
||||
|
||||
it "symlinks gettextutils.py" do
|
||||
ln = ::File.join @dist_dir, "lockutils.py"
|
||||
expect(@chef_run.link(ln)).to link_to @source
|
||||
end
|
||||
end
|
||||
|
||||
describe "netapp.py" do
|
||||
before do
|
||||
f = "/usr/share/pyshared/cinder/volume/netapp.py"
|
||||
@file = @chef_run.cookbook_file f
|
||||
end
|
||||
|
||||
it "has proper owner" do
|
||||
expect(@file).to be_owned_by "root", "root"
|
||||
end
|
||||
|
||||
it "has proper modes" do
|
||||
expect(sprintf("%o", @file.mode)).to eq "644"
|
||||
end
|
||||
|
||||
it "notifies nova-api-ec2 restart" do
|
||||
expect(@file).to notify "service[cinder-volume]", :restart
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue