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:
John Dewey 2013-05-14 20:53:04 -07:00
parent 4a68fb3b78
commit 36e51d8963
10 changed files with 2 additions and 1846 deletions

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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