rev439ベースにライブマイグレーションの機能をマージ
このバージョンはEBSなし、CPUフラグのチェックなし
This commit is contained in:
122
bin/nova-manage
122
bin/nova-manage
@@ -76,6 +76,13 @@ from nova import quota
|
|||||||
from nova import utils
|
from nova import utils
|
||||||
from nova.auth import manager
|
from nova.auth import manager
|
||||||
from nova.cloudpipe import pipelib
|
from nova.cloudpipe import pipelib
|
||||||
|
#added by masumotok
|
||||||
|
from nova import rpc
|
||||||
|
# added by masumotok
|
||||||
|
from nova.api.ec2 import cloud
|
||||||
|
# added by masumotok
|
||||||
|
from nova.compute import power_state
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
@@ -424,6 +431,116 @@ class NetworkCommands(object):
|
|||||||
int(network_size), int(vlan_start),
|
int(network_size), int(vlan_start),
|
||||||
int(vpn_start))
|
int(vpn_start))
|
||||||
|
|
||||||
|
# this class is added by masumotok
|
||||||
|
class InstanceCommands(object):
|
||||||
|
"""Class for mangaging VM instances."""
|
||||||
|
|
||||||
|
def live_migration(self, ec2_id, dest):
|
||||||
|
"""live_migration"""
|
||||||
|
|
||||||
|
logging.basicConfig()
|
||||||
|
ctxt = context.get_admin_context()
|
||||||
|
|
||||||
|
if 'nova.network.manager.VlanManager' != FLAGS.network_manager :
|
||||||
|
msg = 'Only nova.network.manager.VlanManager is supported now. Sorry!'
|
||||||
|
raise Exception(msg)
|
||||||
|
|
||||||
|
# 1. whether destination host exists
|
||||||
|
host_ref = db.host_get_by_name(ctxt, dest)
|
||||||
|
|
||||||
|
# 2. whether instance exists and running
|
||||||
|
# try-catch clause is necessary because only internal_id is shown
|
||||||
|
# when NotFound exception occurs. it isnot understandable to admins.
|
||||||
|
try :
|
||||||
|
internal_id = cloud.ec2_id_to_internal_id(ec2_id)
|
||||||
|
instance_ref = db.instance_get_by_internal_id(ctxt, internal_id)
|
||||||
|
except exception.NotFound :
|
||||||
|
print 'Not found instance_id(%s (internal_id:%s))' % ( ec2_id, internal_id)
|
||||||
|
raise
|
||||||
|
|
||||||
|
if power_state.RUNNING != instance_ref['state'] or \
|
||||||
|
'running' != instance_ref['state_description']:
|
||||||
|
print 'Instance(%s) is not running' % ec2_id
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# 3. the host where instance is running and dst host is not same
|
||||||
|
if dest == instance_ref['host'] :
|
||||||
|
print '%s is where %s is running now. choose different host.' \
|
||||||
|
% (dest, ec2_id)
|
||||||
|
sys.exit(2)
|
||||||
|
|
||||||
|
# 4. live migration
|
||||||
|
rpc.cast(ctxt,
|
||||||
|
FLAGS.scheduler_topic,
|
||||||
|
{ "method": "live_migration",
|
||||||
|
"args": {"ec2_id": ec2_id,
|
||||||
|
"dest":dest}})
|
||||||
|
|
||||||
|
print 'Finished all procedure. check instance are migrated successfully'
|
||||||
|
print 'chech status by using euca-describe-instances.'
|
||||||
|
|
||||||
|
|
||||||
|
# this class is created by masumotok
|
||||||
|
class HostCommands(object):
|
||||||
|
"""Class for mangaging host(physical nodes)."""
|
||||||
|
|
||||||
|
|
||||||
|
def list(self):
|
||||||
|
"""describe host list."""
|
||||||
|
|
||||||
|
# to supress msg: No handlers could be found for logger "amqplib"
|
||||||
|
logging.basicConfig()
|
||||||
|
|
||||||
|
host_refs = db.host_get_all(context.get_admin_context())
|
||||||
|
for host_ref in host_refs:
|
||||||
|
print host_ref['name']
|
||||||
|
|
||||||
|
def show(self, host):
|
||||||
|
"""describe cpu/memory/hdd info for host."""
|
||||||
|
|
||||||
|
# to supress msg: No handlers could be found for logger "amqplib"
|
||||||
|
logging.basicConfig()
|
||||||
|
|
||||||
|
result = rpc.call(context.get_admin_context(),
|
||||||
|
FLAGS.scheduler_topic,
|
||||||
|
{"method": "show_host_resource",
|
||||||
|
"args": {"host": host}})
|
||||||
|
|
||||||
|
# checing result msg format is necessary, that will have done
|
||||||
|
# when this feture is included in API.
|
||||||
|
if dict != type(result):
|
||||||
|
print 'Unexpected error occurs'
|
||||||
|
elif not result['ret'] :
|
||||||
|
print '%s' % result['msg']
|
||||||
|
else :
|
||||||
|
cpu = result['phy_resource']['cpu']
|
||||||
|
mem = result['phy_resource']['memory_mb']
|
||||||
|
hdd = result['phy_resource']['hdd_gb']
|
||||||
|
|
||||||
|
print 'HOST\t\tPROJECT\t\tcpu\tmem(mb)\tdisk(gb)'
|
||||||
|
print '%s\t\t\t%s\t%s\t%s' % ( host,cpu, mem, hdd)
|
||||||
|
for p_id, val in result['usage'].items() :
|
||||||
|
print '%s\t%s\t\t%s\t%s\t%s' % ( host,
|
||||||
|
p_id,
|
||||||
|
val['cpu'],
|
||||||
|
val['memory_mb'],
|
||||||
|
val['hdd_gb'])
|
||||||
|
|
||||||
|
def has_keys(self, dic, keys):
|
||||||
|
not_found = [ key for key in keys if not dict.has_key(key) ]
|
||||||
|
return ( (0 == len(not_found)), not_found )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# modified by masumotok
|
||||||
|
#CATEGORIES = [
|
||||||
|
# ('user', UserCommands),
|
||||||
|
# ('project', ProjectCommands),
|
||||||
|
# ('role', RoleCommands),
|
||||||
|
# ('shell', ShellCommands),
|
||||||
|
# ('vpn', VpnCommands),
|
||||||
|
# ('floating', FloatingIpCommands),
|
||||||
|
# ('network', NetworkCommands)]
|
||||||
CATEGORIES = [
|
CATEGORIES = [
|
||||||
('user', UserCommands),
|
('user', UserCommands),
|
||||||
('project', ProjectCommands),
|
('project', ProjectCommands),
|
||||||
@@ -431,8 +548,9 @@ CATEGORIES = [
|
|||||||
('shell', ShellCommands),
|
('shell', ShellCommands),
|
||||||
('vpn', VpnCommands),
|
('vpn', VpnCommands),
|
||||||
('floating', FloatingIpCommands),
|
('floating', FloatingIpCommands),
|
||||||
('network', NetworkCommands)]
|
('network', NetworkCommands),
|
||||||
|
('instance', InstanceCommands),
|
||||||
|
('host',HostCommands)]
|
||||||
|
|
||||||
def lazy_match(name, key_value_tuples):
|
def lazy_match(name, key_value_tuples):
|
||||||
"""Finds all objects that have a key that case insensitively contains
|
"""Finds all objects that have a key that case insensitively contains
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ from nova import flags
|
|||||||
from nova import manager
|
from nova import manager
|
||||||
from nova import rpc
|
from nova import rpc
|
||||||
from nova import utils
|
from nova import utils
|
||||||
|
# 3 modules are added by masumotok
|
||||||
|
from nova import exception
|
||||||
|
from nova.api.ec2 import cloud
|
||||||
|
from nova.compute import power_state
|
||||||
|
|
||||||
FLAGS = flags.FLAGS
|
FLAGS = flags.FLAGS
|
||||||
flags.DEFINE_string('scheduler_driver',
|
flags.DEFINE_string('scheduler_driver',
|
||||||
@@ -66,3 +70,106 @@ class SchedulerManager(manager.Manager):
|
|||||||
{"method": method,
|
{"method": method,
|
||||||
"args": kwargs})
|
"args": kwargs})
|
||||||
logging.debug("Casting to %s %s for %s", topic, host, method)
|
logging.debug("Casting to %s %s for %s", topic, host, method)
|
||||||
|
|
||||||
|
# created by masumotok
|
||||||
|
def live_migration(self, context, ec2_id, dest):
|
||||||
|
""" live migration method"""
|
||||||
|
|
||||||
|
# 1. get instance id
|
||||||
|
internal_id = cloud.ec2_id_to_internal_id(ec2_id)
|
||||||
|
instance_ref = db.instance_get_by_internal_id(context, internal_id)
|
||||||
|
instance_id = instance_ref['id']
|
||||||
|
|
||||||
|
# 2. check dst host still has enough capacities
|
||||||
|
if not self.has_enough_resource(context, instance_id, dest):
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 3. change instance_state
|
||||||
|
db.instance_set_state(context,
|
||||||
|
instance_id,
|
||||||
|
power_state.PAUSED,
|
||||||
|
'migrating')
|
||||||
|
|
||||||
|
# 4. request live migration
|
||||||
|
host = instance_ref['host']
|
||||||
|
rpc.cast(context,
|
||||||
|
db.queue_get_for(context, FLAGS.compute_topic, host),
|
||||||
|
{"method": 'live_migration',
|
||||||
|
"args": {'instance_id': instance_id,
|
||||||
|
'dest': dest}})
|
||||||
|
return True
|
||||||
|
|
||||||
|
# this method is created by masumotok
|
||||||
|
def has_enough_resource(self, context, instance_id, dest):
|
||||||
|
|
||||||
|
# get instance information
|
||||||
|
instance_ref = db.instance_get(context, instance_id)
|
||||||
|
ec2_id = instance_ref['hostname']
|
||||||
|
vcpus = instance_ref['vcpus']
|
||||||
|
mem = instance_ref['memory_mb']
|
||||||
|
hdd = instance_ref['local_gb']
|
||||||
|
|
||||||
|
# get host information
|
||||||
|
host_ref = db.host_get_by_name(context, dest)
|
||||||
|
total_cpu = int(host_ref['cpu'])
|
||||||
|
total_mem = int(host_ref['memory_mb'])
|
||||||
|
total_hdd = int(host_ref['hdd_gb'])
|
||||||
|
|
||||||
|
instances_ref = db.instance_get_all_by_host(context, dest)
|
||||||
|
for i_ref in instances_ref:
|
||||||
|
total_cpu -= int(i_ref['vcpus'])
|
||||||
|
total_mem -= int(i_ref['memory_mb'])
|
||||||
|
total_hdd -= int(i_ref['local_gb'])
|
||||||
|
|
||||||
|
# check host has enough information
|
||||||
|
logging.debug('host(%s) remains vcpu:%s mem:%s hdd:%s,' %
|
||||||
|
(dest, total_cpu, total_mem, total_hdd))
|
||||||
|
logging.debug('instance(%s) has vcpu:%s mem:%s hdd:%s,' %
|
||||||
|
(ec2_id, total_cpu, total_mem, total_hdd))
|
||||||
|
|
||||||
|
if total_cpu <= vcpus or total_mem <= mem or total_hdd <= hdd:
|
||||||
|
logging.debug('%s doesnt have enough resource for %s' %
|
||||||
|
(dest, ec2_id))
|
||||||
|
return False
|
||||||
|
|
||||||
|
logging.debug('%s has enough resource for %s' % (dest, ec2_id))
|
||||||
|
return True
|
||||||
|
|
||||||
|
# this method is created by masumotok
|
||||||
|
def show_host_resource(self, context, host, *args):
|
||||||
|
""" show the physical/usage resource given by hosts."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
host_ref = db.host_get_by_name(context, host)
|
||||||
|
except exception.NotFound:
|
||||||
|
return {'ret': False, 'msg': 'No such Host'}
|
||||||
|
except:
|
||||||
|
raise
|
||||||
|
|
||||||
|
# get physical resource information
|
||||||
|
h_resource = {'cpu': host_ref['cpu'],
|
||||||
|
'memory_mb': host_ref['memory_mb'],
|
||||||
|
'hdd_gb': host_ref['hdd_gb']}
|
||||||
|
|
||||||
|
# get usage resource information
|
||||||
|
u_resource = {}
|
||||||
|
instances_ref = db.instance_get_all_by_host(context, host_ref['name'])
|
||||||
|
|
||||||
|
if 0 == len(instances_ref):
|
||||||
|
return {'ret': True, 'phy_resource': h_resource, 'usage': {}}
|
||||||
|
|
||||||
|
project_ids = [i['project_id'] for i in instances_ref]
|
||||||
|
project_ids = list(set(project_ids))
|
||||||
|
for p_id in project_ids:
|
||||||
|
cpu = db.instance_get_vcpu_sum_by_host_and_project(context,
|
||||||
|
host,
|
||||||
|
p_id)
|
||||||
|
mem = db.instance_get_memory_sum_by_host_and_project(context,
|
||||||
|
host,
|
||||||
|
p_id)
|
||||||
|
hdd = db.instance_get_disk_sum_by_host_and_project(context,
|
||||||
|
host,
|
||||||
|
p_id)
|
||||||
|
u_resource[p_id] = {'cpu': cpu, 'memory_mb': mem, 'hdd_gb': hdd}
|
||||||
|
|
||||||
|
return {'ret': True, 'phy_resource': h_resource, 'usage': u_resource}
|
||||||
|
|||||||
@@ -72,6 +72,14 @@ class Service(object, service.Service):
|
|||||||
self.manager.init_host()
|
self.manager.init_host()
|
||||||
self.model_disconnected = False
|
self.model_disconnected = False
|
||||||
ctxt = context.get_admin_context()
|
ctxt = context.get_admin_context()
|
||||||
|
|
||||||
|
# this try-except operations are added by masumotok
|
||||||
|
try:
|
||||||
|
host_ref = db.host_get_by_name(ctxt, self.host)
|
||||||
|
except exception.NotFound:
|
||||||
|
host_ref = db.host_create(ctxt, {'name': self.host})
|
||||||
|
host_ref = self._update_host_ref(ctxt, host_ref)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
service_ref = db.service_get_by_args(ctxt,
|
service_ref = db.service_get_by_args(ctxt,
|
||||||
self.host,
|
self.host,
|
||||||
@@ -109,6 +117,20 @@ class Service(object, service.Service):
|
|||||||
'report_count': 0})
|
'report_count': 0})
|
||||||
self.service_id = service_ref['id']
|
self.service_id = service_ref['id']
|
||||||
|
|
||||||
|
# created by masumotok
|
||||||
|
def _update_host_ref(self, context, host_ref):
|
||||||
|
|
||||||
|
if 0 <= self.manager_class_name.find('ComputeManager'):
|
||||||
|
cpu = self.manager.get_cpu_number()
|
||||||
|
memory_mb = self.manager.get_mem_size()
|
||||||
|
hdd_gb = self.manager.get_hdd_size()
|
||||||
|
db.host_update(context,
|
||||||
|
host_ref['id'],
|
||||||
|
{'cpu': cpu,
|
||||||
|
'memory_mb': memory_mb,
|
||||||
|
'hdd_gb': hdd_gb})
|
||||||
|
return host_ref
|
||||||
|
|
||||||
def __getattr__(self, key):
|
def __getattr__(self, key):
|
||||||
manager = self.__dict__.get('manager', None)
|
manager = self.__dict__.get('manager', None)
|
||||||
return getattr(manager, key)
|
return getattr(manager, key)
|
||||||
|
|||||||
@@ -133,9 +133,16 @@ def runthis(prompt, cmd, check_exit_code=True):
|
|||||||
|
|
||||||
|
|
||||||
def generate_uid(topic, size=8):
|
def generate_uid(topic, size=8):
|
||||||
characters = '01234567890abcdefghijklmnopqrstuvwxyz'
|
#modified by masumotok
|
||||||
choices = [random.choice(characters) for x in xrange(size)]
|
#characters = '01234567890abcdefghijklmnopqrstuvwxyz'
|
||||||
return '%s-%s' % (topic, ''.join(choices))
|
#choices = [random.choice(characters) for x in xrange(size)]
|
||||||
|
#return '%s-%s' % (topic, ''.join(choices))
|
||||||
|
if topic == "i":
|
||||||
|
return random.randint(0, 2 ** 28 - 1)
|
||||||
|
else:
|
||||||
|
characters = '01234567890abcdefghijklmnopqrstuvwxyz'
|
||||||
|
choices = [random.choice(characters) for x in xrange(size)]
|
||||||
|
return '%s-%s' % (topic, ''.join(choices))
|
||||||
|
|
||||||
|
|
||||||
def generate_mac():
|
def generate_mac():
|
||||||
|
|||||||
5
setup.py
5
setup.py
@@ -25,6 +25,7 @@ from sphinx.setup_command import BuildDoc
|
|||||||
|
|
||||||
from nova.utils import parse_mailmap, str_dict_replace
|
from nova.utils import parse_mailmap, str_dict_replace
|
||||||
|
|
||||||
|
|
||||||
class local_BuildDoc(BuildDoc):
|
class local_BuildDoc(BuildDoc):
|
||||||
def run(self):
|
def run(self):
|
||||||
for builder in ['html', 'man']:
|
for builder in ['html', 'man']:
|
||||||
@@ -54,8 +55,8 @@ setup(name='nova',
|
|||||||
author='OpenStack',
|
author='OpenStack',
|
||||||
author_email='nova@lists.launchpad.net',
|
author_email='nova@lists.launchpad.net',
|
||||||
url='http://www.openstack.org/',
|
url='http://www.openstack.org/',
|
||||||
cmdclass={ 'sdist': local_sdist,
|
cmdclass={'sdist': local_sdist,
|
||||||
'build_sphinx' : local_BuildDoc },
|
'build_sphinx': local_BuildDoc},
|
||||||
packages=find_packages(exclude=['bin', 'smoketests']),
|
packages=find_packages(exclude=['bin', 'smoketests']),
|
||||||
include_package_data=True,
|
include_package_data=True,
|
||||||
scripts=['bin/nova-api',
|
scripts=['bin/nova-api',
|
||||||
|
|||||||
Reference in New Issue
Block a user