Remove deprecated Folsom code: config convert
Removes config file converter: nova-manage config convert Change-Id: I146bff9ac00a4885e7054f999ae52159da3f86ef
This commit is contained in:
@@ -74,7 +74,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'nova', '__init__.py')):
|
|||||||
gettext.install('nova', unicode=1)
|
gettext.install('nova', unicode=1)
|
||||||
|
|
||||||
from nova.api.ec2 import ec2utils
|
from nova.api.ec2 import ec2utils
|
||||||
from nova.compat import flagfile
|
|
||||||
from nova.compute import instance_types
|
from nova.compute import instance_types
|
||||||
from nova.compute import rpcapi as compute_rpcapi
|
from nova.compute import rpcapi as compute_rpcapi
|
||||||
from nova import context
|
from nova import context
|
||||||
@@ -778,40 +777,6 @@ class VersionCommands(object):
|
|||||||
class VolumeCommands(object):
|
class VolumeCommands(object):
|
||||||
"""Methods for dealing with a cloud in an odd state"""
|
"""Methods for dealing with a cloud in an odd state"""
|
||||||
|
|
||||||
@args('--volume', dest='volume_id', metavar='<volume id>',
|
|
||||||
help='Volume ID')
|
|
||||||
def delete(self, volume_id):
|
|
||||||
"""WARNING: This method is deprecated and will be removed.
|
|
||||||
Delete a volume, bypassing the check that it
|
|
||||||
must be available."""
|
|
||||||
|
|
||||||
print(_("\"nova-manage volume delete\" is deprecated; use"
|
|
||||||
" the os-reset_status os-admin-actions extension instead."))
|
|
||||||
if 'cinder' in FLAGS.volume_api_class:
|
|
||||||
print(_("\"nova-manage volume delete\" only valid "
|
|
||||||
"when using nova-volume service"))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
ctxt = context.get_admin_context()
|
|
||||||
volume = db.volume_get(ctxt, param2id(volume_id))
|
|
||||||
host = volume['host']
|
|
||||||
|
|
||||||
if not host:
|
|
||||||
print "Volume not yet assigned to host."
|
|
||||||
print "Deleting volume from database and skipping rpc."
|
|
||||||
db.volume_destroy(ctxt, volume_id)
|
|
||||||
return
|
|
||||||
|
|
||||||
if volume['status'] == 'in-use':
|
|
||||||
print "Volume is in-use."
|
|
||||||
print "Detach volume from instance and then try again."
|
|
||||||
return
|
|
||||||
|
|
||||||
rpc.cast(ctxt,
|
|
||||||
rpc.queue_get_for(ctxt, FLAGS.volume_topic, host),
|
|
||||||
{"method": "delete_volume",
|
|
||||||
"args": {"volume_id": volume['id']}})
|
|
||||||
|
|
||||||
@args('--volume', dest='volume_id', metavar='<volume id>',
|
@args('--volume', dest='volume_id', metavar='<volume id>',
|
||||||
help='Volume ID')
|
help='Volume ID')
|
||||||
def reattach(self, volume_id):
|
def reattach(self, volume_id):
|
||||||
@@ -1168,34 +1133,6 @@ class AgentBuildCommands(object):
|
|||||||
'md5hash': md5hash})
|
'md5hash': md5hash})
|
||||||
|
|
||||||
|
|
||||||
class ConfigCommands(object):
|
|
||||||
"""Class for exposing the flags defined by flag_file(s)."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def list(self):
|
|
||||||
for key, value in FLAGS.iteritems():
|
|
||||||
if value is not None:
|
|
||||||
print '%s = %s' % (key, value)
|
|
||||||
|
|
||||||
@args('--infile', dest='infile', metavar='<path>',
|
|
||||||
help='old-style flagfile to convert to config')
|
|
||||||
@args('--outfile', dest='outfile', metavar='<path>',
|
|
||||||
help='path for output file. Writes config'
|
|
||||||
'to stdout if not specified.')
|
|
||||||
def convert(self, infile, outfile=None):
|
|
||||||
"""Converts a flagfile and prints results to stdout."""
|
|
||||||
arg = '--flagfile=%s' % infile
|
|
||||||
with flagfile.handle_flagfiles_managed([arg]) as newargs:
|
|
||||||
with open(newargs[0].split('=')[1]) as configfile:
|
|
||||||
config = configfile.read()
|
|
||||||
if outfile:
|
|
||||||
with open(outfile, 'w') as configfile:
|
|
||||||
configfile.write(config)
|
|
||||||
else:
|
|
||||||
print config,
|
|
||||||
|
|
||||||
|
|
||||||
class GetLogCommands(object):
|
class GetLogCommands(object):
|
||||||
"""Get logging information"""
|
"""Get logging information"""
|
||||||
@@ -1249,7 +1186,6 @@ class GetLogCommands(object):
|
|||||||
CATEGORIES = [
|
CATEGORIES = [
|
||||||
('account', AccountCommands),
|
('account', AccountCommands),
|
||||||
('agent', AgentBuildCommands),
|
('agent', AgentBuildCommands),
|
||||||
('config', ConfigCommands),
|
|
||||||
('db', DbCommands),
|
('db', DbCommands),
|
||||||
('fixed', FixedIpCommands),
|
('fixed', FixedIpCommands),
|
||||||
('flavor', InstanceTypeCommands),
|
('flavor', InstanceTypeCommands),
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2012 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
@@ -1,188 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2012 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# 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 contextlib
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
'''
|
|
||||||
Compatibility code for handling the deprecated --flagfile option.
|
|
||||||
|
|
||||||
gflags style configuration files are deprecated and will be removed in future.
|
|
||||||
|
|
||||||
The code in this module transles --flagfile options into --config-file and can
|
|
||||||
be removed when support for --flagfile is removed.
|
|
||||||
'''
|
|
||||||
|
|
||||||
|
|
||||||
def _get_flagfile(argp):
|
|
||||||
'''Parse the filename from a --flagfile argument.
|
|
||||||
|
|
||||||
The current and next arguments are passed as a 2 item list. If the
|
|
||||||
flagfile filename is in the next argument, the two arguments are
|
|
||||||
joined into the first item while the second item is set to None.
|
|
||||||
'''
|
|
||||||
i = argp[0].find('-flagfile')
|
|
||||||
if i < 0:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Accept -flagfile or -flagfile
|
|
||||||
if i != 0 and (i != 1 or argp[0][i] != '-'):
|
|
||||||
return None
|
|
||||||
|
|
||||||
i += len('-flagfile')
|
|
||||||
if i == len(argp[0]): # Accept [-]-flagfile foo
|
|
||||||
argp[0] += '=' + argp[1]
|
|
||||||
argp[1] = None
|
|
||||||
|
|
||||||
if argp[0][i] != '=': # Accept [-]-flagfile=foo
|
|
||||||
return None
|
|
||||||
|
|
||||||
return argp[0][i + 1:]
|
|
||||||
|
|
||||||
|
|
||||||
def _open_file_for_reading(path):
|
|
||||||
'''Helper method which test code may stub out.'''
|
|
||||||
return open(path, 'r')
|
|
||||||
|
|
||||||
|
|
||||||
def _open_fd_for_writing(fd, _path):
|
|
||||||
'''Helper method which test code may stub out.'''
|
|
||||||
return os.fdopen(fd, 'w')
|
|
||||||
|
|
||||||
|
|
||||||
def _read_lines(flagfile):
|
|
||||||
'''Read a flag file, returning all lines with comments stripped.'''
|
|
||||||
with _open_file_for_reading(flagfile) as f:
|
|
||||||
lines = f.readlines()
|
|
||||||
ret = []
|
|
||||||
for l in lines:
|
|
||||||
if l.isspace() or l.startswith('#') or l.startswith('//'):
|
|
||||||
continue
|
|
||||||
ret.append(l.strip())
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
def _read_flagfile(arg, next_arg, tempdir=None):
|
|
||||||
'''Convert a --flagfile argument to --config-file.
|
|
||||||
|
|
||||||
If the supplied argument is a --flagfile argument, read the contents
|
|
||||||
of the file and convert it to a .ini format config file. Return a
|
|
||||||
--config-file argument with the converted file.
|
|
||||||
|
|
||||||
If the flag file contains more --flagfile arguments, multiple
|
|
||||||
--config-file arguments will be returned.
|
|
||||||
|
|
||||||
The returned argument list may also contain None values which should
|
|
||||||
be filtered out later.
|
|
||||||
'''
|
|
||||||
argp = [arg, next_arg]
|
|
||||||
flagfile = _get_flagfile(argp)
|
|
||||||
if not flagfile:
|
|
||||||
return argp
|
|
||||||
|
|
||||||
args = _read_lines(flagfile)
|
|
||||||
|
|
||||||
if args and not args[0].startswith('--'):
|
|
||||||
# This is a config file, not a flagfile, so return it.
|
|
||||||
return ['--config-file=' + flagfile] + argp[1:]
|
|
||||||
|
|
||||||
#
|
|
||||||
# We're recursing here to convert any --flagfile arguments
|
|
||||||
# read from this flagfile into --config-file arguments
|
|
||||||
#
|
|
||||||
# We don't actually include those --config-file arguments
|
|
||||||
# in the generated config file; instead we include all those
|
|
||||||
# --config-file args in the final command line
|
|
||||||
#
|
|
||||||
args = _iterate_args(args, _read_flagfile, tempdir=tempdir)
|
|
||||||
|
|
||||||
config_file_args = []
|
|
||||||
|
|
||||||
(fd, tmpconf) = tempfile.mkstemp(suffix='.conf', dir=tempdir)
|
|
||||||
|
|
||||||
with _open_fd_for_writing(fd, tmpconf) as f:
|
|
||||||
f.write('[DEFAULT]\n')
|
|
||||||
for arg in args:
|
|
||||||
if arg.startswith('--config-file='):
|
|
||||||
config_file_args.append(arg)
|
|
||||||
continue
|
|
||||||
if '=' in arg:
|
|
||||||
f.write(arg[2:] + '\n')
|
|
||||||
elif arg[2:].startswith('no'):
|
|
||||||
f.write(arg[4:] + '=false\n')
|
|
||||||
else:
|
|
||||||
f.write(arg[2:] + '=true\n')
|
|
||||||
|
|
||||||
return ['--config-file=' + tmpconf] + argp[1:] + config_file_args
|
|
||||||
|
|
||||||
|
|
||||||
def _iterate_args(args, iterator, **kwargs):
|
|
||||||
'''Run an iterator function on the supplied args list.
|
|
||||||
|
|
||||||
The iterator is passed the current arg and next arg and returns a
|
|
||||||
list of args. The returned args replace the suppied args in the
|
|
||||||
resulting args list.
|
|
||||||
|
|
||||||
The iterator will be passed None for the next arg when processing
|
|
||||||
the last arg.
|
|
||||||
'''
|
|
||||||
args.append(None)
|
|
||||||
|
|
||||||
ret = []
|
|
||||||
for i in range(len(args)):
|
|
||||||
if args[i] is None: # last item, or consumed file name
|
|
||||||
continue
|
|
||||||
|
|
||||||
modified = iterator(args[i], args[i + 1], **kwargs)
|
|
||||||
args[i], args[i + 1] = modified[:2]
|
|
||||||
|
|
||||||
ret.extend(modified[:1] + modified[2:]) # don't append next arg
|
|
||||||
|
|
||||||
return filter(None, ret)
|
|
||||||
|
|
||||||
|
|
||||||
def handle_flagfiles(args, tempdir=None):
|
|
||||||
'''Replace --flagfile arguments with --config-file arguments.
|
|
||||||
|
|
||||||
Replace any --flagfile argument in the supplied list with a --config-file
|
|
||||||
argument containing a temporary config file with the contents of the flag
|
|
||||||
file translated to .ini format.
|
|
||||||
|
|
||||||
The tempdir argument is a directory which will be used to create temporary
|
|
||||||
files.
|
|
||||||
'''
|
|
||||||
return _iterate_args(args[:], _read_flagfile, tempdir=tempdir)
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def handle_flagfiles_managed(args):
|
|
||||||
'''A context manager for handle_flagfiles() which removes temp files.
|
|
||||||
|
|
||||||
For use with the 'with' statement, i.e.::
|
|
||||||
|
|
||||||
with handle_flagfiles_managed(args) as args:
|
|
||||||
# Do stuff
|
|
||||||
# Any temporary fils have been removed
|
|
||||||
'''
|
|
||||||
# NOTE(johannes): Would be nice to use utils.tempdir(), but it
|
|
||||||
# causes an import loop
|
|
||||||
tempdir = tempfile.mkdtemp(prefix='nova-conf-')
|
|
||||||
try:
|
|
||||||
yield handle_flagfiles(args, tempdir=tempdir)
|
|
||||||
finally:
|
|
||||||
shutil.rmtree(tempdir)
|
|
||||||
@@ -1,175 +0,0 @@
|
|||||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
|
||||||
|
|
||||||
# Copyright (c) 2012 Red Hat, Inc.
|
|
||||||
#
|
|
||||||
# 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 contextlib
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import StringIO
|
|
||||||
import tempfile
|
|
||||||
import textwrap
|
|
||||||
import unittest
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
from nova.compat import flagfile
|
|
||||||
from nova import test
|
|
||||||
|
|
||||||
|
|
||||||
class ThatLastTwoPercentCoverageTestCase(unittest.TestCase):
|
|
||||||
def test_open_file_for_reading(self):
|
|
||||||
with flagfile._open_file_for_reading(__file__):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def test_open_fd_for_writing(self):
|
|
||||||
(fd, path) = tempfile.mkstemp()
|
|
||||||
try:
|
|
||||||
with flagfile._open_fd_for_writing(fd, None):
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
os.remove(path)
|
|
||||||
|
|
||||||
|
|
||||||
class CompatFlagfileTestCase(test.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
super(CompatFlagfileTestCase, self).setUp()
|
|
||||||
self.files = {}
|
|
||||||
self.tempdir = str(uuid.uuid4())
|
|
||||||
self.tempfiles = []
|
|
||||||
|
|
||||||
self.stubs.Set(flagfile, '_open_file_for_reading', self._fake_open)
|
|
||||||
self.stubs.Set(flagfile, '_open_fd_for_writing', self._fake_open)
|
|
||||||
self.stubs.Set(tempfile, 'mkdtemp', self._fake_mkdtemp)
|
|
||||||
self.stubs.Set(tempfile, 'mkstemp', self._fake_mkstemp)
|
|
||||||
self.stubs.Set(shutil, 'rmtree', self._fake_rmtree)
|
|
||||||
|
|
||||||
def _fake_open(self, *args):
|
|
||||||
@contextlib.contextmanager
|
|
||||||
def managed_stringio(path):
|
|
||||||
if not path in self.files:
|
|
||||||
self.files[path] = ""
|
|
||||||
sio = StringIO.StringIO(textwrap.dedent(self.files[path]))
|
|
||||||
try:
|
|
||||||
yield sio
|
|
||||||
finally:
|
|
||||||
self.files[path] = sio.getvalue()
|
|
||||||
sio.close()
|
|
||||||
if len(args) == 2:
|
|
||||||
args = args[1:] # remove the fd arg for fdopen() case
|
|
||||||
return managed_stringio(args[0])
|
|
||||||
|
|
||||||
def _fake_mkstemp(self, *args, **kwargs):
|
|
||||||
self.assertTrue('dir' in kwargs)
|
|
||||||
self.assertEquals(kwargs['dir'], self.tempdir)
|
|
||||||
self.tempfiles.append(str(uuid.uuid4()))
|
|
||||||
return (None, self.tempfiles[-1])
|
|
||||||
|
|
||||||
def _fake_mkdtemp(self, *args, **kwargs):
|
|
||||||
return self.tempdir
|
|
||||||
|
|
||||||
def _fake_rmtree(self, path):
|
|
||||||
self.assertEquals(self.tempdir, path)
|
|
||||||
self.tempdir = None
|
|
||||||
|
|
||||||
def test_no_args(self):
|
|
||||||
before = []
|
|
||||||
after = flagfile.handle_flagfiles(before, tempdir=self.tempdir)
|
|
||||||
self.assertEquals(after, before)
|
|
||||||
|
|
||||||
def _do_test_empty_flagfile(self, before):
|
|
||||||
self.files['foo.flags'] = ''
|
|
||||||
after = flagfile.handle_flagfiles(before, tempdir=self.tempdir)
|
|
||||||
self.assertEquals(after, ['--config-file=' + self.tempfiles[-1]])
|
|
||||||
self.assertEquals(self.files[self.tempfiles[-1]], '[DEFAULT]\n')
|
|
||||||
|
|
||||||
def test_empty_flagfile(self):
|
|
||||||
self._do_test_empty_flagfile(['--flagfile=foo.flags'])
|
|
||||||
|
|
||||||
def test_empty_flagfile_separated(self):
|
|
||||||
self._do_test_empty_flagfile(['--flagfile', 'foo.flags'])
|
|
||||||
|
|
||||||
def test_empty_flagfile_single_hyphen(self):
|
|
||||||
self._do_test_empty_flagfile(['-flagfile=foo.flags'])
|
|
||||||
|
|
||||||
def test_empty_flagfile_single_hyphen_separated_separated(self):
|
|
||||||
self._do_test_empty_flagfile(['-flagfile', 'foo.flags'])
|
|
||||||
|
|
||||||
def test_empty_flagfile_with_other_args(self):
|
|
||||||
self.files['foo.flags'] = ''
|
|
||||||
|
|
||||||
before = [
|
|
||||||
'--foo', 'bar',
|
|
||||||
'--flagfile=foo.flags',
|
|
||||||
'--blaa=foo',
|
|
||||||
'--foo-flagfile',
|
|
||||||
'--flagfile-foo'
|
|
||||||
]
|
|
||||||
|
|
||||||
after = flagfile.handle_flagfiles(before, tempdir=self.tempdir)
|
|
||||||
|
|
||||||
self.assertEquals(after, [
|
|
||||||
'--foo', 'bar',
|
|
||||||
'--config-file=' + self.tempfiles[-1],
|
|
||||||
'--blaa=foo',
|
|
||||||
'--foo-flagfile',
|
|
||||||
'--flagfile-foo'])
|
|
||||||
self.assertEquals(self.files[self.tempfiles[-1]], '[DEFAULT]\n')
|
|
||||||
|
|
||||||
def _do_test_flagfile(self, flags, conf):
|
|
||||||
self.files['foo.flags'] = flags
|
|
||||||
|
|
||||||
before = ['--flagfile=foo.flags']
|
|
||||||
|
|
||||||
after = flagfile.handle_flagfiles(before, tempdir=self.tempdir)
|
|
||||||
|
|
||||||
self.assertEquals(after,
|
|
||||||
['--config-file=' + t
|
|
||||||
for t in reversed(self.tempfiles)])
|
|
||||||
self.assertEquals(self.files[self.tempfiles[-1]],
|
|
||||||
'[DEFAULT]\n' + conf)
|
|
||||||
|
|
||||||
def test_flagfile(self):
|
|
||||||
self._do_test_flagfile('--bar=foo', 'bar=foo\n')
|
|
||||||
|
|
||||||
def test_boolean_flag(self):
|
|
||||||
self._do_test_flagfile('--verbose', 'verbose=true\n')
|
|
||||||
|
|
||||||
def test_boolean_inverted_flag(self):
|
|
||||||
self._do_test_flagfile('--noverbose', 'verbose=false\n')
|
|
||||||
|
|
||||||
def test_flagfile_comments(self):
|
|
||||||
self._do_test_flagfile(' \n\n#foo\n--bar=foo\n--foo=bar\n//bar',
|
|
||||||
'bar=foo\nfoo=bar\n')
|
|
||||||
|
|
||||||
def test_flagfile_is_config(self):
|
|
||||||
self.files['foo.flags'] = '\n\n#foo\n//bar\n[DEFAULT]\nbar=foo'
|
|
||||||
before = ['--flagfile=foo.flags']
|
|
||||||
after = flagfile.handle_flagfiles(before, tempdir=self.tempdir)
|
|
||||||
self.assertEquals(after, ['--config-file=foo.flags'])
|
|
||||||
|
|
||||||
def test_flagfile_nested(self):
|
|
||||||
self.files['bar.flags'] = '--foo=bar'
|
|
||||||
|
|
||||||
self._do_test_flagfile('--flagfile=bar.flags', '')
|
|
||||||
|
|
||||||
self.assertEquals(self.files[self.tempfiles[-2]],
|
|
||||||
'[DEFAULT]\nfoo=bar\n')
|
|
||||||
|
|
||||||
def test_flagfile_managed(self):
|
|
||||||
self.files['foo.flags'] = ''
|
|
||||||
before = ['--flagfile=foo.flags']
|
|
||||||
with flagfile.handle_flagfiles_managed(before) as after:
|
|
||||||
self.assertEquals(after, ['--config-file=' + self.tempfiles[-1]])
|
|
||||||
self.assertEquals(self.files[self.tempfiles[-1]], '[DEFAULT]\n')
|
|
||||||
self.assertTrue(self.tempdir is None)
|
|
||||||
Reference in New Issue
Block a user