Add live migration support and firewall rules

The nova live migration url was set to qemu_ssh//... which doesn't work
on Red Hat distributions as the user in the packages is set up with a
nologin shell.
The desired way to do live migrations is to use qemu+tcp://...
The libvirt config option (listen_tcp) is already set to 1 in this
patch - https://review.openstack.org/#/c/106436/

Fixes: rhbz#1122457, rhbz#1122703, rhbz#1117524

Change-Id: I36055847fa293edb63a972a0c9f597bc2e27b7ab
This commit is contained in:
Vladan Popovic
2014-07-28 12:03:10 +02:00
committed by Gilles Dubreuil
parent 1575898829
commit 2ff66be39c
5 changed files with 74 additions and 33 deletions

View File

@@ -195,6 +195,9 @@ Nova Options
**CONFIG_NOVA_COMPUTE_PRIVIF** **CONFIG_NOVA_COMPUTE_PRIVIF**
Private interface for Flat DHCP on the Nova compute servers. Private interface for Flat DHCP on the Nova compute servers.
**CONFIG_NOVA_COMPUTE_MIGRATE_PROTOCOL**
Protocol used for instance migration. Allowed values are tcp and ssh. Note that by defaul nova user is created with /sbin/nologin shell so that ssh protocol won't be working. To make ssh protocol work you have to fix nova user on compute hosts manually.
**CONFIG_NOVA_NETWORK_HOSTS** **CONFIG_NOVA_NETWORK_HOSTS**
List of IP address of the servers on which to install the Nova Network service. List of IP address of the servers on which to install the Nova Network service.

View File

@@ -90,6 +90,24 @@ def initConfig(controller):
"USE_DEFAULT": False, "USE_DEFAULT": False,
"NEED_CONFIRM": False, "NEED_CONFIRM": False,
"CONDITION": False}, "CONDITION": False},
{"CMD_OPTION": "novacompute-migrate-protocol",
"USAGE": ("Protocol used for instance migration. Allowed values "
"are tcp and ssh. Note that by defaul nova user is "
"created with /sbin/nologin shell so that ssh protocol "
"won't be working. To make ssh protocol work you have "
"to fix nova user on compute hosts manually."),
"PROMPT": ("Enter protocol which will be used for instance "
"migration"),
"OPTION_LIST": ['tcp', 'ssh'],
"VALIDATORS": [validators.validate_options],
"DEFAULT_VALUE": 'tcp',
"MASK_INPUT": False,
"LOOSE_VALIDATION": True,
"CONF_NAME": "CONFIG_NOVA_COMPUTE_MIGRATE_PROTOCOL",
"USE_DEFAULT": False,
"NEED_CONFIRM": False,
"CONDITION": False},
], ],
"NOVA_NETWORK": [ "NOVA_NETWORK": [
@@ -309,7 +327,7 @@ def initSequences(controller):
{'title': 'Creating ssh keys for Nova migration', {'title': 'Creating ssh keys for Nova migration',
'functions': [create_ssh_keys]}, 'functions': [create_ssh_keys]},
{'title': 'Gathering ssh host keys for Nova migration', {'title': 'Gathering ssh host keys for Nova migration',
'functions': [gather_host_keys]}, 'functions': [gather_host_keys]},
{'title': 'Adding Nova Compute manifest entries', {'title': 'Adding Nova Compute manifest entries',
'functions': [create_compute_manifest]}, 'functions': [create_compute_manifest]},
{'title': 'Adding Nova Scheduler manifest entries', {'title': 'Adding Nova Scheduler manifest entries',
@@ -434,12 +452,23 @@ def create_conductor_manifest(config, messages):
def create_compute_manifest(config, messages): def create_compute_manifest(config, messages):
global compute_hosts, network_hosts global compute_hosts, network_hosts
migrate_protocol = config['CONFIG_NOVA_COMPUTE_MIGRATE_PROTOCOL']
if migrate_protocol == 'ssh':
config['CONFIG_NOVA_COMPUTE_MIGRATE_URL'] = (
'qemu+ssh://nova@%s/system?no_verify=1&'
'keyfile=/etc/nova/ssh/nova_migration_key'
)
else:
config['CONFIG_NOVA_COMPUTE_MIGRATE_URL'] = (
'qemu+tcp://nova@%s/system'
)
ssh_hostkeys = '' ssh_hostkeys = ''
for host in compute_hosts: for host in compute_hosts:
try: try:
host_name, host_aliases, host_addrs = socket.gethostbyaddr(host) hostname, aliases, addrs = socket.gethostbyaddr(host)
except socket.herror: except socket.herror:
host_name, host_aliases, host_addrs = (host, [], []) hostname, aliases, addrs = (host, [], [])
for hostkey in config['HOST_KEYS_%s' % host].split('\n'): for hostkey in config['HOST_KEYS_%s' % host].split('\n'):
hostkey = hostkey.strip() hostkey = hostkey.strip()
@@ -447,9 +476,9 @@ def create_compute_manifest(config, messages):
continue continue
_, host_key_type, host_key_data = hostkey.split() _, host_key_type, host_key_data = hostkey.split()
config['SSH_HOST_NAME'] = host_name config['SSH_HOST_NAME'] = hostname
config['SSH_HOST_ALIASES'] = ','.join( config['SSH_HOST_ALIASES'] = ','.join(
'"%s"' % addr for addr in host_aliases + host_addrs '"%s"' % addr for addr in aliases + addrs
) )
config['SSH_HOST_KEY'] = host_key_data config['SSH_HOST_KEY'] = host_key_data
config['SSH_HOST_KEY_TYPE'] = host_key_type config['SSH_HOST_KEY_TYPE'] = host_key_type
@@ -459,15 +488,16 @@ def create_compute_manifest(config, messages):
config["CONFIG_NOVA_COMPUTE_HOST"] = host config["CONFIG_NOVA_COMPUTE_HOST"] = host
manifestdata = getManifestTemplate("nova_compute.pp") manifestdata = getManifestTemplate("nova_compute.pp")
for c_host in compute_hosts: if migrate_protocol == 'ssh':
config['FIREWALL_SERVICE_NAME'] = "nova qemu migration" for c_host in compute_hosts:
config['FIREWALL_PORTS'] = "'49152-49215'" config['FIREWALL_SERVICE_NAME'] = "nova qemu migration"
config['FIREWALL_CHAIN'] = "INPUT" config['FIREWALL_PORTS'] = "'49152-49215'"
config['FIREWALL_PROTOCOL'] = 'tcp' config['FIREWALL_CHAIN'] = "INPUT"
config['FIREWALL_ALLOWED'] = "'%s'" % c_host config['FIREWALL_PROTOCOL'] = 'tcp'
config['FIREWALL_SERVICE_ID'] = ("nova_qemu_migration_%s_%s" config['FIREWALL_ALLOWED'] = "'%s'" % c_host
% (host, c_host)) config['FIREWALL_SERVICE_ID'] = ("nova_qemu_migration_%s_%s"
manifestdata += getManifestTemplate("firewall.pp") % (host, c_host))
manifestdata += getManifestTemplate("firewall.pp")
if config['CONFIG_VMWARE_BACKEND'] == 'y': if config['CONFIG_VMWARE_BACKEND'] == 'y':
manifestdata += getManifestTemplate("nova_compute_vmware.pp") manifestdata += getManifestTemplate("nova_compute_vmware.pp")
@@ -502,10 +532,12 @@ def create_compute_manifest(config, messages):
manifestdata += getManifestTemplate(mq_template) manifestdata += getManifestTemplate(mq_template)
manifestdata += getManifestTemplate("nova_ceilometer.pp") manifestdata += getManifestTemplate("nova_ceilometer.pp")
config['FIREWALL_PORTS'] = ['5900-5999']
if migrate_protocol == 'tcp':
config['FIREWALL_PORTS'].append('16509')
config['FIREWALL_ALLOWED'] = "'%s'" % config['CONFIG_CONTROLLER_HOST'] config['FIREWALL_ALLOWED'] = "'%s'" % config['CONFIG_CONTROLLER_HOST']
config['FIREWALL_SERVICE_NAME'] = "nova compute" config['FIREWALL_SERVICE_NAME'] = "nova compute"
config['FIREWALL_SERVICE_ID'] = "nova_compute" config['FIREWALL_SERVICE_ID'] = "nova_compute"
config['FIREWALL_PORTS'] = "'5900-5999'"
config['FIREWALL_CHAIN'] = "INPUT" config['FIREWALL_CHAIN'] = "INPUT"
config['FIREWALL_PROTOCOL'] = 'tcp' config['FIREWALL_PROTOCOL'] = 'tcp'
manifestdata += getManifestTemplate("firewall.pp") manifestdata += getManifestTemplate("firewall.pp")

View File

@@ -1,4 +1,13 @@
$private_key = {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_SECRET)s',
}
$public_key = {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_PUBLIC)s',
}
class { "nova": class { "nova":
glance_api_servers => "%(CONFIG_CONTROLLER_HOST)s:9292", glance_api_servers => "%(CONFIG_CONTROLLER_HOST)s:9292",
qpid_hostname => "%(CONFIG_AMQP_HOST)s", qpid_hostname => "%(CONFIG_AMQP_HOST)s",
@@ -9,13 +18,7 @@ class { "nova":
qpid_protocol => '%(CONFIG_AMQP_PROTOCOL)s', qpid_protocol => '%(CONFIG_AMQP_PROTOCOL)s',
verbose => true, verbose => true,
debug => %(CONFIG_DEBUG_MODE)s, debug => %(CONFIG_DEBUG_MODE)s,
nova_public_key => { nova_public_key => $public_key,
type => '%(NOVA_MIGRATION_KEY_TYPE)s', nova_private_key => $private_key,
key => '%(NOVA_MIGRATION_KEY_PUBLIC)s',
},
nova_private_key => {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_SECRET)s',
},
nova_shell => '/bin/bash', nova_shell => '/bin/bash',
} }

View File

@@ -1,4 +1,13 @@
$private_key = {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_SECRET)s',
}
$public_key = {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_PUBLIC)s',
}
class { "nova": class { "nova":
glance_api_servers => "%(CONFIG_CONTROLLER_HOST)s:9292", glance_api_servers => "%(CONFIG_CONTROLLER_HOST)s:9292",
rabbit_host => "%(CONFIG_AMQP_HOST)s", rabbit_host => "%(CONFIG_AMQP_HOST)s",
@@ -7,13 +16,7 @@ class { "nova":
rabbit_password => '%(CONFIG_AMQP_AUTH_PASSWORD)s', rabbit_password => '%(CONFIG_AMQP_AUTH_PASSWORD)s',
verbose => true, verbose => true,
debug => %(CONFIG_DEBUG_MODE)s, debug => %(CONFIG_DEBUG_MODE)s,
nova_public_key => { nova_public_key => $public_key,
type => '%(NOVA_MIGRATION_KEY_TYPE)s', nova_private_key => $private_key,
key => '%(NOVA_MIGRATION_KEY_PUBLIC)s',
},
nova_private_key => {
type => '%(NOVA_MIGRATION_KEY_TYPE)s',
key => '%(NOVA_MIGRATION_KEY_SECRET)s',
},
nova_shell => '/bin/bash', nova_shell => '/bin/bash',
} }

View File

@@ -1,3 +1,4 @@
package{'python-cinderclient': package{'python-cinderclient':
before => Class["nova"] before => Class["nova"]
} }
@@ -21,7 +22,7 @@ file { '/etc/nova/ssh/nova_migration_key':
nova_config{ nova_config{
"DEFAULT/volume_api_class": value => "nova.volume.cinder.API"; "DEFAULT/volume_api_class": value => "nova.volume.cinder.API";
"libvirt/live_migration_uri": value => "qemu+ssh://nova@%%s/system?no_verify=1&keyfile=/etc/nova/ssh/nova_migration_key"; "libvirt/live_migration_uri": value => "%(CONFIG_NOVA_COMPUTE_MIGRATE_URL)s";
} }
class {"nova::compute": class {"nova::compute":
@@ -74,4 +75,3 @@ exec {'tuned-virtual-host':
command => '/usr/sbin/tuned-adm profile virtual-host', command => '/usr/sbin/tuned-adm profile virtual-host',
require => Service['tuned'], require => Service['tuned'],
} }