CLI for bare-metal database sync.
Part 3 of 6: blueprint general-bare-metal-provisioning-framework. Change-Id: Ia19ce00edb84aa924c2ab2c9c2217f6b49073d69 Co-authored-by: Mikyung Kang <mkkang@isi.edu> Co-authored-by: David Kang <dkang@isi.edu> Co-authored-by: Ken Igarashi <igarashik@nttdocomo.co.jp> Co-authored-by: Arata Notsu <notsu@virtualtech.jp>
This commit is contained in:
parent
7cd22aaca7
commit
eeff3ddcb6
234
bin/nova-baremetal-manage
Executable file
234
bin/nova-baremetal-manage
Executable file
@ -0,0 +1,234 @@
|
||||
#!/usr/bin/env python
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2011 X.commerce, a business unit of eBay Inc.
|
||||
# Copyright 2010 United States Government as represented by the
|
||||
# Administrator of the National Aeronautics and Space Administration.
|
||||
# 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.
|
||||
|
||||
# Interactive shell based on Django:
|
||||
#
|
||||
# Copyright (c) 2005, the Lawrence Journal-World
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of Django nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without
|
||||
# specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
"""
|
||||
CLI interface for nova bare-metal management.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import errno
|
||||
import gettext
|
||||
import math
|
||||
import netaddr
|
||||
import optparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
# If ../nova/__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, 'nova', '__init__.py')):
|
||||
sys.path.insert(0, POSSIBLE_TOPDIR)
|
||||
|
||||
gettext.install('nova', unicode=1)
|
||||
|
||||
from nova import config
|
||||
from nova import context
|
||||
from nova import exception
|
||||
from nova.openstack.common import cfg
|
||||
from nova.openstack.common import cliutils
|
||||
from nova.openstack.common import importutils
|
||||
from nova.openstack.common import log as logging
|
||||
from nova.openstack.common import rpc
|
||||
from nova.openstack.common import timeutils
|
||||
from nova import utils
|
||||
from nova import version
|
||||
from nova.virt.baremetal import db as bmdb
|
||||
from nova.virt.baremetal.db import migration as bmdb_migration
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
# Decorators for actions
|
||||
def args(*args, **kwargs):
|
||||
def _decorator(func):
|
||||
func.__dict__.setdefault('args', []).insert(0, (args, kwargs))
|
||||
return func
|
||||
return _decorator
|
||||
|
||||
|
||||
class BareMetalDbCommands(object):
|
||||
"""Class for managing the bare-metal database."""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@args('--version', dest='version', metavar='<version>',
|
||||
help='Bare-metal Database version')
|
||||
def sync(self, version=None):
|
||||
"""Sync the database up to the most recent version."""
|
||||
bmdb_migration.db_sync(version)
|
||||
|
||||
def version(self):
|
||||
"""Print the current database version."""
|
||||
v = bmdb_migration.db_version()
|
||||
print(v)
|
||||
# return for unittest
|
||||
return v
|
||||
|
||||
|
||||
CATEGORIES = {
|
||||
'db': BareMetalDbCommands,
|
||||
}
|
||||
|
||||
|
||||
def methods_of(obj):
|
||||
"""Get all callable methods of an object that don't start with underscore
|
||||
returns a list of tuples of the form (method_name, method)"""
|
||||
result = []
|
||||
for i in dir(obj):
|
||||
if callable(getattr(obj, i)) and not i.startswith('_'):
|
||||
result.append((i, getattr(obj, i)))
|
||||
return result
|
||||
|
||||
|
||||
def add_command_parsers(subparsers):
|
||||
parser = subparsers.add_parser('bash-completion')
|
||||
parser.add_argument('query_category', nargs='?')
|
||||
|
||||
for category in CATEGORIES:
|
||||
command_object = CATEGORIES[category]()
|
||||
|
||||
parser = subparsers.add_parser(category)
|
||||
parser.set_defaults(command_object=command_object)
|
||||
|
||||
category_subparsers = parser.add_subparsers(dest='action')
|
||||
|
||||
for (action, action_fn) in methods_of(command_object):
|
||||
parser = category_subparsers.add_parser(action)
|
||||
|
||||
action_kwargs = []
|
||||
for args, kwargs in getattr(action_fn, 'args', []):
|
||||
action_kwargs.append(kwargs['dest'])
|
||||
kwargs['dest'] = 'action_kwarg_' + kwargs['dest']
|
||||
parser.add_argument(*args, **kwargs)
|
||||
|
||||
parser.set_defaults(action_fn=action_fn)
|
||||
parser.set_defaults(action_kwargs=action_kwargs)
|
||||
|
||||
parser.add_argument('action_args', nargs='*')
|
||||
|
||||
|
||||
category_opt = cfg.SubCommandOpt('category',
|
||||
title='Command categories',
|
||||
help='Available categories',
|
||||
handler=add_command_parsers)
|
||||
|
||||
|
||||
def main():
|
||||
"""Parse options and call the appropriate class/method."""
|
||||
CONF.register_cli_opt(category_opt)
|
||||
try:
|
||||
config.parse_args(sys.argv)
|
||||
logging.setup("nova")
|
||||
except cfg.ConfigFilesNotFoundError:
|
||||
cfgfile = CONF.config_file[-1] if CONF.config_file else None
|
||||
if cfgfile and not os.access(cfgfile, os.R_OK):
|
||||
st = os.stat(cfgfile)
|
||||
print(_("Could not read %s. Re-running with sudo") % cfgfile)
|
||||
try:
|
||||
os.execvp('sudo', ['sudo', '-u', '#%s' % st.st_uid] + sys.argv)
|
||||
except Exception:
|
||||
print(_('sudo failed, continuing as if nothing happened'))
|
||||
|
||||
print(_('Please re-run nova-manage as root.'))
|
||||
sys.exit(2)
|
||||
|
||||
if CONF.category.name == "version":
|
||||
print(_("%(version)s (%(vcs)s)") %
|
||||
{'version': version.version_string(),
|
||||
'vcs': version.version_string_with_vcs()})
|
||||
sys.exit(0)
|
||||
|
||||
if CONF.category.name == "bash-completion":
|
||||
if not CONF.category.query_category:
|
||||
print(" ".join(CATEGORIES.keys()))
|
||||
elif CONF.category.query_category in CATEGORIES:
|
||||
fn = CATEGORIES[CONF.category.query_category]
|
||||
command_object = fn()
|
||||
actions = methods_of(command_object)
|
||||
print(" ".join([k for (k, v) in actions]))
|
||||
sys.exit(0)
|
||||
|
||||
fn = CONF.category.action_fn
|
||||
fn_args = [arg.decode('utf-8') for arg in CONF.category.action_args]
|
||||
fn_kwargs = {}
|
||||
for k in CONF.category.action_kwargs:
|
||||
v = getattr(CONF.category, 'action_kwarg_' + k)
|
||||
if v is None:
|
||||
continue
|
||||
if isinstance(v, basestring):
|
||||
v = v.decode('utf-8')
|
||||
fn_kwargs[k] = v
|
||||
|
||||
# call the action with the remaining arguments
|
||||
# check arguments
|
||||
try:
|
||||
cliutils.validate_args(fn, *fn_args, **fn_kwargs)
|
||||
except cliutils.MissingArgs as e:
|
||||
print(fn.__doc__)
|
||||
parser.print_help()
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
try:
|
||||
fn(*fn_args, **fn_kwargs)
|
||||
sys.exit(0)
|
||||
except Exception:
|
||||
print(_("Command failed, please check log for more info"))
|
||||
raise
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
67
doc/source/man/nova-baremetal-manage.rst
Normal file
67
doc/source/man/nova-baremetal-manage.rst
Normal file
@ -0,0 +1,67 @@
|
||||
=====================
|
||||
nova-baremetal-manage
|
||||
=====================
|
||||
|
||||
------------------------------------------------------
|
||||
Manage bare-metal DB in OpenStack Nova
|
||||
------------------------------------------------------
|
||||
|
||||
:Author: openstack@lists.launchpad.net
|
||||
:Date: 2012-10-17
|
||||
:Copyright: OpenStack LLC
|
||||
:Version: 2013.1
|
||||
:Manual section: 1
|
||||
:Manual group: cloud computing
|
||||
|
||||
SYNOPSIS
|
||||
========
|
||||
|
||||
nova-baremetal-manage <category> <action> [<args>]
|
||||
|
||||
DESCRIPTION
|
||||
===========
|
||||
|
||||
nova-baremetal-manage manages bare-metal DB schema.
|
||||
|
||||
OPTIONS
|
||||
=======
|
||||
|
||||
The standard pattern for executing a nova-baremetal-manage command is:
|
||||
``nova-baremetal-manage <category> <command> [<args>]``
|
||||
|
||||
Run without arguments to see a list of available command categories:
|
||||
``nova-baremetal-manage``
|
||||
|
||||
Categories are db. Detailed descriptions are below.
|
||||
|
||||
You can also run with a category argument such as "db" to see a list of all commands in that category:
|
||||
``nova-baremetal-manage db``
|
||||
|
||||
These sections describe the available categories and arguments for nova-baremetal-manage.
|
||||
|
||||
Bare-Metal DB
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
``nova-baremetal-manage db version``
|
||||
|
||||
Print the current database version.
|
||||
|
||||
``nova-baremetal-manage db sync``
|
||||
|
||||
Sync the database up to the most recent version. This is the standard way to create the db as well.
|
||||
|
||||
FILES
|
||||
========
|
||||
|
||||
/etc/nova/nova.conf: get location of bare-metal DB
|
||||
|
||||
SEE ALSO
|
||||
========
|
||||
|
||||
* `OpenStack Nova <http://nova.openstack.org>`__
|
||||
|
||||
BUGS
|
||||
====
|
||||
|
||||
* Nova is maintained in Launchpad so you can view current bugs at `OpenStack Nova <https://bugs.launchpad.net/nova>`__
|
||||
|
49
nova/tests/baremetal/test_nova_baremetal_manage.py
Normal file
49
nova/tests/baremetal/test_nova_baremetal_manage.py
Normal file
@ -0,0 +1,49 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright (c) 2012 NTT DOCOMO, INC.
|
||||
# Copyright 2011 OpenStack LLC
|
||||
# Copyright 2011 Ilya Alekseyev
|
||||
#
|
||||
# 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 imp
|
||||
import os
|
||||
import sys
|
||||
|
||||
from nova import context
|
||||
from nova import test
|
||||
from nova.virt.baremetal import db as bmdb
|
||||
|
||||
from nova.tests.baremetal.db import base as bm_db_base
|
||||
|
||||
TOPDIR = os.path.normpath(os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
os.pardir,
|
||||
os.pardir,
|
||||
os.pardir))
|
||||
BM_MAN_PATH = os.path.join(TOPDIR, 'bin', 'nova-baremetal-manage')
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
bm_man = imp.load_source('bm_man', BM_MAN_PATH)
|
||||
sys.dont_write_bytecode = False
|
||||
|
||||
|
||||
class BareMetalDbCommandsTestCase(bm_db_base.BMDBTestCase):
|
||||
def setUp(self):
|
||||
super(BareMetalDbCommandsTestCase, self).setUp()
|
||||
self.commands = bm_man.BareMetalDbCommands()
|
||||
|
||||
def test_sync_and_version(self):
|
||||
self.commands.sync()
|
||||
v = self.commands.version()
|
||||
self.assertTrue(v > 0)
|
Loading…
Reference in New Issue
Block a user