Merge "Remove scripts for migrating nova baremetal"

This commit is contained in:
Jenkins 2015-04-21 17:04:24 +00:00 committed by Gerrit Code Review
commit 6f36e056d4
5 changed files with 0 additions and 428 deletions

View File

@ -1,318 +0,0 @@
# 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.
from __future__ import print_function
import argparse
import ConfigParser
import os
import sys
from oslo_utils import uuidutils
import sqlalchemy as sa
from sqlalchemy.orm import sessionmaker
from ironic.common import states as ironic_states
from ironic.db.sqlalchemy import models as ironic_models
from ironic.migrate_nova import nova_baremetal_states as nova_states
from ironic.migrate_nova import nova_models
DESCRIPTION = """
This is an administrative utility to be used for migrating a nova-baremetal
node inventory to Ironic. It will migrate nova-baremetal node and interface
information and associated driver configuration from the Nova database to the
Ironic database. It only supports migrating from the IPMI and
VirtualPowerManager power drivers.
"""
IRONIC_ENGINE = None
NOVA_BM_ENGINE = None
# Relevant nova-baremetal config with their associated defaults as of Juno.
NOVA_BM_CONFIG_KEYS = {
# nova.virt.baremetal.driver
'driver': 'nova.virt.baremetal.pxe.PXE',
'power_manager': 'nova.virt.baremetal.ipmi.IPMI',
# nova.virt.baremetal.virtual_power_driver
'virtual_power_ssh_host': '',
'virtual_power_ssh_port': 22,
'virtual_power_type': 'virsh',
'virtual_power_host_user': '',
'virtual_power_host_pass': '',
'virtual_power_host_key': '',
}
def get_nova_nodes():
Session = sessionmaker(bind=NOVA_BM_ENGINE)
session = Session()
query = session.query(nova_models.BareMetalNode)
try:
nodes = query.all()
except sa.exc.OperationalError as err:
print("Could not get nodes from Nova:\n%s" % err, file=sys.stderr)
sys.exit(2)
session.close()
return nodes
def get_nova_ports():
Session = sessionmaker(bind=NOVA_BM_ENGINE)
session = Session()
query = session.query(nova_models.BareMetalInterface)
try:
ports = query.all()
except sa.exc.OperationalError as err:
print("Could not get ports from Nova:\n%s" % err, file=sys.stderr)
sys.exit(2)
session.close()
return ports
def convert_nova_nodes(nodes, cpu_arch, nova_conf):
ironic_nodes = []
for n_node in nodes:
# Create an empty Ironic Node
i_node = ironic_models.Node()
# Populate basic properties
i_node.id = n_node.id
i_node.uuid = n_node.uuid
i_node.chassis_id = None
i_node.last_error = None
i_node.instance_uuid = n_node.instance_uuid
i_node.reservation = None
i_node.maintenance = False
i_node.updated_at = n_node.updated_at
i_node.created_at = n_node.created_at
# Populate states
if n_node.task_state == nova_states.ACTIVE:
i_node.power_state = ironic_states.POWER_ON
else:
i_node.power_state = ironic_states.POWER_OFF
i_node.target_power_state = None
if i_node.instance_uuid:
prov_state = ironic_states.ACTIVE
else:
prov_state = ironic_states.NOSTATE
i_node.provision_state = prov_state
i_node.target_provision_state = None
# Populate extra properties
i_node.extra = {}
# Populate driver_info
i_node.driver_info = {}
power_manager = nova_conf['power_manager']
if power_manager.endswith('IPMI'):
i_node.driver = 'pxe_ipmitool'
if n_node.pm_address:
i_node.driver_info['ipmi_address'] = n_node.pm_address
if n_node.pm_user:
i_node.driver_info['ipmi_username'] = n_node.pm_user
if n_node.pm_password:
i_node.driver_info['ipmi_password'] = n_node.pm_password
elif power_manager.endswith('VirtualPowerManager'):
i_node.driver = 'pxe_ssh'
i_node.driver_info = {
'ssh_virt_type': nova_conf['virtual_power_type'],
'ssh_address': nova_conf['virtual_power_ssh_host'],
'ssh_username': nova_conf['virtual_power_host_user'],
}
ssh_port = nova_conf.get('ssh_port')
if ssh_port:
ssh_port = nova_conf['virtual_power_ssh_port']
ssh_key = nova_conf.get('virtual_power_host_key')
if ssh_key:
i_node.driver_info['ssh_key_filename'] = ssh_key
ssh_pass = nova_conf.get('virtual_power_host_pass')
if ssh_pass:
i_node.driver_info['ssh_password'] = ssh_pass
else:
print("This does not support migration from power driver: "
"%s\n" % nova_conf['driver'], file=sys.stderr)
sys.exit(2)
# Populate instance_info
i_node.instance_info = {}
if n_node.root_mb:
i_node.instance_info['root_mb'] = n_node.root_mb
if n_node.swap_mb:
i_node.instance_info['swap_mb'] = n_node.swap_mb
if n_node.ephemeral_mb:
i_node.instance_info['ephemeral_mb'] = n_node.ephemeral_mb
i_node.properties = {'cpu_arch': cpu_arch,
'cpus': n_node.cpus,
'local_gb': n_node.local_gb,
'memory_mb': n_node.memory_mb}
ironic_nodes.append(i_node)
return ironic_nodes
def convert_nova_ports(ports):
ironic_ports = []
for n_port in ports:
i_port = ironic_models.Port()
i_port.id = n_port.id
i_port.uuid = uuidutils.generate_uuid()
i_port.address = n_port.address
i_port.node_id = n_port.bm_node_id
i_port.extra = {}
if n_port.vif_uuid:
i_port.extra['vif_uuid'] = n_port.vif_uuid
ironic_ports.append(i_port)
return ironic_ports
def save_ironic_objects(objects):
Session = sessionmaker(bind=IRONIC_ENGINE)
session = Session()
try:
session.add_all(objects)
session.commit()
except sa.exc.OperationalError as err:
print("Could not send data to Ironic:\n%s" % err, file=sys.stderr)
sys.exit(2)
session.close()
def parse_nova_config(config_file):
"""Parse nova.conf and return known defaults if setting is not present.
This avoids having to import nova code from this script and risk conflicts
with Ironic's tree around oslo_config resources.
"""
if not os.path.isfile(config_file):
print("nova.conf not found at %s. Please specify the location via "
"the --nova-config option." % config_file, file=sys.stderr)
sys.exit(1)
nova_conf = ConfigParser.SafeConfigParser()
nova_conf.read(config_file)
conf = {}
for setting, default in NOVA_BM_CONFIG_KEYS.items():
try:
conf[setting] = nova_conf.get('baremetal', setting)
except ConfigParser.NoOptionError:
conf[setting] = default
return conf
def validate_config(config):
"""Early validation of required configuration prior to touching the db."""
if config['power_manager'].endswith('VirtualPowerManager'):
# confirm nova.conf contains all required ssh info, as per
# ironic.drivers.ssh.REQUIRED_PROPERTIES.
req = ['virtual_power_host_user', 'virtual_power_type',
'virtual_power_ssh_host']
missing = []
for r in req:
if not config.get(r):
missing.append(r)
if missing:
print('nova.conf is missing required settings in the '
'[baremetal] section to migrate VirtualPowerManager: %s' %
' '.join(missing), file=sys.stderr)
sys.exit(1)
def parse_args():
parser = argparse.ArgumentParser(description=DESCRIPTION)
parser.add_argument('--nova-bm-db', '-b', type=str,
required=True, dest='nova_bm_conn_string',
help='Connection string to Nova baremetal database.')
parser.add_argument('--ironic-db', '-i', type=str,
required=True, dest='ironic_conn_string',
help='Connection string to Ironic database.')
parser.add_argument('--node-arch', '-a', type=str,
required=True, dest='cpu_arch',
help='CPU architecture of the nodes.')
parser.add_argument('--nova-config', '-c', type=str,
required=False, dest='nova_config',
default='/etc/nova/nova.conf',
help='Path to nova.conf. (default: '
'/etc/nova/nova.conf)')
return parser.parse_args(sys.argv[1:])
def main():
args = parse_args()
global IRONIC_ENGINE
global NOVA_BM_ENGINE
IRONIC_ENGINE = sa.create_engine(args.ironic_conn_string)
NOVA_BM_ENGINE = sa.create_engine(args.nova_bm_conn_string)
# Load and validate nova.conf
nova_conf = parse_nova_config(args.nova_config)
validate_config(nova_conf)
# Process nodes
print("Getting data for baremetal nodes from Nova...")
nova_nodes = get_nova_nodes()
print("Got %d nodes from Nova..." % len(nova_nodes))
print("Converting information for Nova nodes to Ironic...")
ironic_nodes = convert_nova_nodes(nova_nodes, args.cpu_arch,
nova_conf)
print("Saving nodes to Ironic...")
save_ironic_objects(ironic_nodes)
# Process ports
print("Getting baremetal ports from Nova...")
nova_ports = get_nova_ports()
print("Got %d ports from Nova." % len(nova_ports))
print("Converting Nova ports...")
ironic_ports = convert_nova_ports(nova_ports)
print("Saving ports to Ironic...")
save_ironic_objects(ironic_ports)
# Printing summary
print("All done!")
print("%d nodes and %d ports have been migrated from "
"Nova to Ironic." % (len(nova_nodes), len(nova_ports)))
if __name__ == '__main__':
main()

View File

@ -1,38 +0,0 @@
# Copyright (c) 2012 NTT DOCOMO, INC.
# Copyright 2010 OpenStack Foundation
# 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.
# NOTE(adam_g): This code has been copied directly from Nova (J2) to facilitate
# Nova baremetal data migration tools. The original may be found in the Nova
# tree (nova.virt.baremetal.baremetal_states).
"""
Possible baremetal node states for instances.
Compute instance baremetal states represent the state of an instance as it
pertains to a user or administrator. When combined with task states
(task_states.py), a better picture can be formed regarding the instance's
health.
"""
ACTIVE = 'active'
BUILDING = 'building'
DEPLOYING = 'deploying'
DEPLOYFAIL = 'deploy failed'
DEPLOYDONE = 'deploy complete'
DELETED = 'deleted'
ERROR = 'error'
PREPARED = 'prepared'

View File

@ -1,71 +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.
# NOTE(adam_g): This code has been copied directly from Nova (J2) to facilitate
# Nova baremetal data migration tools. The original may be found in the Nova
# tree (nova.virt.baremetal.db.sqlalchemy.models).
"""
SQLAlchemy models for baremetal data.
"""
from sqlalchemy import Column, Boolean, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import ForeignKey, Text
from ironic.db.sqlalchemy import models
BASE = declarative_base()
class BareMetalNode(BASE, models.Base):
"""Represents a bare metal node."""
__tablename__ = 'bm_nodes'
id = Column(Integer, primary_key=True)
deleted = Column(Boolean, default=False)
uuid = Column(String(36))
service_host = Column(String(255))
instance_uuid = Column(String(36))
instance_name = Column(String(255))
cpus = Column(Integer)
memory_mb = Column(Integer)
local_gb = Column(Integer)
preserve_ephemeral = Column(Boolean)
pm_address = Column(Text)
pm_user = Column(Text)
pm_password = Column(Text)
task_state = Column(String(255))
terminal_port = Column(Integer)
image_path = Column(String(255))
pxe_config_path = Column(String(255))
deploy_key = Column(String(255))
# root_mb, swap_mb and ephemeral_mb are cached flavor values for the
# current deployment not attributes of the node.
root_mb = Column(Integer)
swap_mb = Column(Integer)
ephemeral_mb = Column(Integer)
class BareMetalInterface(BASE, models.Base):
__tablename__ = 'bm_interfaces'
id = Column(Integer, primary_key=True)
deleted = Column(Boolean, default=False)
bm_node_id = Column(Integer, ForeignKey('bm_nodes.id'))
address = Column(String(255), unique=True)
datapath_id = Column(String(255))
port_no = Column(Integer)
vif_uuid = Column(String(36), unique=True)

View File

@ -27,7 +27,6 @@ console_scripts =
ironic-dbsync = ironic.cmd.dbsync:main
ironic-conductor = ironic.cmd.conductor:main
ironic-rootwrap = oslo_rootwrap.cmd:main
ironic-nova-bm-migrate = ironic.migrate_nova.migrate_db:main
ironic.dhcp =
neutron = ironic.dhcp.neutron:NeutronDHCPApi