diff options
author | Jenkins <jenkins@review.openstack.org> | 2014-10-08 16:35:08 +0000 |
---|---|---|
committer | Gerrit Code Review <review@openstack.org> | 2014-10-08 16:35:08 +0000 |
commit | dc6e2375acdcc91fa2ed0b69c707c5be1fa7d781 (patch) | |
tree | 7a36600db0c83b2f1d1e5d02fd5055321ccb6b1e /nova/cmd | |
parent | e4fd16d4b27903aecd747e981ee743bdbae913ab (diff) | |
parent | 46ed619b9ab1d61582f36155eea0d4a88f31fd50 (diff) | |
download | nova-dc6e2375acdcc91fa2ed0b69c707c5be1fa7d781.tar.gz |
Merge "Remove baremetal virt driver"
Diffstat (limited to 'nova/cmd')
-rw-r--r-- | nova/cmd/baremetal_deploy_helper.py | 376 | ||||
-rw-r--r-- | nova/cmd/baremetal_manage.py | 208 |
2 files changed, 0 insertions, 584 deletions
diff --git a/nova/cmd/baremetal_deploy_helper.py b/nova/cmd/baremetal_deploy_helper.py deleted file mode 100644 index dc6e961b1a..0000000000 --- a/nova/cmd/baremetal_deploy_helper.py +++ /dev/null @@ -1,376 +0,0 @@ -# Copyright (c) 2012 NTT DOCOMO, 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. - -"""Starter script for Bare-Metal Deployment Service.""" - - -import cgi -import os -import Queue -import re -import socket -import stat -import sys -import threading -import time -from wsgiref import simple_server - -from oslo.utils import excutils -from oslo.utils import units - -from nova import config -from nova import context as nova_context -from nova.i18n import _ -from nova import objects -from nova.openstack.common import log as logging -from nova.openstack.common import processutils -from nova import utils -from nova.virt.baremetal import baremetal_states -from nova.virt.baremetal import db -from nova.virt.disk import api as disk - - -QUEUE = Queue.Queue() -LOG = logging.getLogger(__name__) - - -class BareMetalDeployException(Exception): - pass - - -# All functions are called from deploy() directly or indirectly. -# They are split for stub-out. - -def discovery(portal_address, portal_port): - """Do iSCSI discovery on portal.""" - utils.execute('iscsiadm', - '-m', 'discovery', - '-t', 'st', - '-p', '%s:%s' % (portal_address, portal_port), - run_as_root=True, - check_exit_code=[0]) - - -def login_iscsi(portal_address, portal_port, target_iqn): - """Login to an iSCSI target.""" - utils.execute('iscsiadm', - '-m', 'node', - '-p', '%s:%s' % (portal_address, portal_port), - '-T', target_iqn, - '--login', - run_as_root=True, - check_exit_code=[0]) - # Ensure the login complete - time.sleep(10) - - -def logout_iscsi(portal_address, portal_port, target_iqn): - """Logout from an iSCSI target.""" - utils.execute('iscsiadm', - '-m', 'node', - '-p', '%s:%s' % (portal_address, portal_port), - '-T', target_iqn, - '--logout', - run_as_root=True, - check_exit_code=[0]) - - -def make_partitions(dev, root_mb, swap_mb, ephemeral_mb): - """Create partitions for root, ephemeral and swap on a disk device.""" - # Lead in with 1MB to allow room for the partition table itself, otherwise - # the way sfdisk adjusts doesn't shift the partition up to compensate, and - # we lose the space. - # http://bazaar.launchpad.net/~ubuntu-branches/ubuntu/raring/util-linux/ - # raring/view/head:/fdisk/sfdisk.c#L1940 - if ephemeral_mb: - stdin_command = ('1,%d,83;\n,%d,82;\n,%d,83;\n0,0;\n' % - (ephemeral_mb, swap_mb, root_mb)) - else: - stdin_command = ('1,%d,83;\n,%d,82;\n0,0;\n0,0;\n' % - (root_mb, swap_mb)) - utils.execute('sfdisk', '-uM', dev, process_input=stdin_command, - run_as_root=True, - attempts=3, - check_exit_code=[0]) - # avoid "device is busy" - time.sleep(10) - - -def is_block_device(dev): - """Check whether a device is block or not.""" - s = os.stat(dev) - return stat.S_ISBLK(s.st_mode) - - -def dd(src, dst): - """Execute dd from src to dst.""" - utils.execute('dd', - 'if=%s' % src, - 'of=%s' % dst, - 'bs=1M', - 'oflag=direct', - run_as_root=True, - check_exit_code=[0]) - - -def mkswap(dev, label='swap1'): - """Execute mkswap on a device.""" - utils.execute('mkswap', - '-L', label, - dev, - run_as_root=True, - check_exit_code=[0]) - - -def mkfs_ephemeral(dev, label="ephemeral0"): - # TODO(jogo) support non-default mkfs options as well - disk.mkfs("default", label, dev) - - -def block_uuid(dev): - """Get UUID of a block device.""" - out, _ = utils.execute('blkid', '-s', 'UUID', '-o', 'value', dev, - run_as_root=True, - check_exit_code=[0]) - return out.strip() - - -def switch_pxe_config(path, root_uuid): - """Switch a pxe config from deployment mode to service mode.""" - with open(path) as f: - lines = f.readlines() - root = 'UUID=%s' % root_uuid - rre = re.compile(r'\$\{ROOT\}') - dre = re.compile('^default .*$') - with open(path, 'w') as f: - for line in lines: - line = rre.sub(root, line) - line = dre.sub('default boot', line) - f.write(line) - - -def notify(address, port): - """Notify a node that it becomes ready to reboot.""" - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - s.connect((address, port)) - s.send('done') - finally: - s.close() - - -def get_dev(address, port, iqn, lun): - """Returns a device path for given parameters.""" - dev = "/dev/disk/by-path/ip-%s:%s-iscsi-%s-lun-%s" \ - % (address, port, iqn, lun) - return dev - - -def get_image_mb(image_path): - """Get size of an image in Megabyte.""" - mb = units.Mi - image_byte = os.path.getsize(image_path) - # round up size to MB - image_mb = int((image_byte + mb - 1) / mb) - return image_mb - - -def work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, image_path, - preserve_ephemeral): - """Creates partitions and write an image to the root partition. - - :param preserve_ephemeral: If True, no filesystem is written to the - ephemeral block device, preserving whatever content it had (if the - partition table has not changed). - """ - def raise_exception(msg): - LOG.error(msg) - raise BareMetalDeployException(msg) - - if ephemeral_mb: - ephemeral_part = "%s-part1" % dev - swap_part = "%s-part2" % dev - root_part = "%s-part3" % dev - else: - root_part = "%s-part1" % dev - swap_part = "%s-part2" % dev - - if not is_block_device(dev): - raise_exception(_("parent device '%s' not found") % dev) - make_partitions(dev, root_mb, swap_mb, ephemeral_mb) - if not is_block_device(root_part): - raise_exception(_("root device '%s' not found") % root_part) - if not is_block_device(swap_part): - raise_exception(_("swap device '%s' not found") % swap_part) - if ephemeral_mb and not is_block_device(ephemeral_part): - raise_exception(_("ephemeral device '%s' not found") % ephemeral_part) - dd(image_path, root_part) - mkswap(swap_part) - if ephemeral_mb and not preserve_ephemeral: - mkfs_ephemeral(ephemeral_part) - - try: - root_uuid = block_uuid(root_part) - except processutils.ProcessExecutionError: - with excutils.save_and_reraise_exception(): - LOG.error(_("Failed to detect root device UUID.")) - return root_uuid - - -def deploy(address, port, iqn, lun, image_path, pxe_config_path, - root_mb, swap_mb, ephemeral_mb, preserve_ephemeral=False): - """All-in-one function to deploy a node. - - :param preserve_ephemeral: If True, no filesystem is written to the - ephemeral block device, preserving whatever content it had (if the - partition table has not changed). - """ - dev = get_dev(address, port, iqn, lun) - image_mb = get_image_mb(image_path) - if image_mb > root_mb: - root_mb = image_mb - discovery(address, port) - login_iscsi(address, port, iqn) - try: - root_uuid = work_on_disk(dev, root_mb, swap_mb, ephemeral_mb, - image_path, preserve_ephemeral) - except processutils.ProcessExecutionError as err: - with excutils.save_and_reraise_exception(): - # Log output if there was a error - LOG.error(_("Cmd : %s"), err.cmd) - LOG.error(_("StdOut : %r"), err.stdout) - LOG.error(_("StdErr : %r"), err.stderr) - finally: - logout_iscsi(address, port, iqn) - switch_pxe_config(pxe_config_path, root_uuid) - # Ensure the node started netcat on the port after POST the request. - time.sleep(3) - notify(address, 10000) - - -class Worker(threading.Thread): - """Thread that handles requests in queue.""" - - def __init__(self): - super(Worker, self).__init__() - self.setDaemon(True) - self.stop = False - self.queue_timeout = 1 - - def run(self): - while not self.stop: - try: - # Set timeout to check self.stop periodically - (node_id, params) = QUEUE.get(block=True, - timeout=self.queue_timeout) - except Queue.Empty: - pass - else: - # Requests comes here from BareMetalDeploy.post() - LOG.info(_('start deployment for node %(node_id)s, ' - 'params %(params)s'), - {'node_id': node_id, 'params': params}) - context = nova_context.get_admin_context() - try: - db.bm_node_update(context, node_id, - {'task_state': baremetal_states.DEPLOYING}) - deploy(**params) - except Exception: - LOG.exception(_('deployment to node %s failed'), node_id) - db.bm_node_update(context, node_id, - {'task_state': baremetal_states.DEPLOYFAIL}) - else: - LOG.info(_('deployment to node %s done'), node_id) - db.bm_node_update(context, node_id, - {'task_state': baremetal_states.DEPLOYDONE}) - - -class BareMetalDeploy(object): - """WSGI server for bare-metal deployment.""" - - def __init__(self): - self.worker = Worker() - self.worker.start() - - def __call__(self, environ, start_response): - method = environ['REQUEST_METHOD'] - if method == 'POST': - return self.post(environ, start_response) - else: - start_response('501 Not Implemented', - [('Content-type', 'text/plain')]) - return 'Not Implemented' - - def post(self, environ, start_response): - LOG.info(_("post: environ=%s"), environ) - inpt = environ['wsgi.input'] - length = int(environ.get('CONTENT_LENGTH', 0)) - - x = inpt.read(length) - q = dict(cgi.parse_qsl(x)) - try: - node_id = q['i'] - deploy_key = q['k'] - address = q['a'] - port = q.get('p', '3260') - iqn = q['n'] - lun = q.get('l', '1') - err_msg = q.get('e') - except KeyError as e: - start_response('400 Bad Request', [('Content-type', 'text/plain')]) - return "parameter '%s' is not defined" % e - - if err_msg: - LOG.error(_('Deploy agent error message: %s'), err_msg) - - context = nova_context.get_admin_context() - d = db.bm_node_get(context, node_id) - - if d['deploy_key'] != deploy_key: - start_response('400 Bad Request', [('Content-type', 'text/plain')]) - return 'key is not match' - - params = {'address': address, - 'port': port, - 'iqn': iqn, - 'lun': lun, - 'image_path': d['image_path'], - 'pxe_config_path': d['pxe_config_path'], - 'root_mb': int(d['root_mb']), - 'swap_mb': int(d['swap_mb']), - 'ephemeral_mb': int(d['ephemeral_mb']), - 'preserve_ephemeral': d['preserve_ephemeral'], - } - # Restart worker, if needed - if not self.worker.isAlive(): - self.worker = Worker() - self.worker.start() - LOG.info(_("request is queued: node %(node_id)s, params %(params)s"), - {'node_id': node_id, 'params': params}) - QUEUE.put((node_id, params)) - # Requests go to Worker.run() - start_response('200 OK', [('Content-type', 'text/plain')]) - return '' - - -def main(): - config.parse_args(sys.argv) - logging.setup("nova") - global LOG - LOG = logging.getLogger('nova.virt.baremetal.deploy_helper') - objects.register_all() - app = BareMetalDeploy() - srv = simple_server.make_server('', 10000, app) - srv.serve_forever() diff --git a/nova/cmd/baremetal_manage.py b/nova/cmd/baremetal_manage.py deleted file mode 100644 index e8283221ec..0000000000 --- a/nova/cmd/baremetal_manage.py +++ /dev/null @@ -1,208 +0,0 @@ -# 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.i18n import _ -from nova import objects -from nova.openstack.common import cliutils -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 -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.')) - return(2) - - objects.register_all() - - 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 |