¡@

Home 

OpenStack Study: baremetal_manage.py

OpenStack Index

**** CubicPower OpenStack Study ****

# 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 os

import sys

from oslo.config import cfg

import six

from nova import config

from nova.openstack.common import cliutils

from nova.openstack.common.gettextutils import _

from nova.openstack.common import log as logging

from nova import version

from nova.virt.baremetal.db import migration as bmdb_migration

CONF = cfg.CONF

# Decorators for actions

**** CubicPower OpenStack Study ****

def args(*args, **kwargs):

    def _decorator(func):

        func.__dict__.setdefault('args', []).insert(0, (args, kwargs))

        return func

    return _decorator

**** CubicPower OpenStack Study ****

 def _decorator(func):

        func.__dict__.setdefault('args', []).insert(0, (args, kwargs))

        return func

    return _decorator

**** CubicPower OpenStack Study ****

class BareMetalDbCommands(object):

"""Class for managing the bare-metal database."""

**** CubicPower OpenStack Study ****

    def __init__(self):

        pass

    @args('--version', dest='version', metavar='',

            help='Bare-metal Database version')

**** CubicPower OpenStack Study ****

    def sync(self, version=None):

        """Sync the database up to the most recent version."""

        bmdb_migration.db_sync(version)

**** CubicPower OpenStack Study ****

    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.'))

        return(2)

    if CONF.category.name == "version":

        print(version.version_string_with_package())

        return(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]))

        return(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, six.string_types):

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

        print(e)

        return(1)

    try:

        fn(*fn_args, **fn_kwargs)

        return(0)

    except Exception:

        print(_("Command failed, please check log for more info"))

        raise

**** CubicPower OpenStack Study ****

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

**** CubicPower OpenStack Study ****

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)

**** CubicPower OpenStack Study ****

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.'))

        return(2)

    if CONF.category.name == "version":

        print(version.version_string_with_package())

        return(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]))

        return(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, six.string_types):

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

        print(e)

        return(1)

    try:

        fn(*fn_args, **fn_kwargs)

        return(0)

    except Exception:

        print(_("Command failed, please check log for more info"))

        raise