Rebased to trunk rev 1057.

This commit is contained in:
Masanori Itoh
2011-05-08 00:19:28 +09:00
9 changed files with 138 additions and 55 deletions

View File

@@ -1,3 +1,4 @@
Alex Meade <alex.meade@rackspace.com>
Andy Smith <code@term.ie> Andy Smith <code@term.ie>
Andy Southgate <andy.southgate@citrix.com> Andy Southgate <andy.southgate@citrix.com>
Anne Gentle <anne@openstack.org> Anne Gentle <anne@openstack.org>
@@ -45,6 +46,7 @@ Joshua McKenty <jmckenty@gmail.com>
Justin Santa Barbara <justin@fathomdb.com> Justin Santa Barbara <justin@fathomdb.com>
Kei Masumoto <masumotok@nttdata.co.jp> Kei Masumoto <masumotok@nttdata.co.jp>
Ken Pepple <ken.pepple@gmail.com> Ken Pepple <ken.pepple@gmail.com>
Kevin Bringard <kbringard@attinteractive.com>
Kevin L. Mitchell <kevin.mitchell@rackspace.com> Kevin L. Mitchell <kevin.mitchell@rackspace.com>
Koji Iida <iida.koji@lab.ntt.co.jp> Koji Iida <iida.koji@lab.ntt.co.jp>
Lorin Hochstein <lorin@isi.edu> Lorin Hochstein <lorin@isi.edu>
@@ -76,6 +78,8 @@ Trey Morris <trey.morris@rackspace.com>
Tushar Patil <tushar.vitthal.patil@gmail.com> Tushar Patil <tushar.vitthal.patil@gmail.com>
Vasiliy Shlykov <vash@vasiliyshlykov.org> Vasiliy Shlykov <vash@vasiliyshlykov.org>
Vishvananda Ishaya <vishvananda@gmail.com> Vishvananda Ishaya <vishvananda@gmail.com>
William Wolf <will.wolf@rackspace.com>
Yoshiaki Tamura <yoshi@midokura.jp> Yoshiaki Tamura <yoshi@midokura.jp>
Youcef Laribi <Youcef.Laribi@eu.citrix.com> Youcef Laribi <Youcef.Laribi@eu.citrix.com>
Yuriy Taraday <yorik.sar@gmail.com>
Zhixue Wu <Zhixue.Wu@citrix.com> Zhixue Wu <Zhixue.Wu@citrix.com>

View File

@@ -82,6 +82,7 @@ from nova import log as logging
from nova import quota from nova import quota
from nova import rpc from nova import rpc
from nova import utils from nova import utils
from nova import version
from nova.api.ec2 import ec2utils from nova.api.ec2 import ec2utils
from nova.auth import manager from nova.auth import manager
from nova.cloudpipe import pipelib from nova.cloudpipe import pipelib
@@ -150,7 +151,7 @@ class VpnCommands(object):
state = 'up' state = 'up'
print address, print address,
print vpn['host'], print vpn['host'],
print vpn['ec2_id'], print ec2utils.id_to_ec2_id(vpn['id']),
print vpn['state_description'], print vpn['state_description'],
print state print state
else: else:
@@ -385,10 +386,10 @@ class ProjectCommands(object):
with open(filename, 'w') as f: with open(filename, 'w') as f:
f.write(rc) f.write(rc)
def list(self): def list(self, username=None):
"""Lists all projects """Lists all projects
arguments: <none>""" arguments: [username]"""
for project in self.manager.get_projects(): for project in self.manager.get_projects(username):
print project.name print project.name
def quota(self, project_id, key=None, value=None): def quota(self, project_id, key=None, value=None):
@@ -758,6 +759,17 @@ class DbCommands(object):
print migration.db_version() print migration.db_version()
class VersionCommands(object):
"""Class for exposing the codebase version."""
def __init__(self):
pass
def list(self):
print _("%s (%s)") %\
(version.version_string(), version.version_string_with_vcs())
class VolumeCommands(object): class VolumeCommands(object):
"""Methods for dealing with a cloud in an odd state""" """Methods for dealing with a cloud in an odd state"""
@@ -1049,7 +1061,8 @@ CATEGORIES = [
('volume', VolumeCommands), ('volume', VolumeCommands),
('instance_type', InstanceTypeCommands), ('instance_type', InstanceTypeCommands),
('image', ImageCommands), ('image', ImageCommands),
('flavor', InstanceTypeCommands)] ('flavor', InstanceTypeCommands),
('version', VersionCommands)]
def lazy_match(name, key_value_tuples): def lazy_match(name, key_value_tuples):
@@ -1091,6 +1104,8 @@ def main():
script_name = argv.pop(0) script_name = argv.pop(0)
if len(argv) < 1: if len(argv) < 1:
print _("\nOpenStack Nova version: %s (%s)\n") %\
(version.version_string(), version.version_string_with_vcs())
print script_name + " category action [<args>]" print script_name + " category action [<args>]"
print _("Available categories:") print _("Available categories:")
for k, _v in CATEGORIES: for k, _v in CATEGORIES:

View File

@@ -223,6 +223,13 @@ class AuthManager(object):
if driver or not getattr(self, 'driver', None): if driver or not getattr(self, 'driver', None):
self.driver = utils.import_class(driver or FLAGS.auth_driver) self.driver = utils.import_class(driver or FLAGS.auth_driver)
if FLAGS.memcached_servers:
import memcache
else:
from nova import fakememcache as memcache
self.mc = memcache.Client(FLAGS.memcached_servers,
debug=0)
def authenticate(self, access, signature, params, verb='GET', def authenticate(self, access, signature, params, verb='GET',
server_string='127.0.0.1:8773', path='/', server_string='127.0.0.1:8773', path='/',
check_type='ec2', headers=None): check_type='ec2', headers=None):
@@ -303,7 +310,8 @@ class AuthManager(object):
LOG.debug(_('signature: %s'), signature) LOG.debug(_('signature: %s'), signature)
if signature != expected_signature: if signature != expected_signature:
LOG.audit(_("Invalid signature for user %s"), user.name) LOG.audit(_("Invalid signature for user %s"), user.name)
raise exception.NotAuthorized(_('Signature does not match')) raise exception.InvalidSignature(signature=signature,
user=user)
elif check_type == 'ec2': elif check_type == 'ec2':
# NOTE(vish): hmac can't handle unicode, so encode ensures that # NOTE(vish): hmac can't handle unicode, so encode ensures that
# secret isn't unicode # secret isn't unicode
@@ -324,7 +332,8 @@ class AuthManager(object):
if signature == host_only_signature: if signature == host_only_signature:
return (user, project) return (user, project)
LOG.audit(_("Invalid signature for user %s"), user.name) LOG.audit(_("Invalid signature for user %s"), user.name)
raise exception.NotAuthorized(_('Signature does not match')) raise exception.InvalidSignature(signature=signature,
user=user)
return (user, project) return (user, project)
def get_access_key(self, user, project): def get_access_key(self, user, project):
@@ -368,6 +377,27 @@ class AuthManager(object):
if self.has_role(user, role): if self.has_role(user, role):
return True return True
def _build_mc_key(self, user, role, project=None):
key_parts = ['rolecache', User.safe_id(user), str(role)]
if project:
key_parts.append(Project.safe_id(project))
return '-'.join(key_parts)
def _clear_mc_key(self, user, role, project=None):
# NOTE(anthony): it would be better to delete the key
self.mc.set(self._build_mc_key(user, role, project), None)
def _has_role(self, user, role, project=None):
mc_key = self._build_mc_key(user, role, project)
rslt = self.mc.get(mc_key)
if rslt is None:
with self.driver() as drv:
rslt = drv.has_role(user, role, project)
self.mc.set(mc_key, rslt)
return rslt
else:
return rslt
def has_role(self, user, role, project=None): def has_role(self, user, role, project=None):
"""Checks existence of role for user """Checks existence of role for user
@@ -391,24 +421,24 @@ class AuthManager(object):
@rtype: bool @rtype: bool
@return: True if the user has the role. @return: True if the user has the role.
""" """
with self.driver() as drv: if role == 'projectmanager':
if role == 'projectmanager': if not project:
if not project: raise exception.Error(_("Must specify project"))
raise exception.Error(_("Must specify project")) return self.is_project_manager(user, project)
return self.is_project_manager(user, project)
global_role = drv.has_role(User.safe_id(user), global_role = self._has_role(User.safe_id(user),
role, role,
None) None)
if not global_role:
return global_role
if not project or role in FLAGS.global_roles: if not global_role:
return global_role return global_role
return drv.has_role(User.safe_id(user), if not project or role in FLAGS.global_roles:
role, return global_role
Project.safe_id(project))
return self._has_role(User.safe_id(user),
role,
Project.safe_id(project))
def add_role(self, user, role, project=None): def add_role(self, user, role, project=None):
"""Adds role for user """Adds role for user
@@ -440,6 +470,7 @@ class AuthManager(object):
LOG.audit(_("Adding sitewide role %(role)s to user %(uid)s") LOG.audit(_("Adding sitewide role %(role)s to user %(uid)s")
% locals()) % locals())
with self.driver() as drv: with self.driver() as drv:
self._clear_mc_key(uid, role, pid)
drv.add_role(uid, role, pid) drv.add_role(uid, role, pid)
def remove_role(self, user, role, project=None): def remove_role(self, user, role, project=None):
@@ -468,6 +499,7 @@ class AuthManager(object):
LOG.audit(_("Removing sitewide role %(role)s" LOG.audit(_("Removing sitewide role %(role)s"
" from user %(uid)s") % locals()) " from user %(uid)s") % locals())
with self.driver() as drv: with self.driver() as drv:
self._clear_mc_key(uid, role, pid)
drv.remove_role(uid, role, pid) drv.remove_role(uid, role, pid)
@staticmethod @staticmethod

View File

@@ -369,6 +369,9 @@ DEFINE_string('host', socket.gethostname(),
DEFINE_string('node_availability_zone', 'nova', DEFINE_string('node_availability_zone', 'nova',
'availability zone of this node') 'availability zone of this node')
DEFINE_list('memcached_servers', None,
'Memcached servers or None for in process cache.')
DEFINE_string('zone_name', 'nova', 'name of this zone') DEFINE_string('zone_name', 'nova', 'name of this zone')
DEFINE_list('zone_capabilities', DEFINE_list('zone_capabilities',
['hypervisor=xenserver;kvm', 'os=linux;windows'], ['hypervisor=xenserver;kvm', 'os=linux;windows'],

View File

@@ -290,7 +290,7 @@ class CloudTestCase(test.TestCase):
instance_id = rv['instancesSet'][0]['instanceId'] instance_id = rv['instancesSet'][0]['instanceId']
output = self.cloud.get_console_output(context=self.context, output = self.cloud.get_console_output(context=self.context,
instance_id=[instance_id]) instance_id=[instance_id])
self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE OUTPUT') self.assertEquals(b64decode(output['output']), 'FAKE CONSOLE?OUTPUT')
# TODO(soren): We need this until we can stop polling in the rpc code # TODO(soren): We need this until we can stop polling in the rpc code
# for unit tests. # for unit tests.
greenthread.sleep(0.3) greenthread.sleep(0.3)

View File

@@ -75,13 +75,13 @@ class InstanceTypeTestCase(test.TestCase):
def test_invalid_create_args_should_fail(self): def test_invalid_create_args_should_fail(self):
"""Ensures that instance type creation fails with invalid args""" """Ensures that instance type creation fails with invalid args"""
self.assertRaises( self.assertRaises(
exception.InvalidInputException, exception.InvalidInput,
instance_types.create, self.name, 0, 1, 120, self.flavorid) instance_types.create, self.name, 0, 1, 120, self.flavorid)
self.assertRaises( self.assertRaises(
exception.InvalidInputException, exception.InvalidInput,
instance_types.create, self.name, 256, -1, 120, self.flavorid) instance_types.create, self.name, 256, -1, 120, self.flavorid)
self.assertRaises( self.assertRaises(
exception.InvalidInputException, exception.InvalidInput,
instance_types.create, self.name, 256, 1, "aa", self.flavorid) instance_types.create, self.name, 256, 1, "aa", self.flavorid)
def test_non_existant_inst_type_shouldnt_delete(self): def test_non_existant_inst_type_shouldnt_delete(self):

View File

@@ -29,11 +29,12 @@ from nova.utils import parse_mailmap, str_dict_replace
class ProjectTestCase(test.TestCase): class ProjectTestCase(test.TestCase):
def test_authors_up_to_date(self): def test_authors_up_to_date(self):
topdir = os.path.normpath(os.path.dirname(__file__) + '/../../') topdir = os.path.normpath(os.path.dirname(__file__) + '/../../')
missing = set()
contributors = set()
mailmap = parse_mailmap(os.path.join(topdir, '.mailmap'))
authors_file = open(os.path.join(topdir, 'Authors'), 'r').read()
if os.path.exists(os.path.join(topdir, '.bzr')): if os.path.exists(os.path.join(topdir, '.bzr')):
contributors = set()
mailmap = parse_mailmap(os.path.join(topdir, '.mailmap'))
import bzrlib.workingtree import bzrlib.workingtree
tree = bzrlib.workingtree.WorkingTree.open(topdir) tree = bzrlib.workingtree.WorkingTree.open(topdir)
tree.lock_read() tree.lock_read()
@@ -47,23 +48,37 @@ class ProjectTestCase(test.TestCase):
for r in revs: for r in revs:
for author in r.get_apparent_authors(): for author in r.get_apparent_authors():
email = author.split(' ')[-1] email = author.split(' ')[-1]
contributors.add(str_dict_replace(email, mailmap)) contributors.add(str_dict_replace(email,
mailmap))
authors_file = open(os.path.join(topdir, 'Authors'),
'r').read()
missing = set()
for contributor in contributors:
if contributor == 'nova-core':
continue
if not contributor in authors_file:
missing.add(contributor)
self.assertTrue(len(missing) == 0,
'%r not listed in Authors' % missing)
finally: finally:
tree.unlock() tree.unlock()
elif os.path.exists(os.path.join(topdir, '.git')):
import git
repo = git.Repo(topdir)
for commit in repo.head.commit.iter_parents():
email = commit.author.email
if email is None:
email = commit.author.name
if 'nova-core' in email:
continue
if email.split(' ')[-1] == '<>':
email = email.split(' ')[-2]
email = '<' + email + '>'
contributors.add(str_dict_replace(email, mailmap))
else:
return
for contributor in contributors:
if contributor == 'nova-core':
continue
if not contributor in authors_file:
missing.add(contributor)
self.assertTrue(len(missing) == 0,
'%r not listed in Authors' % missing)
class LockTestCase(test.TestCase): class LockTestCase(test.TestCase):
def test_synchronized_wrapped_function_metadata(self): def test_synchronized_wrapped_function_metadata(self):

View File

@@ -768,14 +768,10 @@ class SimpleDriverTestCase(test.TestCase):
s_ref = self._create_compute_service(host='somewhere', s_ref = self._create_compute_service(host='somewhere',
memory_mb_used=12) memory_mb_used=12)
try: self.assertRaises(exception.MigrationError,
self.scheduler.driver._live_migration_dest_check(self.context, self.scheduler.driver._live_migration_dest_check,
i_ref, self.context, i_ref, 'somewhere')
'somewhere')
except exception.NotEmpty, e:
c = (e.message.find('Unable to migrate') >= 0)
self.assertTrue(c)
db.instance_destroy(self.context, instance_id) db.instance_destroy(self.context, instance_id)
db.service_destroy(self.context, s_ref['id']) db.service_destroy(self.context, s_ref['id'])

View File

@@ -44,7 +44,9 @@ def _concurrency(wait, done, target):
done.send() done.send()
def _create_network_info(count=1): def _create_network_info(count=1, ipv6=None):
if ipv6 is None:
ipv6 = FLAGS.use_ipv6
fake = 'fake' fake = 'fake'
fake_ip = '0.0.0.0/0' fake_ip = '0.0.0.0/0'
fake_ip_2 = '0.0.0.1/0' fake_ip_2 = '0.0.0.1/0'
@@ -55,8 +57,11 @@ def _create_network_info(count=1):
'cidr': fake_ip, 'cidr': fake_ip,
'cidr_v6': fake_ip} 'cidr_v6': fake_ip}
mapping = {'mac': fake, mapping = {'mac': fake,
'ips': [{'ip': fake_ip}, {'ip': fake_ip}], 'ips': [{'ip': fake_ip}, {'ip': fake_ip}]}
'ip6s': [{'ip': fake_ip}, {'ip': fake_ip_2}, {'ip': fake_ip_3}]} if ipv6:
mapping['ip6s'] = [{'ip': fake_ip},
{'ip': fake_ip_2},
{'ip': fake_ip_3}]
return [(network, mapping) for x in xrange(0, count)] return [(network, mapping) for x in xrange(0, count)]
@@ -641,6 +646,11 @@ class LibvirtConnTestCase(test.TestCase):
self.assertTrue(count) self.assertTrue(count)
def test_get_host_ip_addr(self):
conn = libvirt_conn.LibvirtConnection(False)
ip = conn.get_host_ip_addr()
self.assertEquals(ip, FLAGS.my_ip)
def tearDown(self): def tearDown(self):
self.manager.delete_project(self.project) self.manager.delete_project(self.project)
self.manager.delete_user(self.user) self.manager.delete_user(self.user)
@@ -825,12 +835,20 @@ class IptablesFirewallTestCase(test.TestCase):
"TCP port 80/81 acceptance rule wasn't added") "TCP port 80/81 acceptance rule wasn't added")
db.instance_destroy(admin_ctxt, instance_ref['id']) db.instance_destroy(admin_ctxt, instance_ref['id'])
def test_filters_for_instance(self): def test_filters_for_instance_with_ip_v6(self):
self.flags(use_ipv6=True)
network_info = _create_network_info() network_info = _create_network_info()
rulesv4, rulesv6 = self.fw._filters_for_instance("fake", network_info) rulesv4, rulesv6 = self.fw._filters_for_instance("fake", network_info)
self.assertEquals(len(rulesv4), 2) self.assertEquals(len(rulesv4), 2)
self.assertEquals(len(rulesv6), 3) self.assertEquals(len(rulesv6), 3)
def test_filters_for_instance_without_ip_v6(self):
self.flags(use_ipv6=False)
network_info = _create_network_info()
rulesv4, rulesv6 = self.fw._filters_for_instance("fake", network_info)
self.assertEquals(len(rulesv4), 2)
self.assertEquals(len(rulesv6), 0)
def multinic_iptables_test(self): def multinic_iptables_test(self):
ipv4_rules_per_network = 2 ipv4_rules_per_network = 2
ipv6_rules_per_network = 3 ipv6_rules_per_network = 3