Fixed based on reviewer's comment.
1. DB schema change vcpu/memory/hdd info were stored into Service table. but reviewer pointed out to me creating new table is better since Service table has too much columns. 2. Querying service table method Querying the compute-node recode from DB, several method were used to same purpose. Changed to use same method. 3. Removing unnecessary operation. FixedIP no longer have host column. I didnt find that, remove unnecessary operation from post_live_migration.. 4. Test code Modified testcode to fit following the above changes.
This commit is contained in:
49
.mailmap
49
.mailmap
@@ -1,36 +1,43 @@
|
||||
# Format is:
|
||||
# <preferred e-mail> <other e-mail>
|
||||
<code@term.ie> <github@anarkystic.com>
|
||||
<code@term.ie> <termie@preciousroy.local>
|
||||
<Armando.Migliaccio@eu.citrix.com> <armando.migliaccio@citrix.com>
|
||||
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
|
||||
<matt.dietz@rackspace.com> <mdietz@openstack>
|
||||
<cbehrens@codestud.com> <chris.behrens@rackspace.com>
|
||||
<devin.carlen@gmail.com> <devcamcar@illian.local>
|
||||
<ewan.mellor@citrix.com> <emellor@silver>
|
||||
<jaypipes@gmail.com> <jpipes@serialcoder>
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
||||
<anotherjesse@gmail.com> <jesse@dancelamb>
|
||||
<anotherjesse@gmail.com> <jesse@gigantor.local>
|
||||
<anotherjesse@gmail.com> <jesse@ubuntu>
|
||||
<jmckenty@gmail.com> <jmckenty@yyj-dhcp171.corp.flock.com>
|
||||
<ant@openstack.org> <amesserl@rackspace.com>
|
||||
<Armando.Migliaccio@eu.citrix.com> <armando.migliaccio@citrix.com>
|
||||
<brian.lamar@rackspace.com> <brian.lamar@gmail.com>
|
||||
<bschott@isi.edu> <bfschott@gmail.com>
|
||||
<cbehrens@codestud.com> <chris.behrens@rackspace.com>
|
||||
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
|
||||
<code@term.ie> <github@anarkystic.com>
|
||||
<code@term.ie> <termie@preciousroy.local>
|
||||
<corywright@gmail.com> <cory.wright@rackspace.com>
|
||||
<devin.carlen@gmail.com> <devcamcar@illian.local>
|
||||
<ewan.mellor@citrix.com> <emellor@silver>
|
||||
<jaypipes@gmail.com> <jpipes@serialcoder>
|
||||
<jmckenty@gmail.com> <jmckenty@joshua-mckentys-macbook-pro.local>
|
||||
<jmckenty@gmail.com> <jmckenty@yyj-dhcp171.corp.flock.com>
|
||||
<jmckenty@gmail.com> <joshua.mckenty@nasa.gov>
|
||||
<justin@fathomdb.com> <justinsb@justinsb-desktop>
|
||||
<masumotok@nttdata.co.jp> <root@openstack2-api>
|
||||
<justin@fathomdb.com> <superstack@superstack.org>
|
||||
<masumotok@nttdata.co.jp> Masumoto<masumotok@nttdata.co.jp>
|
||||
<masumotok@nttdata.co.jp> <root@openstack2-api>
|
||||
<matt.dietz@rackspace.com> <matthewdietz@Matthew-Dietzs-MacBook-Pro.local>
|
||||
<matt.dietz@rackspace.com> <mdietz@openstack>
|
||||
<mordred@inaugust.com> <mordred@hudson>
|
||||
<paul@openstack.org> <pvoccio@castor.local>
|
||||
<paul@openstack.org> <paul.voccio@rackspace.com>
|
||||
<paul@openstack.org> <pvoccio@castor.local>
|
||||
<rconradharris@gmail.com> <rick.harris@rackspace.com>
|
||||
<rlane@wikimedia.org> <laner@controller>
|
||||
<sleepsonthefloor@gmail.com> <root@tonbuntu>
|
||||
<soren.hansen@rackspace.com> <soren@linux2go.dk>
|
||||
<todd@ansolabs.com> <todd@lapex>
|
||||
<todd@ansolabs.com> <todd@rubidine.com>
|
||||
<vishvananda@gmail.com> <vishvananda@yahoo.com>
|
||||
<tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
|
||||
<ueno.nachi@lab.ntt.co.jp> <nati.ueno@gmail.com>
|
||||
<ueno.nachi@lab.ntt.co.jp> <nova@u4>
|
||||
<ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp>
|
||||
<vishvananda@gmail.com> <root@mirror.nasanebula.net>
|
||||
<vishvananda@gmail.com> <root@ubuntu>
|
||||
<sleepsonthefloor@gmail.com> <root@tonbuntu>
|
||||
<rlane@wikimedia.org> <laner@controller>
|
||||
<rconradharris@gmail.com> <rick.harris@rackspace.com>
|
||||
<corywright@gmail.com> <cory.wright@rackspace.com>
|
||||
<ant@openstack.org> <amesserl@rackspace.com>
|
||||
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
|
||||
<justin@fathomdb.com> <superstack@superstack.org>
|
||||
<vishvananda@gmail.com> <vishvananda@yahoo.com>
|
||||
|
11
Authors
11
Authors
@@ -4,13 +4,16 @@ Anthony Young <sleepsonthefloor@gmail.com>
|
||||
Antony Messerli <ant@openstack.org>
|
||||
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
||||
Bilal Akhtar <bilalakhtar@ubuntu.com>
|
||||
Brian Lamar <brian.lamar@rackspace.com>
|
||||
Brian Schott <bschott@isi.edu>
|
||||
Brian Waldon <brian.waldon@rackspace.com>
|
||||
Chiradeep Vittal <chiradeep@cloud.com>
|
||||
Chmouel Boudjnah <chmouel@chmouel.com>
|
||||
Chris Behrens <cbehrens@codestud.com>
|
||||
Christian Berendt <berendt@b1-systems.de>
|
||||
Cory Wright <corywright@gmail.com>
|
||||
David Pravec <David.Pravec@danix.org>
|
||||
Dan Prince <dan.prince@rackspace.com>
|
||||
David Pravec <David.Pravec@danix.org>
|
||||
Dean Troyer <dtroyer@gmail.com>
|
||||
Devin Carlen <devin.carlen@gmail.com>
|
||||
Ed Leafe <ed@leafe.com>
|
||||
@@ -41,7 +44,8 @@ Monsyne Dragon <mdragon@rackspace.com>
|
||||
Monty Taylor <mordred@inaugust.com>
|
||||
MORITA Kazutaka <morita.kazutaka@gmail.com>
|
||||
Muneyuki Noguchi <noguchimn@nttdata.co.jp>
|
||||
Nachi Ueno <ueno.nachi@lab.ntt.co.jp> <openstack@lab.ntt.co.jp> <nati.ueno@gmail.com> <nova@u4>
|
||||
Nachi Ueno <ueno.nachi@lab.ntt.co.jp>
|
||||
Naveed Massjouni <naveed.massjouni@rackspace.com>
|
||||
Paul Voccio <paul@openstack.org>
|
||||
Ricardo Carrillo Cruz <emaildericky@gmail.com>
|
||||
Rick Clark <rick@openstack.org>
|
||||
@@ -55,7 +59,8 @@ Soren Hansen <soren.hansen@rackspace.com>
|
||||
Thierry Carrez <thierry@openstack.org>
|
||||
Todd Willey <todd@ansolabs.com>
|
||||
Trey Morris <trey.morris@rackspace.com>
|
||||
Tushar Patil <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
|
||||
Tushar Patil <tushar.vitthal.patil@gmail.com>
|
||||
Vasiliy Shlykov <vash@vasiliyshlykov.org>
|
||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||
Zhixue Wu <Zhixue.Wu@citrix.com>
|
||||
|
19
HACKING
19
HACKING
@@ -47,3 +47,22 @@ Human Alphabetical Order Examples
|
||||
from nova.auth import users
|
||||
from nova.endpoint import api
|
||||
from nova.endpoint import cloud
|
||||
|
||||
Docstrings
|
||||
----------
|
||||
"""Summary of the function, class or method, less than 80 characters.
|
||||
|
||||
New paragraph after newline that explains in more detail any general
|
||||
information about the function, class or method. After this, if defining
|
||||
parameters and return types use the Sphinx format. After that an extra
|
||||
newline then close the quotations.
|
||||
|
||||
When writing the docstring for a class, an extra line should be placed
|
||||
after the closing quotations. For more in-depth explanations for these
|
||||
decisions see http://www.python.org/dev/peps/pep-0257/
|
||||
|
||||
:param foo: the foo parameter
|
||||
:param bar: the bar parameter
|
||||
:returns: description of the return value
|
||||
|
||||
"""
|
||||
|
10
MANIFEST.in
10
MANIFEST.in
@@ -6,14 +6,23 @@ graft doc
|
||||
graft smoketests
|
||||
graft tools
|
||||
graft etc
|
||||
graft bzrplugins
|
||||
graft contrib
|
||||
graft po
|
||||
graft plugins
|
||||
include nova/api/openstack/notes.txt
|
||||
include nova/auth/*.schema
|
||||
include nova/auth/novarc.template
|
||||
include nova/auth/opendj.sh
|
||||
include nova/auth/slap.sh
|
||||
include nova/cloudpipe/bootscript.sh
|
||||
include nova/cloudpipe/client.ovpn.template
|
||||
include nova/cloudpipe/bootscript.template
|
||||
include nova/compute/fakevirtinstance.xml
|
||||
include nova/compute/interfaces.template
|
||||
include nova/console/xvp.conf.template
|
||||
include nova/db/sqlalchemy/migrate_repo/migrate.cfg
|
||||
include nova/db/sqlalchemy/migrate_repo/README
|
||||
include nova/virt/interfaces.template
|
||||
include nova/virt/libvirt*.xml.template
|
||||
include nova/tests/CA/
|
||||
@@ -25,6 +34,7 @@ include nova/tests/bundle/1mb.manifest.xml
|
||||
include nova/tests/bundle/1mb.no_kernel_or_ramdisk.manifest.xml
|
||||
include nova/tests/bundle/1mb.part.0
|
||||
include nova/tests/bundle/1mb.part.1
|
||||
include nova/tests/db/nova.austin.sqlite
|
||||
include plugins/xenapi/README
|
||||
include plugins/xenapi/etc/xapi.d/plugins/objectstore
|
||||
include plugins/xenapi/etc/xapi.d/plugins/pluginlib_nova.py
|
||||
|
@@ -433,6 +433,37 @@ class ProjectCommands(object):
|
||||
"nova-api server on this host.")
|
||||
|
||||
|
||||
class FixedIpCommands(object):
|
||||
"""Class for managing fixed ip."""
|
||||
|
||||
def list(self, host=None):
|
||||
"""Lists all fixed ips (optionally by host) arguments: [host]"""
|
||||
ctxt = context.get_admin_context()
|
||||
if host == None:
|
||||
fixed_ips = db.fixed_ip_get_all(ctxt)
|
||||
else:
|
||||
fixed_ips = db.fixed_ip_get_all_by_host(ctxt, host)
|
||||
|
||||
print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (_('network'),
|
||||
_('IP address'),
|
||||
_('MAC address'),
|
||||
_('hostname'),
|
||||
_('host'))
|
||||
for fixed_ip in fixed_ips:
|
||||
hostname = None
|
||||
host = None
|
||||
mac_address = None
|
||||
if fixed_ip['instance']:
|
||||
instance = fixed_ip['instance']
|
||||
hostname = instance['hostname']
|
||||
host = instance['host']
|
||||
mac_address = instance['mac_address']
|
||||
print "%-18s\t%-15s\t%-17s\t%-15s\t%s" % (
|
||||
fixed_ip['network']['cidr'],
|
||||
fixed_ip['address'],
|
||||
mac_address, hostname, host)
|
||||
|
||||
|
||||
class FloatingIpCommands(object):
|
||||
"""Class for managing floating ip."""
|
||||
|
||||
@@ -472,8 +503,8 @@ class NetworkCommands(object):
|
||||
"""Class for managing networks."""
|
||||
|
||||
def create(self, fixed_range=None, num_networks=None,
|
||||
network_size=None, vlan_start=None, vpn_start=None,
|
||||
fixed_range_v6=None):
|
||||
network_size=None, vlan_start=None,
|
||||
vpn_start=None, fixed_range_v6=None, label='public'):
|
||||
"""Creates fixed ips for host by range
|
||||
arguments: [fixed_range=FLAG], [num_networks=FLAG],
|
||||
[network_size=FLAG], [vlan_start=FLAG],
|
||||
@@ -495,16 +526,29 @@ class NetworkCommands(object):
|
||||
cidr=fixed_range,
|
||||
num_networks=int(num_networks),
|
||||
network_size=int(network_size),
|
||||
cidr_v6=fixed_range_v6,
|
||||
vlan_start=int(vlan_start),
|
||||
vpn_start=int(vpn_start))
|
||||
vpn_start=int(vpn_start),
|
||||
cidr_v6=fixed_range_v6,
|
||||
label=label)
|
||||
|
||||
def list(self):
|
||||
"""List all created networks"""
|
||||
print "%-18s\t%-15s\t%-15s\t%-15s" % (_('network'),
|
||||
_('netmask'),
|
||||
_('start address'),
|
||||
'DNS')
|
||||
for network in db.network_get_all(context.get_admin_context()):
|
||||
print "%-18s\t%-15s\t%-15s\t%-15s" % (network.cidr,
|
||||
network.netmask,
|
||||
network.dhcp_start,
|
||||
network.dns)
|
||||
|
||||
|
||||
class InstanceCommands(object):
|
||||
"""Class for mangaging VM instances."""
|
||||
|
||||
def live_migration(self, ec2_id, dest):
|
||||
"""live_migration"""
|
||||
"""Migrates a running instance to a new machine."""
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
instance_id = ec2_id_to_id(ec2_id)
|
||||
@@ -513,8 +557,8 @@ class InstanceCommands(object):
|
||||
msg = _('Only KVM is supported for now. Sorry!')
|
||||
raise exception.Error(msg)
|
||||
|
||||
if FLAGS.volume_driver != 'nova.volume.driver.AOEDriver' and \
|
||||
FLAGS.volume_driver != 'nova.volume.driver.ISCSIDriver':
|
||||
if (FLAGS.volume_driver != 'nova.volume.driver.AOEDriver' and \
|
||||
FLAGS.volume_driver != 'nova.volume.driver.ISCSIDriver'):
|
||||
msg = _("Support only AOEDriver and ISCSIDriver. Sorry!")
|
||||
raise exception.Error(msg)
|
||||
|
||||
@@ -586,15 +630,14 @@ class ServiceCommands(object):
|
||||
# when this feture is included in API.
|
||||
if type(result) != dict:
|
||||
print 'Unexpected error occurs'
|
||||
elif not result['ret']:
|
||||
print '%s' % result['msg']
|
||||
print '[Result]', result
|
||||
else:
|
||||
cpu = result['phy_resource']['vcpus']
|
||||
mem = result['phy_resource']['memory_mb']
|
||||
hdd = result['phy_resource']['local_gb']
|
||||
cpu_u = result['phy_resource']['vcpus_used']
|
||||
mem_u = result['phy_resource']['memory_mb_used']
|
||||
hdd_u = result['phy_resource']['local_gb_used']
|
||||
cpu = result['resource']['vcpus']
|
||||
mem = result['resource']['memory_mb']
|
||||
hdd = result['resource']['local_gb']
|
||||
cpu_u = result['resource']['vcpus_used']
|
||||
mem_u = result['resource']['memory_mb_used']
|
||||
hdd_u = result['resource']['local_gb_used']
|
||||
|
||||
print 'HOST\t\t\tPROJECT\t\tcpu\tmem(mb)\tdisk(gb)'
|
||||
print '%s(total)\t\t\t%s\t%s\t%s' % (host, cpu, mem, hdd)
|
||||
@@ -657,6 +700,13 @@ class VolumeCommands(object):
|
||||
ctxt = context.get_admin_context()
|
||||
volume = db.volume_get(ctxt, param2id(volume_id))
|
||||
host = volume['host']
|
||||
|
||||
if not host:
|
||||
print "Volume not yet assigned to host."
|
||||
print "Deleting volume from database and skipping rpc."
|
||||
db.volume_destroy(ctxt, param2id(volume_id))
|
||||
return
|
||||
|
||||
if volume['status'] == 'in-use':
|
||||
print "Volume is in-use."
|
||||
print "Detach volume from instance and then try again."
|
||||
@@ -693,6 +743,7 @@ CATEGORIES = [
|
||||
('role', RoleCommands),
|
||||
('shell', ShellCommands),
|
||||
('vpn', VpnCommands),
|
||||
('fixed', FixedIpCommands),
|
||||
('floating', FloatingIpCommands),
|
||||
('network', NetworkCommands),
|
||||
('instance', InstanceCommands),
|
||||
|
@@ -1826,7 +1826,7 @@ msgstr ""
|
||||
|
||||
#: nova/virt/xenapi/vm_utils.py:290
|
||||
#, python-format
|
||||
msgid "PV Kernel in VDI:%d"
|
||||
msgid "PV Kernel in VDI:%s"
|
||||
msgstr ""
|
||||
|
||||
#: nova/virt/xenapi/vm_utils.py:318
|
||||
|
@@ -74,6 +74,25 @@ LOG = logging.getLogger("nova.ldapdriver")
|
||||
# in which we may want to change the interface a bit more.
|
||||
|
||||
|
||||
def _clean(attr):
|
||||
"""Clean attr for insertion into ldap"""
|
||||
if attr is None:
|
||||
return None
|
||||
if type(attr) is unicode:
|
||||
return str(attr)
|
||||
return attr
|
||||
|
||||
|
||||
def sanitize(fn):
|
||||
"""Decorator to sanitize all args"""
|
||||
def _wrapped(self, *args, **kwargs):
|
||||
args = [_clean(x) for x in args]
|
||||
kwargs = dict((k, _clean(v)) for (k, v) in kwargs)
|
||||
return fn(self, *args, **kwargs)
|
||||
_wrapped.func_name = fn.func_name
|
||||
return _wrapped
|
||||
|
||||
|
||||
class LdapDriver(object):
|
||||
"""Ldap Auth driver
|
||||
|
||||
@@ -106,23 +125,27 @@ class LdapDriver(object):
|
||||
self.conn.unbind_s()
|
||||
return False
|
||||
|
||||
@sanitize
|
||||
def get_user(self, uid):
|
||||
"""Retrieve user by id"""
|
||||
attr = self.__get_ldap_user(uid)
|
||||
return self.__to_user(attr)
|
||||
|
||||
@sanitize
|
||||
def get_user_from_access_key(self, access):
|
||||
"""Retrieve user by access key"""
|
||||
query = '(accessKey=%s)' % access
|
||||
dn = FLAGS.ldap_user_subtree
|
||||
return self.__to_user(self.__find_object(dn, query))
|
||||
|
||||
@sanitize
|
||||
def get_project(self, pid):
|
||||
"""Retrieve project by id"""
|
||||
dn = self.__project_to_dn(pid)
|
||||
attr = self.__find_object(dn, LdapDriver.project_pattern)
|
||||
return self.__to_project(attr)
|
||||
|
||||
@sanitize
|
||||
def get_users(self):
|
||||
"""Retrieve list of users"""
|
||||
attrs = self.__find_objects(FLAGS.ldap_user_subtree,
|
||||
@@ -134,6 +157,7 @@ class LdapDriver(object):
|
||||
users.append(user)
|
||||
return users
|
||||
|
||||
@sanitize
|
||||
def get_projects(self, uid=None):
|
||||
"""Retrieve list of projects"""
|
||||
pattern = LdapDriver.project_pattern
|
||||
@@ -143,6 +167,7 @@ class LdapDriver(object):
|
||||
pattern)
|
||||
return [self.__to_project(attr) for attr in attrs]
|
||||
|
||||
@sanitize
|
||||
def create_user(self, name, access_key, secret_key, is_admin):
|
||||
"""Create a user"""
|
||||
if self.__user_exists(name):
|
||||
@@ -196,6 +221,7 @@ class LdapDriver(object):
|
||||
self.conn.add_s(self.__uid_to_dn(name), attr)
|
||||
return self.__to_user(dict(attr))
|
||||
|
||||
@sanitize
|
||||
def create_project(self, name, manager_uid,
|
||||
description=None, member_uids=None):
|
||||
"""Create a project"""
|
||||
@@ -231,6 +257,7 @@ class LdapDriver(object):
|
||||
self.conn.add_s(dn, attr)
|
||||
return self.__to_project(dict(attr))
|
||||
|
||||
@sanitize
|
||||
def modify_project(self, project_id, manager_uid=None, description=None):
|
||||
"""Modify an existing project"""
|
||||
if not manager_uid and not description:
|
||||
@@ -249,21 +276,25 @@ class LdapDriver(object):
|
||||
dn = self.__project_to_dn(project_id)
|
||||
self.conn.modify_s(dn, attr)
|
||||
|
||||
@sanitize
|
||||
def add_to_project(self, uid, project_id):
|
||||
"""Add user to project"""
|
||||
dn = self.__project_to_dn(project_id)
|
||||
return self.__add_to_group(uid, dn)
|
||||
|
||||
@sanitize
|
||||
def remove_from_project(self, uid, project_id):
|
||||
"""Remove user from project"""
|
||||
dn = self.__project_to_dn(project_id)
|
||||
return self.__remove_from_group(uid, dn)
|
||||
|
||||
@sanitize
|
||||
def is_in_project(self, uid, project_id):
|
||||
"""Check if user is in project"""
|
||||
dn = self.__project_to_dn(project_id)
|
||||
return self.__is_in_group(uid, dn)
|
||||
|
||||
@sanitize
|
||||
def has_role(self, uid, role, project_id=None):
|
||||
"""Check if user has role
|
||||
|
||||
@@ -273,6 +304,7 @@ class LdapDriver(object):
|
||||
role_dn = self.__role_to_dn(role, project_id)
|
||||
return self.__is_in_group(uid, role_dn)
|
||||
|
||||
@sanitize
|
||||
def add_role(self, uid, role, project_id=None):
|
||||
"""Add role for user (or user and project)"""
|
||||
role_dn = self.__role_to_dn(role, project_id)
|
||||
@@ -283,11 +315,13 @@ class LdapDriver(object):
|
||||
else:
|
||||
return self.__add_to_group(uid, role_dn)
|
||||
|
||||
@sanitize
|
||||
def remove_role(self, uid, role, project_id=None):
|
||||
"""Remove role for user (or user and project)"""
|
||||
role_dn = self.__role_to_dn(role, project_id)
|
||||
return self.__remove_from_group(uid, role_dn)
|
||||
|
||||
@sanitize
|
||||
def get_user_roles(self, uid, project_id=None):
|
||||
"""Retrieve list of roles for user (or user and project)"""
|
||||
if project_id is None:
|
||||
@@ -307,6 +341,7 @@ class LdapDriver(object):
|
||||
roles = self.__find_objects(project_dn, query)
|
||||
return [role['cn'][0] for role in roles]
|
||||
|
||||
@sanitize
|
||||
def delete_user(self, uid):
|
||||
"""Delete a user"""
|
||||
if not self.__user_exists(uid):
|
||||
@@ -332,12 +367,14 @@ class LdapDriver(object):
|
||||
# Delete entry
|
||||
self.conn.delete_s(self.__uid_to_dn(uid))
|
||||
|
||||
@sanitize
|
||||
def delete_project(self, project_id):
|
||||
"""Delete a project"""
|
||||
project_dn = self.__project_to_dn(project_id)
|
||||
self.__delete_roles(project_dn)
|
||||
self.__delete_group(project_dn)
|
||||
|
||||
@sanitize
|
||||
def modify_user(self, uid, access_key=None, secret_key=None, admin=None):
|
||||
"""Modify an existing user"""
|
||||
if not access_key and not secret_key and admin is None:
|
||||
|
@@ -10,7 +10,6 @@ export NOVA_CERT=${NOVA_KEY_DIR}/%(nova)s
|
||||
export EUCALYPTUS_CERT=${NOVA_CERT} # euca-bundle-image seems to require this set
|
||||
alias ec2-bundle-image="ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 42 --ec2cert ${NOVA_CERT}"
|
||||
alias ec2-upload-bundle="ec2-upload-bundle -a ${EC2_ACCESS_KEY} -s ${EC2_SECRET_KEY} --url ${S3_URL} --ec2cert ${NOVA_CERT}"
|
||||
export CLOUD_SERVERS_API_KEY="%(access)s"
|
||||
export CLOUD_SERVERS_USERNAME="%(user)s"
|
||||
export CLOUD_SERVERS_URL="%(os)s"
|
||||
|
||||
export NOVA_API_KEY="%(access)s"
|
||||
export NOVA_USERNAME="%(user)s"
|
||||
export NOVA_URL="%(os)s"
|
||||
|
@@ -282,6 +282,8 @@ DEFINE_integer('auth_token_ttl', 3600, 'Seconds for auth tokens to linger')
|
||||
|
||||
DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
|
||||
"Top-level directory for maintaining nova's state")
|
||||
DEFINE_string('logdir', None, 'output to a per-service log file in named '
|
||||
'directory')
|
||||
|
||||
DEFINE_string('sql_connection',
|
||||
'sqlite:///$state_path/nova.sqlite',
|
||||
|
21
nova/log.py
21
nova/log.py
@@ -28,9 +28,11 @@ It also allows setting of formatting information through flags.
|
||||
|
||||
|
||||
import cStringIO
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import logging.handlers
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
@@ -92,7 +94,7 @@ critical = logging.critical
|
||||
log = logging.log
|
||||
# handlers
|
||||
StreamHandler = logging.StreamHandler
|
||||
FileHandler = logging.FileHandler
|
||||
WatchedFileHandler = logging.handlers.WatchedFileHandler
|
||||
# logging.SysLogHandler is nicer than logging.logging.handler.SysLogHandler.
|
||||
SysLogHandler = logging.handlers.SysLogHandler
|
||||
|
||||
@@ -111,6 +113,18 @@ def _dictify_context(context):
|
||||
return context
|
||||
|
||||
|
||||
def _get_binary_name():
|
||||
return os.path.basename(inspect.stack()[-1][1])
|
||||
|
||||
|
||||
def get_log_file_path(binary=None):
|
||||
if FLAGS.logfile:
|
||||
return FLAGS.logfile
|
||||
if FLAGS.logdir:
|
||||
binary = binary or _get_binary_name()
|
||||
return '%s.log' % (os.path.join(FLAGS.logdir, binary),)
|
||||
|
||||
|
||||
def basicConfig():
|
||||
logging.basicConfig()
|
||||
for handler in logging.root.handlers:
|
||||
@@ -123,8 +137,9 @@ def basicConfig():
|
||||
syslog = SysLogHandler(address='/dev/log')
|
||||
syslog.setFormatter(_formatter)
|
||||
logging.root.addHandler(syslog)
|
||||
if FLAGS.logfile:
|
||||
logfile = FileHandler(FLAGS.logfile)
|
||||
logpath = get_log_file_path()
|
||||
if logpath:
|
||||
logfile = WatchedFileHandler(logpath)
|
||||
logfile.setFormatter(_formatter)
|
||||
logging.root.addHandler(logfile)
|
||||
|
||||
|
@@ -29,6 +29,7 @@ import uuid
|
||||
|
||||
from carrot import connection as carrot_connection
|
||||
from carrot import messaging
|
||||
from eventlet import greenpool
|
||||
from eventlet import greenthread
|
||||
|
||||
from nova import context
|
||||
@@ -42,6 +43,8 @@ from nova import utils
|
||||
FLAGS = flags.FLAGS
|
||||
LOG = logging.getLogger('nova.rpc')
|
||||
|
||||
flags.DEFINE_integer('rpc_thread_pool_size', 1024, 'Size of RPC thread pool')
|
||||
|
||||
|
||||
class Connection(carrot_connection.BrokerConnection):
|
||||
"""Connection instance object"""
|
||||
@@ -155,11 +158,15 @@ class AdapterConsumer(TopicConsumer):
|
||||
def __init__(self, connection=None, topic="broadcast", proxy=None):
|
||||
LOG.debug(_('Initing the Adapter Consumer for %s') % topic)
|
||||
self.proxy = proxy
|
||||
self.pool = greenpool.GreenPool(FLAGS.rpc_thread_pool_size)
|
||||
super(AdapterConsumer, self).__init__(connection=connection,
|
||||
topic=topic)
|
||||
|
||||
def receive(self, *args, **kwargs):
|
||||
self.pool.spawn_n(self._receive, *args, **kwargs)
|
||||
|
||||
@exception.wrap_exception
|
||||
def receive(self, message_data, message):
|
||||
def _receive(self, message_data, message):
|
||||
"""Magically looks for a method on the proxy object and calls it
|
||||
|
||||
Message data should be a dictionary with two keys:
|
||||
|
@@ -119,11 +119,12 @@ class Scheduler(object):
|
||||
msg = _('volume node is not alive(time synchronize problem?)')
|
||||
raise exception.Invalid(msg)
|
||||
|
||||
# Checking src host is alive.
|
||||
# Checking src host exists and compute node
|
||||
src = instance_ref['host']
|
||||
services = db.service_get_all_by_topic(context, 'compute')
|
||||
services = [service for service in services if service.host == src]
|
||||
if len(services) < 1 or not self.service_is_up(services[0]):
|
||||
services = db.service_get_all_compute_by_host(context, src)
|
||||
|
||||
# Checking src host is alive.
|
||||
if not self.service_is_up(services[0]):
|
||||
msg = _('%s is not alive(time synchronize problem?)')
|
||||
raise exception.Invalid(msg % src)
|
||||
|
||||
@@ -131,15 +132,8 @@ class Scheduler(object):
|
||||
"""Live migration check routine (for destination host)"""
|
||||
|
||||
# Checking dest exists and compute node.
|
||||
dservice_refs = db.service_get_all_by_host(context, dest)
|
||||
if len(dservice_refs) <= 0:
|
||||
msg = _('%s does not exists.')
|
||||
raise exception.Invalid(msg % dest)
|
||||
|
||||
dservice_refs = db.service_get_all_compute_by_host(context, dest)
|
||||
dservice_ref = dservice_refs[0]
|
||||
if dservice_ref['topic'] != 'compute':
|
||||
msg = _('%s must be compute node')
|
||||
raise exception.Invalid(msg % dest)
|
||||
|
||||
# Checking dest host is alive.
|
||||
if not self.service_is_up(dservice_ref):
|
||||
@@ -169,18 +163,18 @@ class Scheduler(object):
|
||||
self.mounted_on_same_shared_storage(context, instance_ref, dest)
|
||||
|
||||
# Checking dest exists.
|
||||
dservice_refs = db.service_get_all_by_host(context, dest)
|
||||
if len(dservice_refs) <= 0:
|
||||
raise exception.Invalid(_('%s does not exists.') % dest)
|
||||
dservice_ref = dservice_refs[0]
|
||||
dservice_refs = db.service_get_all_compute_by_host(context, dest)
|
||||
dservice_ref = dservice_refs[0]['compute_service'][0]
|
||||
|
||||
# Checking original host( where instance was launched at) exists.
|
||||
oservice_refs = db.service_get_all_by_host(context,
|
||||
try:
|
||||
oservice_refs = \
|
||||
db.service_get_all_compute_by_host(context,
|
||||
instance_ref['launched_on'])
|
||||
if len(oservice_refs) <= 0:
|
||||
except exception.NotFound:
|
||||
msg = _('%s(where instance was launched at) does not exists.')
|
||||
raise exception.Invalid(msg % instance_ref['launched_on'])
|
||||
oservice_ref = oservice_refs[0]
|
||||
oservice_ref = oservice_refs[0]['compute_service'][0]
|
||||
|
||||
# Checking hypervisor is same.
|
||||
o = oservice_ref['hypervisor_type']
|
||||
@@ -223,13 +217,11 @@ class Scheduler(object):
|
||||
ec2_id = instance_ref['hostname']
|
||||
|
||||
# Getting host information
|
||||
service_refs = db.service_get_all_by_host(context, dest)
|
||||
if len(service_refs) <= 0:
|
||||
raise exception.Invalid(_('%s does not exists.') % dest)
|
||||
service_ref = service_refs[0]
|
||||
service_refs = db.service_get_all_compute_by_host(context, dest)
|
||||
compute_service_ref = service_refs[0]['compute_service'][0]
|
||||
|
||||
mem_total = int(service_ref['memory_mb'])
|
||||
mem_used = int(service_ref['memory_mb_used'])
|
||||
mem_total = int(compute_service_ref['memory_mb'])
|
||||
mem_used = int(compute_service_ref['memory_mb_used'])
|
||||
mem_avail = mem_total - mem_used
|
||||
mem_inst = instance_ref['memory_mb']
|
||||
if mem_avail <= mem_inst:
|
||||
|
@@ -74,30 +74,26 @@ class SchedulerManager(manager.Manager):
|
||||
def show_host_resource(self, context, host, *args):
|
||||
"""show the physical/usage resource given by hosts."""
|
||||
|
||||
compute_refs = db.service_get_all_compute_sorted(context)
|
||||
compute_refs = [s for s, v in compute_refs if s['host'] == host]
|
||||
if 0 == len(compute_refs):
|
||||
return {'ret': False, 'msg': 'No such Host or not compute node.'}
|
||||
compute_ref = db.service_get_all_compute_by_host(context, host)
|
||||
compute_ref = compute_ref[0]
|
||||
|
||||
# Getting physical resource information
|
||||
h_resource = {'vcpus': compute_refs[0]['vcpus'],
|
||||
'memory_mb': compute_refs[0]['memory_mb'],
|
||||
'local_gb': compute_refs[0]['local_gb'],
|
||||
'vcpus_used': compute_refs[0]['vcpus_used'],
|
||||
'memory_mb_used': compute_refs[0]['memory_mb_used'],
|
||||
'local_gb_used': compute_refs[0]['local_gb_used']}
|
||||
compute_service_ref = compute_ref['compute_service'][0]
|
||||
resource = {'vcpus': compute_service_ref['vcpus'],
|
||||
'memory_mb': compute_service_ref['memory_mb'],
|
||||
'local_gb': compute_service_ref['local_gb'],
|
||||
'vcpus_used': compute_service_ref['vcpus_used'],
|
||||
'memory_mb_used': compute_service_ref['memory_mb_used'],
|
||||
'local_gb_used': compute_service_ref['local_gb_used']}
|
||||
|
||||
# Getting usage resource information
|
||||
u_resource = {}
|
||||
instances_refs = db.instance_get_all_by_host(context,
|
||||
compute_refs[0]['host'])
|
||||
usage = {}
|
||||
instance_refs = db.instance_get_all_by_host(context,
|
||||
compute_ref['host'])
|
||||
if 0 == len(instance_refs):
|
||||
return {'resource': resource, 'usage': usage}
|
||||
|
||||
if 0 == len(instances_refs):
|
||||
return {'ret': True,
|
||||
'phy_resource': h_resource,
|
||||
'usage': u_resource}
|
||||
|
||||
project_ids = [i['project_id'] for i in instances_refs]
|
||||
project_ids = [i['project_id'] for i in instance_refs]
|
||||
project_ids = list(set(project_ids))
|
||||
for i in project_ids:
|
||||
vcpus = db.instance_get_vcpu_sum_by_host_and_project(context,
|
||||
@@ -109,8 +105,8 @@ class SchedulerManager(manager.Manager):
|
||||
hdd = db.instance_get_disk_sum_by_host_and_project(context,
|
||||
host,
|
||||
i)
|
||||
u_resource[i] = {'vcpus': int(vcpus),
|
||||
'memory_mb': int(mem),
|
||||
'local_gb': int(hdd)}
|
||||
usage[i] = {'vcpus': int(vcpus),
|
||||
'memory_mb': int(mem),
|
||||
'local_gb': int(hdd)}
|
||||
|
||||
return {'ret': True, 'phy_resource': h_resource, 'usage': u_resource}
|
||||
return {'resource': resource, 'usage': usage}
|
||||
|
@@ -248,16 +248,14 @@ class ApiEc2TestCase(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rv = self.ec2.get_all_security_groups()
|
||||
# I don't bother checkng that we actually find it here,
|
||||
# because the create/delete unit test further up should
|
||||
# be good enough for that.
|
||||
for group in rv:
|
||||
if group.name == security_group_name:
|
||||
self.assertEquals(len(group.rules), 1)
|
||||
self.assertEquals(int(group.rules[0].from_port), 80)
|
||||
self.assertEquals(int(group.rules[0].to_port), 81)
|
||||
self.assertEquals(len(group.rules[0].grants), 1)
|
||||
self.assertEquals(str(group.rules[0].grants[0]), '0.0.0.0/0')
|
||||
|
||||
group = [grp for grp in rv if grp.name == security_group_name][0]
|
||||
|
||||
self.assertEquals(len(group.rules), 1)
|
||||
self.assertEquals(int(group.rules[0].from_port), 80)
|
||||
self.assertEquals(int(group.rules[0].to_port), 81)
|
||||
self.assertEquals(len(group.rules[0].grants), 1)
|
||||
self.assertEquals(str(group.rules[0].grants[0]), '0.0.0.0/0')
|
||||
|
||||
self.expect_http()
|
||||
self.mox.ReplayAll()
|
||||
@@ -314,16 +312,13 @@ class ApiEc2TestCase(test.TestCase):
|
||||
self.mox.ReplayAll()
|
||||
|
||||
rv = self.ec2.get_all_security_groups()
|
||||
# I don't bother checkng that we actually find it here,
|
||||
# because the create/delete unit test further up should
|
||||
# be good enough for that.
|
||||
for group in rv:
|
||||
if group.name == security_group_name:
|
||||
self.assertEquals(len(group.rules), 1)
|
||||
self.assertEquals(int(group.rules[0].from_port), 80)
|
||||
self.assertEquals(int(group.rules[0].to_port), 81)
|
||||
self.assertEquals(len(group.rules[0].grants), 1)
|
||||
self.assertEquals(str(group.rules[0].grants[0]), '::/0')
|
||||
|
||||
group = [grp for grp in rv if grp.name == security_group_name][0]
|
||||
self.assertEquals(len(group.rules), 1)
|
||||
self.assertEquals(int(group.rules[0].from_port), 80)
|
||||
self.assertEquals(int(group.rules[0].to_port), 81)
|
||||
self.assertEquals(len(group.rules[0].grants), 1)
|
||||
self.assertEquals(str(group.rules[0].grants[0]), '::/0')
|
||||
|
||||
self.expect_http()
|
||||
self.mox.ReplayAll()
|
||||
|
@@ -243,6 +243,14 @@ class ComputeTestCase(test.TestCase):
|
||||
self.compute.set_admin_password(self.context, instance_id)
|
||||
self.compute.terminate_instance(self.context, instance_id)
|
||||
|
||||
def test_inject_file(self):
|
||||
"""Ensure we can write a file to an instance"""
|
||||
instance_id = self._create_instance()
|
||||
self.compute.run_instance(self.context, instance_id)
|
||||
self.compute.inject_file(self.context, instance_id, "/tmp/test",
|
||||
"File Contents")
|
||||
self.compute.terminate_instance(self.context, instance_id)
|
||||
|
||||
def test_snapshot(self):
|
||||
"""Ensure instance can be snapshotted"""
|
||||
instance_id = self._create_instance()
|
||||
@@ -476,7 +484,8 @@ class ComputeTestCase(test.TestCase):
|
||||
'state': power_state.RUNNING,
|
||||
'host': i_ref['host']})
|
||||
for v in i_ref['volumes']:
|
||||
dbmock.volume_update(c, v['id'], {'status': 'in-use'})
|
||||
dbmock.volume_update(c, v['id'], {'status': 'in-use',
|
||||
'host': i_ref['host']})
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.mox.ReplayAll()
|
||||
@@ -541,14 +550,25 @@ class ComputeTestCase(test.TestCase):
|
||||
def test_post_live_migration_working_correctly(self):
|
||||
"""post_live_migration works as expected correctly """
|
||||
|
||||
i_ref = self._get_dummy_instance()
|
||||
fixed_ip_ref = {'id': 1, 'address': '1.1.1.1'}
|
||||
floating_ip_ref = {'id': 1, 'address': '2.2.2.2'}
|
||||
c = context.get_admin_context()
|
||||
dest = 'desthost'
|
||||
flo_addr = '1.2.1.2'
|
||||
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
dbmock.volume_get_all_by_instance(c, i_ref['id']).\
|
||||
AndReturn(i_ref['volumes'])
|
||||
# Preparing datas
|
||||
c = context.get_admin_context()
|
||||
instance_id = self._create_instance()
|
||||
i_ref = db.instance_get(c, instance_id)
|
||||
db.instance_update(c, i_ref['id'], {'state_description': 'migrating',
|
||||
'state': power_state.PAUSED})
|
||||
v_ref = db.volume_create(c, {'size': 1, 'instance_id': instance_id})
|
||||
fix_addr = db.fixed_ip_create(c, {'address': '1.1.1.1',
|
||||
'instance_id': instance_id})
|
||||
fix_ref = db.fixed_ip_get_by_address(c, fix_addr)
|
||||
flo_ref = db.floating_ip_create(c, {'address': flo_addr,
|
||||
'fixed_ip_id': fix_ref['id']})
|
||||
# reload is necessary before setting mocks
|
||||
i_ref = db.instance_get(c, instance_id)
|
||||
|
||||
# Preparing mocks
|
||||
self.mox.StubOutWithMock(self.compute.volume_manager,
|
||||
'remove_compute_volume')
|
||||
for v in i_ref['volumes']:
|
||||
@@ -556,102 +576,22 @@ class ComputeTestCase(test.TestCase):
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
||||
self.compute.driver.unfilter_instance(i_ref)
|
||||
|
||||
fixed_ip = fixed_ip_ref['address']
|
||||
dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn(fixed_ip)
|
||||
dbmock.fixed_ip_update(c, fixed_ip, {'host': i_ref['host']})
|
||||
|
||||
fl_ip = floating_ip_ref['address']
|
||||
dbmock.instance_get_floating_address(c, i_ref['id']).AndReturn(fl_ip)
|
||||
dbmock.floating_ip_get_by_address(c, fl_ip).AndReturn(floating_ip_ref)
|
||||
dbmock.floating_ip_update(c, floating_ip_ref['address'],
|
||||
{'host': i_ref['host']})
|
||||
dbmock.instance_update(c, i_ref['id'],
|
||||
{'state_description': 'running',
|
||||
'state': power_state.RUNNING,
|
||||
'host': i_ref['host']})
|
||||
for v in i_ref['volumes']:
|
||||
dbmock.volume_update(c, v['id'], {'status': 'in-use'})
|
||||
|
||||
self.compute.db = dbmock
|
||||
# executing
|
||||
self.mox.ReplayAll()
|
||||
ret = self.compute.post_live_migration(c, i_ref, i_ref['host'])
|
||||
self.assertEqual(ret, None)
|
||||
self.mox.ResetAll()
|
||||
ret = self.compute.post_live_migration(c, i_ref, dest)
|
||||
self.mox.UnsetStubs()
|
||||
|
||||
def test_post_live_migration_no_floating_ip(self):
|
||||
"""
|
||||
post_live_migration works as expected correctly
|
||||
(in case instance doesnt have floaitng ip)
|
||||
"""
|
||||
i_ref = self._get_dummy_instance()
|
||||
i_ref.__setitem__('volumes', [])
|
||||
fixed_ip_ref = {'id': 1, 'address': '1.1.1.1'}
|
||||
floating_ip_ref = {'id': 1, 'address': '1.1.1.1'}
|
||||
c = context.get_admin_context()
|
||||
# make sure every data is rewritten to dest
|
||||
i_ref = db.instance_get(c, i_ref['id'])
|
||||
c1 = (i_ref['host'] == dest)
|
||||
v_ref = db.volume_get(c, v_ref['id'])
|
||||
c2 = (v_ref['host'] == dest)
|
||||
c3 = False
|
||||
flo_refs = db.floating_ip_get_all_by_host(c, dest)
|
||||
c3 = (len(flo_refs) != 0 and flo_refs[0]['address'] == flo_addr)
|
||||
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
dbmock.volume_get_all_by_instance(c, i_ref['id']).AndReturn([])
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
||||
self.compute.driver.unfilter_instance(i_ref)
|
||||
|
||||
fixed_ip = fixed_ip_ref['address']
|
||||
dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn(fixed_ip)
|
||||
dbmock.fixed_ip_update(c, fixed_ip, {'host': i_ref['host']})
|
||||
|
||||
dbmock.instance_get_floating_address(c, i_ref['id']).AndReturn(None)
|
||||
dbmock.instance_update(c, i_ref['id'],
|
||||
{'state_description': 'running',
|
||||
'state': power_state.RUNNING,
|
||||
'host': i_ref['host']})
|
||||
for v in i_ref['volumes']:
|
||||
dbmock.volume_update(c, v['id'], {'status': 'in-use'})
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.mox.ReplayAll()
|
||||
ret = self.compute.post_live_migration(c, i_ref, i_ref['host'])
|
||||
self.assertEqual(ret, None)
|
||||
self.mox.ResetAll()
|
||||
|
||||
def test_post_live_migration_no_floating_ip_with_exception(self):
|
||||
"""
|
||||
post_live_migration works as expected correctly
|
||||
(in case instance doesnt have floaitng ip, and raise exception)
|
||||
"""
|
||||
i_ref = self._get_dummy_instance()
|
||||
i_ref.__setitem__('volumes', [])
|
||||
fixed_ip_ref = {'id': 1, 'address': '1.1.1.1'}
|
||||
floating_ip_ref = {'id': 1, 'address': '1.1.1.1'}
|
||||
c = context.get_admin_context()
|
||||
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
dbmock.volume_get_all_by_instance(c, i_ref['id']).AndReturn([])
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
||||
self.compute.driver.unfilter_instance(i_ref)
|
||||
|
||||
fixed_ip = fixed_ip_ref['address']
|
||||
dbmock.instance_get_fixed_address(c, i_ref['id']).AndReturn(fixed_ip)
|
||||
dbmock.fixed_ip_update(c, fixed_ip, {'host': i_ref['host']})
|
||||
dbmock.instance_get_floating_address(c, i_ref['id']).\
|
||||
AndRaise(exception.NotFound())
|
||||
|
||||
self.mox.StubOutWithMock(compute_manager.LOG, 'info')
|
||||
compute_manager.LOG.info(_('post_live_migration() is started..'))
|
||||
compute_manager.LOG.info(_('floating_ip is not found for %s'),
|
||||
i_ref.name)
|
||||
# first 2 messages are checked.
|
||||
compute_manager.LOG.info(mox.IgnoreArg())
|
||||
compute_manager.LOG.info(mox.IgnoreArg())
|
||||
|
||||
self.mox.StubOutWithMock(db, 'instance_update')
|
||||
dbmock.instance_update(c, i_ref['id'], {'state_description': 'running',
|
||||
'state': power_state.RUNNING,
|
||||
'host': i_ref['host']})
|
||||
self.mox.StubOutWithMock(db, 'volume_update')
|
||||
for v in i_ref['volumes']:
|
||||
dbmock.volume_update(c, v['id'], {'status': 'in-use'})
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.mox.ReplayAll()
|
||||
ret = self.compute.post_live_migration(c, i_ref, i_ref['host'])
|
||||
self.assertEqual(ret, None)
|
||||
self.mox.ResetAll()
|
||||
# post operaton
|
||||
self.assertTrue(c1 and c2 and c3)
|
||||
db.instance_destroy(c, instance_id)
|
||||
db.volume_destroy(c, v_ref['id'])
|
||||
db.floating_ip_destroy(c, flo_addr)
|
||||
|
@@ -46,6 +46,27 @@ class RootLoggerTestCase(test.TestCase):
|
||||
self.assert_(True) # didn't raise exception
|
||||
|
||||
|
||||
class LogHandlerTestCase(test.TestCase):
|
||||
def test_log_path_logdir(self):
|
||||
self.flags(logdir='/some/path')
|
||||
self.assertEquals(log.get_log_file_path(binary='foo-bar'),
|
||||
'/some/path/foo-bar.log')
|
||||
|
||||
def test_log_path_logfile(self):
|
||||
self.flags(logfile='/some/path/foo-bar.log')
|
||||
self.assertEquals(log.get_log_file_path(binary='foo-bar'),
|
||||
'/some/path/foo-bar.log')
|
||||
|
||||
def test_log_path_none(self):
|
||||
self.assertTrue(log.get_log_file_path(binary='foo-bar') is None)
|
||||
|
||||
def test_log_path_logfile_overrides_logdir(self):
|
||||
self.flags(logdir='/some/other/path',
|
||||
logfile='/some/path/foo-bar.log')
|
||||
self.assertEquals(log.get_log_file_path(binary='foo-bar'),
|
||||
'/some/path/foo-bar.log')
|
||||
|
||||
|
||||
class NovaFormatterTestCase(test.TestCase):
|
||||
def setUp(self):
|
||||
super(NovaFormatterTestCase, self).setUp()
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@ from nova.virt import xenapi_conn
|
||||
from nova.virt.xenapi import fake as xenapi_fake
|
||||
from nova.virt.xenapi import volume_utils
|
||||
from nova.virt.xenapi.vmops import SimpleDH
|
||||
from nova.virt.xenapi.vmops import VMOps
|
||||
from nova.tests.db import fakes as db_fakes
|
||||
from nova.tests.xenapi import stubs
|
||||
from nova.tests.glance import stubs as glance_stubs
|
||||
@@ -141,6 +142,10 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
self.stubs.UnsetAll()
|
||||
|
||||
|
||||
def reset_network(*args):
|
||||
pass
|
||||
|
||||
|
||||
class XenAPIVMTestCase(test.TestCase):
|
||||
"""
|
||||
Unit tests for VM operations
|
||||
@@ -162,6 +167,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
|
||||
stubs.stubout_get_this_vm_uuid(self.stubs)
|
||||
stubs.stubout_stream_disk(self.stubs)
|
||||
self.stubs.Set(VMOps, 'reset_network', reset_network)
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
glance_stubs.FakeGlance)
|
||||
self.conn = xenapi_conn.get_connection(False)
|
||||
@@ -243,7 +249,8 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
# Check that the VM is running according to XenAPI.
|
||||
self.assertEquals(vm['power_state'], 'Running')
|
||||
|
||||
def _test_spawn(self, image_id, kernel_id, ramdisk_id):
|
||||
def _test_spawn(self, image_id, kernel_id, ramdisk_id,
|
||||
instance_type="m1.large"):
|
||||
stubs.stubout_session(self.stubs, stubs.FakeSessionForVMTests)
|
||||
values = {'name': 1,
|
||||
'id': 1,
|
||||
@@ -252,7 +259,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
'image_id': image_id,
|
||||
'kernel_id': kernel_id,
|
||||
'ramdisk_id': ramdisk_id,
|
||||
'instance_type': 'm1.large',
|
||||
'instance_type': instance_type,
|
||||
'mac_address': 'aa:bb:cc:dd:ee:ff',
|
||||
}
|
||||
conn = xenapi_conn.get_connection(False)
|
||||
@@ -260,6 +267,12 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
conn.spawn(instance)
|
||||
self.check_vm_record(conn)
|
||||
|
||||
def test_spawn_not_enough_memory(self):
|
||||
FLAGS.xenapi_image_service = 'glance'
|
||||
self.assertRaises(Exception,
|
||||
self._test_spawn,
|
||||
1, 2, 3, "m1.xlarge")
|
||||
|
||||
def test_spawn_raw_objectstore(self):
|
||||
FLAGS.xenapi_image_service = 'objectstore'
|
||||
self._test_spawn(1, None, None)
|
||||
|
@@ -43,8 +43,6 @@ else:
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_string('logdir', None, 'directory to keep log files in '
|
||||
'(will be prepended to $logfile)')
|
||||
|
||||
|
||||
class TwistdServerOptions(ServerOptions):
|
||||
|
@@ -20,13 +20,14 @@
|
||||
System-level utilities and helper functions.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import datetime
|
||||
import inspect
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import subprocess
|
||||
import socket
|
||||
import string
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
@@ -36,6 +37,7 @@ import netaddr
|
||||
|
||||
from eventlet import event
|
||||
from eventlet import greenthread
|
||||
from eventlet.green import subprocess
|
||||
|
||||
from nova import exception
|
||||
from nova.exception import ProcessExecutionError
|
||||
@@ -235,6 +237,15 @@ def generate_mac():
|
||||
return ':'.join(map(lambda x: "%02x" % x, mac))
|
||||
|
||||
|
||||
def generate_password(length=20):
|
||||
"""Generate a random sequence of letters and digits
|
||||
to be used as a password. Note that this is not intended
|
||||
to represent the ultimate in security.
|
||||
"""
|
||||
chrs = string.letters + string.digits
|
||||
return "".join([random.choice(chrs) for i in xrange(length)])
|
||||
|
||||
|
||||
def last_octet(address):
|
||||
return int(address.split(".")[-1])
|
||||
|
||||
@@ -476,3 +487,15 @@ def dumps(value):
|
||||
|
||||
def loads(s):
|
||||
return json.loads(s)
|
||||
|
||||
|
||||
def ensure_b64_encoding(val):
|
||||
"""Safety method to ensure that values expected to be base64-encoded
|
||||
actually are. If they are, the value is returned unchanged. Otherwise,
|
||||
the encoded value is returned.
|
||||
"""
|
||||
try:
|
||||
dummy = base64.decode(val)
|
||||
return val
|
||||
except TypeError:
|
||||
return base64.b64encode(val)
|
||||
|
7
setup.py
7
setup.py
@@ -85,9 +85,13 @@ setup(name='nova',
|
||||
packages=find_packages(exclude=['bin', 'smoketests']),
|
||||
include_package_data=True,
|
||||
test_suite='nose.collector',
|
||||
scripts=['bin/nova-api',
|
||||
scripts=['bin/nova-ajax-console-proxy',
|
||||
'bin/nova-api',
|
||||
'bin/nova-combined',
|
||||
'bin/nova-compute',
|
||||
'bin/nova-console',
|
||||
'bin/nova-dhcpbridge',
|
||||
'bin/nova-direct-api',
|
||||
'bin/nova-import-canonical-imagestore',
|
||||
'bin/nova-instancemonitor',
|
||||
'bin/nova-logspool',
|
||||
@@ -96,5 +100,6 @@ setup(name='nova',
|
||||
'bin/nova-objectstore',
|
||||
'bin/nova-scheduler',
|
||||
'bin/nova-spoolsentry',
|
||||
'bin/stack',
|
||||
'bin/nova-volume',
|
||||
'tools/nova-debug'])
|
||||
|
Reference in New Issue
Block a user