fixed merge conflict
This commit is contained in:
1
.mailmap
1
.mailmap
@@ -33,3 +33,4 @@
|
|||||||
<corywright@gmail.com> <cory.wright@rackspace.com>
|
<corywright@gmail.com> <cory.wright@rackspace.com>
|
||||||
<ant@openstack.org> <amesserl@rackspace.com>
|
<ant@openstack.org> <amesserl@rackspace.com>
|
||||||
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
|
<chiradeep@cloud.com> <chiradeep@chiradeep-lt2>
|
||||||
|
<justin@fathomdb.com> <superstack@superstack.org>
|
||||||
|
|||||||
7
Authors
7
Authors
@@ -3,11 +3,14 @@ Anne Gentle <anne@openstack.org>
|
|||||||
Anthony Young <sleepsonthefloor@gmail.com>
|
Anthony Young <sleepsonthefloor@gmail.com>
|
||||||
Antony Messerli <ant@openstack.org>
|
Antony Messerli <ant@openstack.org>
|
||||||
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
||||||
|
Bilal Akhtar <bilalakhtar@ubuntu.com>
|
||||||
Chiradeep Vittal <chiradeep@cloud.com>
|
Chiradeep Vittal <chiradeep@cloud.com>
|
||||||
Chmouel Boudjnah <chmouel@chmouel.com>
|
Chmouel Boudjnah <chmouel@chmouel.com>
|
||||||
Chris Behrens <cbehrens@codestud.com>
|
Chris Behrens <cbehrens@codestud.com>
|
||||||
|
Christian Berendt <berendt@b1-systems.de>
|
||||||
Cory Wright <corywright@gmail.com>
|
Cory Wright <corywright@gmail.com>
|
||||||
David Pravec <David.Pravec@danix.org>
|
David Pravec <David.Pravec@danix.org>
|
||||||
|
Dan Prince <dan.prince@rackspace.com>
|
||||||
Dean Troyer <dtroyer@gmail.com>
|
Dean Troyer <dtroyer@gmail.com>
|
||||||
Devin Carlen <devin.carlen@gmail.com>
|
Devin Carlen <devin.carlen@gmail.com>
|
||||||
Ed Leafe <ed@leafe.com>
|
Ed Leafe <ed@leafe.com>
|
||||||
@@ -21,7 +24,9 @@ Jay Pipes <jaypipes@gmail.com>
|
|||||||
Jesse Andrews <anotherjesse@gmail.com>
|
Jesse Andrews <anotherjesse@gmail.com>
|
||||||
Joe Heck <heckj@mac.com>
|
Joe Heck <heckj@mac.com>
|
||||||
Joel Moore <joelbm24@gmail.com>
|
Joel Moore <joelbm24@gmail.com>
|
||||||
|
John Dewey <john@dewey.ws>
|
||||||
Jonathan Bryce <jbryce@jbryce.com>
|
Jonathan Bryce <jbryce@jbryce.com>
|
||||||
|
Jordan Rinke <jordan@openstack.org>
|
||||||
Josh Durgin <joshd@hq.newdream.net>
|
Josh Durgin <joshd@hq.newdream.net>
|
||||||
Josh Kearney <josh.kearney@rackspace.com>
|
Josh Kearney <josh.kearney@rackspace.com>
|
||||||
Joshua McKenty <jmckenty@gmail.com>
|
Joshua McKenty <jmckenty@gmail.com>
|
||||||
@@ -38,6 +43,7 @@ MORITA Kazutaka <morita.kazutaka@gmail.com>
|
|||||||
Muneyuki Noguchi <noguchimn@nttdata.co.jp>
|
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> <openstack@lab.ntt.co.jp> <nati.ueno@gmail.com> <nova@u4>
|
||||||
Paul Voccio <paul@openstack.org>
|
Paul Voccio <paul@openstack.org>
|
||||||
|
Ricardo Carrillo Cruz <emaildericky@gmail.com>
|
||||||
Rick Clark <rick@openstack.org>
|
Rick Clark <rick@openstack.org>
|
||||||
Rick Harris <rconradharris@gmail.com>
|
Rick Harris <rconradharris@gmail.com>
|
||||||
Rob Kost <kost@isi.edu>
|
Rob Kost <kost@isi.edu>
|
||||||
@@ -49,6 +55,7 @@ Soren Hansen <soren.hansen@rackspace.com>
|
|||||||
Thierry Carrez <thierry@openstack.org>
|
Thierry Carrez <thierry@openstack.org>
|
||||||
Todd Willey <todd@ansolabs.com>
|
Todd Willey <todd@ansolabs.com>
|
||||||
Trey Morris <trey.morris@rackspace.com>
|
Trey Morris <trey.morris@rackspace.com>
|
||||||
|
Tushar Patil <tushar.vitthal.patil@gmail.com> <tpatil@vertex.co.in>
|
||||||
Vishvananda Ishaya <vishvananda@gmail.com>
|
Vishvananda Ishaya <vishvananda@gmail.com>
|
||||||
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
Youcef Laribi <Youcef.Laribi@eu.citrix.com>
|
||||||
Zhixue Wu <Zhixue.Wu@citrix.com>
|
Zhixue Wu <Zhixue.Wu@citrix.com>
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ def run_app(paste_config_file):
|
|||||||
if config is None:
|
if config is None:
|
||||||
LOG.debug(_("No paste configuration for app: %s"), api)
|
LOG.debug(_("No paste configuration for app: %s"), api)
|
||||||
continue
|
continue
|
||||||
LOG.debug(_("App Config: %s\n%r"), api, config)
|
LOG.debug(_("App Config: %(api)s\n%(config)r") % locals())
|
||||||
wsgi.paste_config_to_flags(config, {
|
wsgi.paste_config_to_flags(config, {
|
||||||
"verbose": FLAGS.verbose,
|
"verbose": FLAGS.verbose,
|
||||||
"%s_host" % api: config.get('host', '0.0.0.0'),
|
"%s_host" % api: config.get('host', '0.0.0.0'),
|
||||||
|
|||||||
@@ -120,9 +120,9 @@ def main():
|
|||||||
mac = argv[2]
|
mac = argv[2]
|
||||||
ip = argv[3]
|
ip = argv[3]
|
||||||
hostname = argv[4]
|
hostname = argv[4]
|
||||||
LOG.debug(_("Called %s for mac %s with ip %s and "
|
msg = _("Called %(action)s for mac %(mac)s with ip %(ip)s and"
|
||||||
"hostname %s on interface %s"),
|
" hostname %(hostname)s on interface %(interface)s") % locals()
|
||||||
action, mac, ip, hostname, interface)
|
LOG.debug(msg)
|
||||||
globals()[action + '_lease'](mac, ip, hostname, interface)
|
globals()[action + '_lease'](mac, ip, hostname, interface)
|
||||||
else:
|
else:
|
||||||
print init_leases(interface)
|
print init_leases(interface)
|
||||||
|
|||||||
@@ -267,6 +267,14 @@ class RoleCommands(object):
|
|||||||
self.manager.remove_role(user, role, project)
|
self.manager.remove_role(user, role, project)
|
||||||
|
|
||||||
|
|
||||||
|
def _db_error(caught_exception):
|
||||||
|
print caught_exception
|
||||||
|
print _("The above error may show that the database has not "
|
||||||
|
"been created.\nPlease create a database using "
|
||||||
|
"nova-manage sync db before running this command.")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
class UserCommands(object):
|
class UserCommands(object):
|
||||||
"""Class for managing users."""
|
"""Class for managing users."""
|
||||||
|
|
||||||
@@ -282,13 +290,19 @@ class UserCommands(object):
|
|||||||
def admin(self, name, access=None, secret=None):
|
def admin(self, name, access=None, secret=None):
|
||||||
"""creates a new admin and prints exports
|
"""creates a new admin and prints exports
|
||||||
arguments: name [access] [secret]"""
|
arguments: name [access] [secret]"""
|
||||||
user = self.manager.create_user(name, access, secret, True)
|
try:
|
||||||
|
user = self.manager.create_user(name, access, secret, True)
|
||||||
|
except exception.DBError, e:
|
||||||
|
_db_error(e)
|
||||||
self._print_export(user)
|
self._print_export(user)
|
||||||
|
|
||||||
def create(self, name, access=None, secret=None):
|
def create(self, name, access=None, secret=None):
|
||||||
"""creates a new user and prints exports
|
"""creates a new user and prints exports
|
||||||
arguments: name [access] [secret]"""
|
arguments: name [access] [secret]"""
|
||||||
user = self.manager.create_user(name, access, secret, False)
|
try:
|
||||||
|
user = self.manager.create_user(name, access, secret, False)
|
||||||
|
except exception.DBError, e:
|
||||||
|
_db_error(e)
|
||||||
self._print_export(user)
|
self._print_export(user)
|
||||||
|
|
||||||
def delete(self, name):
|
def delete(self, name):
|
||||||
@@ -409,9 +423,14 @@ class ProjectCommands(object):
|
|||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
f.write(zip_file)
|
f.write(zip_file)
|
||||||
except db.api.NoMoreNetworks:
|
except db.api.NoMoreNetworks:
|
||||||
print ('No more networks available. If this is a new '
|
print _('No more networks available. If this is a new '
|
||||||
'installation, you need\nto call something like this:\n\n'
|
'installation, you need\nto call something like this:\n\n'
|
||||||
' nova-manage network create 10.0.0.0/8 10 64\n\n')
|
' nova-manage network create 10.0.0.0/8 10 64\n\n')
|
||||||
|
except exception.ProcessExecutionError, e:
|
||||||
|
print e
|
||||||
|
print _("The above error may show that the certificate db has not "
|
||||||
|
"been created.\nPlease create a database by running a "
|
||||||
|
"nova-api server on this host.")
|
||||||
|
|
||||||
|
|
||||||
class FloatingIpCommands(object):
|
class FloatingIpCommands(object):
|
||||||
|
|||||||
@@ -74,10 +74,8 @@ class SpoolSentry(object):
|
|||||||
return rv
|
return rv
|
||||||
|
|
||||||
def send_data(self, data):
|
def send_data(self, data):
|
||||||
data = {
|
data = {'data': base64.b64encode(pickle.dumps(data).encode('zlib')),
|
||||||
'data': base64.b64encode(pickle.dumps(data).encode('zlib')),
|
'key': self.key}
|
||||||
'key': self.key
|
|
||||||
}
|
|
||||||
req = urllib2.Request(self.sentry_url)
|
req = urllib2.Request(self.sentry_url)
|
||||||
res = urllib2.urlopen(req, urllib.urlencode(data))
|
res = urllib2.urlopen(req, urllib.urlencode(data))
|
||||||
if res.getcode() != 200:
|
if res.getcode() != 200:
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"machine" : ["kernel", "ramdisk"]
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,7 @@ Nova User API client library.
|
|||||||
|
|
||||||
import base64
|
import base64
|
||||||
import boto
|
import boto
|
||||||
|
import boto.exception
|
||||||
import httplib
|
import httplib
|
||||||
|
|
||||||
from boto.ec2.regioninfo import RegionInfo
|
from boto.ec2.regioninfo import RegionInfo
|
||||||
@@ -190,6 +191,45 @@ class HostInfo(object):
|
|||||||
setattr(self, name, value)
|
setattr(self, name, value)
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceType(object):
|
||||||
|
"""
|
||||||
|
Information about a Nova instance type, as parsed through SAX.
|
||||||
|
|
||||||
|
**Fields include**
|
||||||
|
|
||||||
|
* name
|
||||||
|
* vcpus
|
||||||
|
* disk_gb
|
||||||
|
* memory_mb
|
||||||
|
* flavor_id
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, connection=None):
|
||||||
|
self.connection = connection
|
||||||
|
self.name = None
|
||||||
|
self.vcpus = None
|
||||||
|
self.disk_gb = None
|
||||||
|
self.memory_mb = None
|
||||||
|
self.flavor_id = None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return 'InstanceType:%s' % self.name
|
||||||
|
|
||||||
|
def startElement(self, name, attrs, connection):
|
||||||
|
return None
|
||||||
|
|
||||||
|
def endElement(self, name, value, connection):
|
||||||
|
if name == "memoryMb":
|
||||||
|
self.memory_mb = str(value)
|
||||||
|
elif name == "flavorId":
|
||||||
|
self.flavor_id = str(value)
|
||||||
|
elif name == "diskGb":
|
||||||
|
self.disk_gb = str(value)
|
||||||
|
else:
|
||||||
|
setattr(self, name, str(value))
|
||||||
|
|
||||||
|
|
||||||
class NovaAdminClient(object):
|
class NovaAdminClient(object):
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@@ -249,10 +289,14 @@ class NovaAdminClient(object):
|
|||||||
|
|
||||||
def get_user(self, name):
|
def get_user(self, name):
|
||||||
"""Grab a single user by name."""
|
"""Grab a single user by name."""
|
||||||
user = self.apiconn.get_object('DescribeUser', {'Name': name},
|
try:
|
||||||
UserInfo)
|
return self.apiconn.get_object('DescribeUser',
|
||||||
if user.username != None:
|
{'Name': name},
|
||||||
return user
|
UserInfo)
|
||||||
|
except boto.exception.BotoServerError, e:
|
||||||
|
if e.status == 400 and e.error_code == 'NotFound':
|
||||||
|
return None
|
||||||
|
raise
|
||||||
|
|
||||||
def has_user(self, username):
|
def has_user(self, username):
|
||||||
"""Determine if user exists."""
|
"""Determine if user exists."""
|
||||||
@@ -337,6 +381,13 @@ class NovaAdminClient(object):
|
|||||||
'MemberUsers': member_users}
|
'MemberUsers': member_users}
|
||||||
return self.apiconn.get_object('RegisterProject', params, ProjectInfo)
|
return self.apiconn.get_object('RegisterProject', params, ProjectInfo)
|
||||||
|
|
||||||
|
def modify_project(self, projectname, manager_user=None, description=None):
|
||||||
|
"""Modifies an existing project."""
|
||||||
|
params = {'Name': projectname,
|
||||||
|
'ManagerUser': manager_user,
|
||||||
|
'Description': description}
|
||||||
|
return self.apiconn.get_status('ModifyProject', params)
|
||||||
|
|
||||||
def delete_project(self, projectname):
|
def delete_project(self, projectname):
|
||||||
"""Permanently deletes the specified project."""
|
"""Permanently deletes the specified project."""
|
||||||
return self.apiconn.get_object('DeregisterProject',
|
return self.apiconn.get_object('DeregisterProject',
|
||||||
@@ -373,3 +424,8 @@ class NovaAdminClient(object):
|
|||||||
|
|
||||||
def get_hosts(self):
|
def get_hosts(self):
|
||||||
return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)])
|
return self.apiconn.get_list('DescribeHosts', {}, [('item', HostInfo)])
|
||||||
|
|
||||||
|
def get_instance_types(self):
|
||||||
|
"""Grabs the list of all users."""
|
||||||
|
return self.apiconn.get_list('DescribeInstanceTypes', {},
|
||||||
|
[('item', InstanceType)])
|
||||||
|
|||||||
@@ -473,8 +473,8 @@ class LdapDriver(object):
|
|||||||
raise exception.NotFound(_("The group at dn %s doesn't exist") %
|
raise exception.NotFound(_("The group at dn %s doesn't exist") %
|
||||||
group_dn)
|
group_dn)
|
||||||
if self.__is_in_group(uid, group_dn):
|
if self.__is_in_group(uid, group_dn):
|
||||||
raise exception.Duplicate(_("User %s is already a member of "
|
raise exception.Duplicate(_("User %(uid)s is already a member of "
|
||||||
"the group %s") % (uid, group_dn))
|
"the group %(group_dn)s") % locals())
|
||||||
attr = [(self.ldap.MOD_ADD, 'member', self.__uid_to_dn(uid))]
|
attr = [(self.ldap.MOD_ADD, 'member', self.__uid_to_dn(uid))]
|
||||||
self.conn.modify_s(group_dn, attr)
|
self.conn.modify_s(group_dn, attr)
|
||||||
|
|
||||||
@@ -585,10 +585,11 @@ class LdapDriver(object):
|
|||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@staticmethod
|
def __dn_to_uid(self, dn):
|
||||||
def __dn_to_uid(dn):
|
|
||||||
"""Convert user dn to uid"""
|
"""Convert user dn to uid"""
|
||||||
return dn.split(',')[0].split('=')[1]
|
query = '(objectclass=novaUser)'
|
||||||
|
user = self.__find_object(dn, query)
|
||||||
|
return user[FLAGS.ldap_user_id_attribute][0]
|
||||||
|
|
||||||
|
|
||||||
class FakeLdapDriver(LdapDriver):
|
class FakeLdapDriver(LdapDriver):
|
||||||
|
|||||||
@@ -272,16 +272,22 @@ class AuthManager(object):
|
|||||||
|
|
||||||
project = self.get_project(project_id)
|
project = self.get_project(project_id)
|
||||||
if project == None:
|
if project == None:
|
||||||
LOG.audit(_("failed authorization: no project named %s (user=%s)"),
|
pjid = project_id
|
||||||
project_id, user.name)
|
uname = user.name
|
||||||
|
LOG.audit(_("failed authorization: no project named %(pjid)s"
|
||||||
|
" (user=%(uname)s)") % locals())
|
||||||
raise exception.NotFound(_('No project called %s could be found')
|
raise exception.NotFound(_('No project called %s could be found')
|
||||||
% project_id)
|
% project_id)
|
||||||
if not self.is_admin(user) and not self.is_project_member(user,
|
if not self.is_admin(user) and not self.is_project_member(user,
|
||||||
project):
|
project):
|
||||||
LOG.audit(_("Failed authorization: user %s not admin and not "
|
uname = user.name
|
||||||
"member of project %s"), user.name, project.name)
|
uid = user.id
|
||||||
raise exception.NotFound(_('User %s is not a member of project %s')
|
pjname = project.name
|
||||||
% (user.id, project.id))
|
pjid = project.id
|
||||||
|
LOG.audit(_("Failed authorization: user %(uname)s not admin"
|
||||||
|
" and not member of project %(pjname)s") % locals())
|
||||||
|
raise exception.NotFound(_('User %(uid)s is not a member of'
|
||||||
|
' project %(pjid)s') % locals())
|
||||||
if check_type == 's3':
|
if check_type == 's3':
|
||||||
sign = signer.Signer(user.secret.encode())
|
sign = signer.Signer(user.secret.encode())
|
||||||
expected_signature = sign.s3_authorization(headers, verb, path)
|
expected_signature = sign.s3_authorization(headers, verb, path)
|
||||||
@@ -408,14 +414,16 @@ class AuthManager(object):
|
|||||||
raise exception.NotFound(_("The %s role can not be found") % role)
|
raise exception.NotFound(_("The %s role can not be found") % role)
|
||||||
if project is not None and role in FLAGS.global_roles:
|
if project is not None and role in FLAGS.global_roles:
|
||||||
raise exception.NotFound(_("The %s role is global only") % role)
|
raise exception.NotFound(_("The %s role is global only") % role)
|
||||||
|
uid = User.safe_id(user)
|
||||||
|
pid = Project.safe_id(project)
|
||||||
if project:
|
if project:
|
||||||
LOG.audit(_("Adding role %s to user %s in project %s"), role,
|
LOG.audit(_("Adding role %(role)s to user %(uid)s"
|
||||||
User.safe_id(user), Project.safe_id(project))
|
" in project %(pid)s") % locals())
|
||||||
else:
|
else:
|
||||||
LOG.audit(_("Adding sitewide role %s to user %s"), role,
|
LOG.audit(_("Adding sitewide role %(role)s to user %(uid)s")
|
||||||
User.safe_id(user))
|
% locals())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.add_role(User.safe_id(user), role, Project.safe_id(project))
|
drv.add_role(uid, role, pid)
|
||||||
|
|
||||||
def remove_role(self, user, role, project=None):
|
def remove_role(self, user, role, project=None):
|
||||||
"""Removes role for user
|
"""Removes role for user
|
||||||
@@ -434,14 +442,16 @@ class AuthManager(object):
|
|||||||
@type project: Project or project_id
|
@type project: Project or project_id
|
||||||
@param project: Project in which to remove local role.
|
@param project: Project in which to remove local role.
|
||||||
"""
|
"""
|
||||||
|
uid = User.safe_id(user)
|
||||||
|
pid = Project.safe_id(project)
|
||||||
if project:
|
if project:
|
||||||
LOG.audit(_("Removing role %s from user %s on project %s"),
|
LOG.audit(_("Removing role %(role)s from user %(uid)s"
|
||||||
role, User.safe_id(user), Project.safe_id(project))
|
" on project %(pid)s") % locals())
|
||||||
else:
|
else:
|
||||||
LOG.audit(_("Removing sitewide role %s from user %s"), role,
|
LOG.audit(_("Removing sitewide role %(role)s"
|
||||||
User.safe_id(user))
|
" from user %(uid)s") % locals())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.remove_role(User.safe_id(user), role, Project.safe_id(project))
|
drv.remove_role(uid, role, pid)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_roles(project_roles=True):
|
def get_roles(project_roles=True):
|
||||||
@@ -502,8 +512,8 @@ class AuthManager(object):
|
|||||||
description,
|
description,
|
||||||
member_users)
|
member_users)
|
||||||
if project_dict:
|
if project_dict:
|
||||||
LOG.audit(_("Created project %s with manager %s"), name,
|
LOG.audit(_("Created project %(name)s with"
|
||||||
manager_user)
|
" manager %(manager_user)s") % locals())
|
||||||
project = Project(**project_dict)
|
project = Project(**project_dict)
|
||||||
return project
|
return project
|
||||||
|
|
||||||
@@ -530,11 +540,12 @@ class AuthManager(object):
|
|||||||
|
|
||||||
def add_to_project(self, user, project):
|
def add_to_project(self, user, project):
|
||||||
"""Add user to project"""
|
"""Add user to project"""
|
||||||
LOG.audit(_("Adding user %s to project %s"), User.safe_id(user),
|
uid = User.safe_id(user)
|
||||||
Project.safe_id(project))
|
pid = Project.safe_id(project)
|
||||||
|
LOG.audit(_("Adding user %(uid)s to project %(pid)s") % locals())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
return drv.add_to_project(User.safe_id(user),
|
return drv.add_to_project(User.safe_id(user),
|
||||||
Project.safe_id(project))
|
Project.safe_id(project))
|
||||||
|
|
||||||
def is_project_manager(self, user, project):
|
def is_project_manager(self, user, project):
|
||||||
"""Checks if user is project manager"""
|
"""Checks if user is project manager"""
|
||||||
@@ -550,11 +561,11 @@ class AuthManager(object):
|
|||||||
|
|
||||||
def remove_from_project(self, user, project):
|
def remove_from_project(self, user, project):
|
||||||
"""Removes a user from a project"""
|
"""Removes a user from a project"""
|
||||||
LOG.audit(_("Remove user %s from project %s"), User.safe_id(user),
|
uid = User.safe_id(user)
|
||||||
Project.safe_id(project))
|
pid = Project.safe_id(project)
|
||||||
|
LOG.audit(_("Remove user %(uid)s from project %(pid)s") % locals())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
return drv.remove_from_project(User.safe_id(user),
|
return drv.remove_from_project(uid, pid)
|
||||||
Project.safe_id(project))
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_project_vpn_data(project):
|
def get_project_vpn_data(project):
|
||||||
@@ -634,7 +645,10 @@ class AuthManager(object):
|
|||||||
user_dict = drv.create_user(name, access, secret, admin)
|
user_dict = drv.create_user(name, access, secret, admin)
|
||||||
if user_dict:
|
if user_dict:
|
||||||
rv = User(**user_dict)
|
rv = User(**user_dict)
|
||||||
LOG.audit(_("Created user %s (admin: %r)"), rv.name, rv.admin)
|
rvname = rv.name
|
||||||
|
rvadmin = rv.admin
|
||||||
|
LOG.audit(_("Created user %(rvname)s"
|
||||||
|
" (admin: %(rvadmin)r)") % locals())
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
def delete_user(self, user):
|
def delete_user(self, user):
|
||||||
@@ -656,7 +670,8 @@ class AuthManager(object):
|
|||||||
if secret_key:
|
if secret_key:
|
||||||
LOG.audit(_("Secret Key change for user %s"), uid)
|
LOG.audit(_("Secret Key change for user %s"), uid)
|
||||||
if admin is not None:
|
if admin is not None:
|
||||||
LOG.audit(_("Admin status set to %r for user %s"), admin, uid)
|
LOG.audit(_("Admin status set to %(admin)r"
|
||||||
|
" for user %(uid)s") % locals())
|
||||||
with self.driver() as drv:
|
with self.driver() as drv:
|
||||||
drv.modify_user(uid, access_key, secret_key, admin)
|
drv.modify_user(uid, access_key, secret_key, admin)
|
||||||
|
|
||||||
|
|||||||
@@ -45,8 +45,9 @@ class Exchange(object):
|
|||||||
self._routes = {}
|
self._routes = {}
|
||||||
|
|
||||||
def publish(self, message, routing_key=None):
|
def publish(self, message, routing_key=None):
|
||||||
LOG.debug(_('(%s) publish (key: %s) %s'),
|
nm = self.name
|
||||||
self.name, routing_key, message)
|
LOG.debug(_('(%(nm)s) publish (key: %(routing_key)s)'
|
||||||
|
' %(message)s') % locals())
|
||||||
routing_key = routing_key.split('.')[0]
|
routing_key = routing_key.split('.')[0]
|
||||||
if routing_key in self._routes:
|
if routing_key in self._routes:
|
||||||
for f in self._routes[routing_key]:
|
for f in self._routes[routing_key]:
|
||||||
@@ -92,8 +93,8 @@ class Backend(base.BaseBackend):
|
|||||||
def queue_bind(self, queue, exchange, routing_key, **kwargs):
|
def queue_bind(self, queue, exchange, routing_key, **kwargs):
|
||||||
global EXCHANGES
|
global EXCHANGES
|
||||||
global QUEUES
|
global QUEUES
|
||||||
LOG.debug(_('Binding %s to %s with key %s'),
|
LOG.debug(_('Binding %(queue)s to %(exchange)s with'
|
||||||
queue, exchange, routing_key)
|
' key %(routing_key)s') % locals())
|
||||||
EXCHANGES[exchange].bind(QUEUES[queue].push, routing_key)
|
EXCHANGES[exchange].bind(QUEUES[queue].push, routing_key)
|
||||||
|
|
||||||
def declare_consumer(self, queue, callback, *args, **kwargs):
|
def declare_consumer(self, queue, callback, *args, **kwargs):
|
||||||
@@ -117,7 +118,7 @@ class Backend(base.BaseBackend):
|
|||||||
content_type=content_type,
|
content_type=content_type,
|
||||||
content_encoding=content_encoding)
|
content_encoding=content_encoding)
|
||||||
message.result = True
|
message.result = True
|
||||||
LOG.debug(_('Getting from %s: %s'), queue, message)
|
LOG.debug(_('Getting from %(queue)s: %(message)s') % locals())
|
||||||
return message
|
return message
|
||||||
|
|
||||||
def prepare_message(self, message_data, delivery_mode,
|
def prepare_message(self, message_data, delivery_mode,
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ def _get_my_ip():
|
|||||||
(addr, port) = csock.getsockname()
|
(addr, port) = csock.getsockname()
|
||||||
csock.close()
|
csock.close()
|
||||||
return addr
|
return addr
|
||||||
except socket.gaierror as ex:
|
except socket.error as ex:
|
||||||
return "127.0.0.1"
|
return "127.0.0.1"
|
||||||
|
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ def _get_my_ip():
|
|||||||
DEFINE_string('my_ip', _get_my_ip(), 'host ip address')
|
DEFINE_string('my_ip', _get_my_ip(), 'host ip address')
|
||||||
DEFINE_list('region_list',
|
DEFINE_list('region_list',
|
||||||
[],
|
[],
|
||||||
'list of region=url pairs separated by commas')
|
'list of region=fqdn pairs separated by commas')
|
||||||
DEFINE_string('connection_type', 'libvirt', 'libvirt, xenapi or fake')
|
DEFINE_string('connection_type', 'libvirt', 'libvirt, xenapi or fake')
|
||||||
DEFINE_string('aws_access_key_id', 'admin', 'AWS Access ID')
|
DEFINE_string('aws_access_key_id', 'admin', 'AWS Access ID')
|
||||||
DEFINE_string('aws_secret_access_key', 'admin', 'AWS Access Key')
|
DEFINE_string('aws_secret_access_key', 'admin', 'AWS Access Key')
|
||||||
@@ -286,8 +286,8 @@ DEFINE_string('state_path', os.path.join(os.path.dirname(__file__), '../'),
|
|||||||
DEFINE_string('sql_connection',
|
DEFINE_string('sql_connection',
|
||||||
'sqlite:///$state_path/nova.sqlite',
|
'sqlite:///$state_path/nova.sqlite',
|
||||||
'connection string for sql database')
|
'connection string for sql database')
|
||||||
DEFINE_string('sql_idle_timeout',
|
DEFINE_integer('sql_idle_timeout',
|
||||||
'3600',
|
3600,
|
||||||
'timeout for idle sql database connections')
|
'timeout for idle sql database connections')
|
||||||
DEFINE_integer('sql_max_retries', 12, 'sql connection attempts')
|
DEFINE_integer('sql_max_retries', 12, 'sql connection attempts')
|
||||||
DEFINE_integer('sql_retry_interval', 10, 'sql connection retry interval')
|
DEFINE_integer('sql_retry_interval', 10, 'sql connection retry interval')
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import cStringIO
|
|||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import logging.handlers
|
import logging.handlers
|
||||||
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
from nova import flags
|
from nova import flags
|
||||||
@@ -191,6 +192,12 @@ class NovaLogger(logging.Logger):
|
|||||||
kwargs.pop('exc_info')
|
kwargs.pop('exc_info')
|
||||||
self.error(message, **kwargs)
|
self.error(message, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_exception(type, value, tb):
|
||||||
|
logging.root.critical(str(value), exc_info=(type, value, tb))
|
||||||
|
|
||||||
|
|
||||||
|
sys.excepthook = handle_exception
|
||||||
logging.setLoggerClass(NovaLogger)
|
logging.setLoggerClass(NovaLogger)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
nova/rpc.py
25
nova/rpc.py
@@ -46,7 +46,7 @@ LOG = logging.getLogger('nova.rpc')
|
|||||||
class Connection(carrot_connection.BrokerConnection):
|
class Connection(carrot_connection.BrokerConnection):
|
||||||
"""Connection instance object"""
|
"""Connection instance object"""
|
||||||
@classmethod
|
@classmethod
|
||||||
def instance(cls, new=False):
|
def instance(cls, new=True):
|
||||||
"""Returns the instance"""
|
"""Returns the instance"""
|
||||||
if new or not hasattr(cls, '_instance'):
|
if new or not hasattr(cls, '_instance'):
|
||||||
params = dict(hostname=FLAGS.rabbit_host,
|
params = dict(hostname=FLAGS.rabbit_host,
|
||||||
@@ -89,15 +89,16 @@ class Consumer(messaging.Consumer):
|
|||||||
self.failed_connection = False
|
self.failed_connection = False
|
||||||
break
|
break
|
||||||
except: # Catching all because carrot sucks
|
except: # Catching all because carrot sucks
|
||||||
LOG.exception(_("AMQP server on %s:%d is unreachable."
|
fl_host = FLAGS.rabbit_host
|
||||||
" Trying again in %d seconds.") % (
|
fl_port = FLAGS.rabbit_port
|
||||||
FLAGS.rabbit_host,
|
fl_intv = FLAGS.rabbit_retry_interval
|
||||||
FLAGS.rabbit_port,
|
LOG.exception(_("AMQP server on %(fl_host)s:%(fl_port)d is"
|
||||||
FLAGS.rabbit_retry_interval))
|
" unreachable. Trying again in %(fl_intv)d seconds.")
|
||||||
|
% locals())
|
||||||
self.failed_connection = True
|
self.failed_connection = True
|
||||||
if self.failed_connection:
|
if self.failed_connection:
|
||||||
LOG.exception(_("Unable to connect to AMQP server "
|
LOG.exception(_("Unable to connect to AMQP server "
|
||||||
"after %d tries. Shutting down."),
|
"after %d tries. Shutting down."),
|
||||||
FLAGS.rabbit_max_retries)
|
FLAGS.rabbit_max_retries)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
@@ -152,7 +153,7 @@ class TopicConsumer(Consumer):
|
|||||||
class AdapterConsumer(TopicConsumer):
|
class AdapterConsumer(TopicConsumer):
|
||||||
"""Calls methods on a proxy object based on method and args"""
|
"""Calls methods on a proxy object based on method and args"""
|
||||||
def __init__(self, connection=None, topic="broadcast", proxy=None):
|
def __init__(self, connection=None, topic="broadcast", proxy=None):
|
||||||
LOG.debug(_('Initing the Adapter Consumer for %s') % (topic))
|
LOG.debug(_('Initing the Adapter Consumer for %s') % topic)
|
||||||
self.proxy = proxy
|
self.proxy = proxy
|
||||||
super(AdapterConsumer, self).__init__(connection=connection,
|
super(AdapterConsumer, self).__init__(connection=connection,
|
||||||
topic=topic)
|
topic=topic)
|
||||||
@@ -167,7 +168,7 @@ class AdapterConsumer(TopicConsumer):
|
|||||||
|
|
||||||
Example: {'method': 'echo', 'args': {'value': 42}}
|
Example: {'method': 'echo', 'args': {'value': 42}}
|
||||||
"""
|
"""
|
||||||
LOG.debug(_('received %s') % (message_data))
|
LOG.debug(_('received %s') % message_data)
|
||||||
msg_id = message_data.pop('_msg_id', None)
|
msg_id = message_data.pop('_msg_id', None)
|
||||||
|
|
||||||
ctxt = _unpack_context(message_data)
|
ctxt = _unpack_context(message_data)
|
||||||
@@ -180,7 +181,7 @@ class AdapterConsumer(TopicConsumer):
|
|||||||
# messages stay in the queue indefinitely, so for now
|
# messages stay in the queue indefinitely, so for now
|
||||||
# we just log the message and send an error string
|
# we just log the message and send an error string
|
||||||
# back to the caller
|
# back to the caller
|
||||||
LOG.warn(_('no method for message: %s') % (message_data))
|
LOG.warn(_('no method for message: %s') % message_data)
|
||||||
msg_reply(msg_id, _('No method for message: %s') % message_data)
|
msg_reply(msg_id, _('No method for message: %s') % message_data)
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -245,7 +246,7 @@ def msg_reply(msg_id, reply=None, failure=None):
|
|||||||
LOG.error(_("Returning exception %s to caller"), message)
|
LOG.error(_("Returning exception %s to caller"), message)
|
||||||
LOG.error(tb)
|
LOG.error(tb)
|
||||||
failure = (failure[0].__name__, str(failure[1]), tb)
|
failure = (failure[0].__name__, str(failure[1]), tb)
|
||||||
conn = Connection.instance(True)
|
conn = Connection.instance()
|
||||||
publisher = DirectPublisher(connection=conn, msg_id=msg_id)
|
publisher = DirectPublisher(connection=conn, msg_id=msg_id)
|
||||||
try:
|
try:
|
||||||
publisher.send({'result': reply, 'failure': failure})
|
publisher.send({'result': reply, 'failure': failure})
|
||||||
@@ -318,7 +319,7 @@ def call(context, topic, msg):
|
|||||||
self.result = data['result']
|
self.result = data['result']
|
||||||
|
|
||||||
wait_msg = WaitMessage()
|
wait_msg = WaitMessage()
|
||||||
conn = Connection.instance(True)
|
conn = Connection.instance()
|
||||||
consumer = DirectConsumer(connection=conn, msg_id=msg_id)
|
consumer = DirectConsumer(connection=conn, msg_id=msg_id)
|
||||||
consumer.register_callback(wait_msg)
|
consumer.register_callback(wait_msg)
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,9 @@ class SimpleScheduler(chance.ChanceScheduler):
|
|||||||
def schedule_run_instance(self, context, instance_id, *_args, **_kwargs):
|
def schedule_run_instance(self, context, instance_id, *_args, **_kwargs):
|
||||||
"""Picks a host that is up and has the fewest running instances."""
|
"""Picks a host that is up and has the fewest running instances."""
|
||||||
instance_ref = db.instance_get(context, instance_id)
|
instance_ref = db.instance_get(context, instance_id)
|
||||||
if instance_ref['availability_zone'] and context.is_admin:
|
if (instance_ref['availability_zone']
|
||||||
|
and ':' in instance_ref['availability_zone']
|
||||||
|
and context.is_admin):
|
||||||
zone, _x, host = instance_ref['availability_zone'].partition(':')
|
zone, _x, host = instance_ref['availability_zone'].partition(':')
|
||||||
service = db.service_get_by_args(context.elevated(), host,
|
service = db.service_get_by_args(context.elevated(), host,
|
||||||
'nova-compute')
|
'nova-compute')
|
||||||
@@ -75,7 +77,9 @@ class SimpleScheduler(chance.ChanceScheduler):
|
|||||||
def schedule_create_volume(self, context, volume_id, *_args, **_kwargs):
|
def schedule_create_volume(self, context, volume_id, *_args, **_kwargs):
|
||||||
"""Picks a host that is up and has the fewest volumes."""
|
"""Picks a host that is up and has the fewest volumes."""
|
||||||
volume_ref = db.volume_get(context, volume_id)
|
volume_ref = db.volume_get(context, volume_id)
|
||||||
if (':' in volume_ref['availability_zone']) and context.is_admin:
|
if (volume_ref['availability_zone']
|
||||||
|
and ':' in volume_ref['availability_zone']
|
||||||
|
and context.is_admin):
|
||||||
zone, _x, host = volume_ref['availability_zone'].partition(':')
|
zone, _x, host = volume_ref['availability_zone'].partition(':')
|
||||||
service = db.service_get_by_args(context.elevated(), host,
|
service = db.service_get_by_args(context.elevated(), host,
|
||||||
'nova-volume')
|
'nova-volume')
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ from nova.auth import manager
|
|||||||
class FakeHttplibSocket(object):
|
class FakeHttplibSocket(object):
|
||||||
"""a fake socket implementation for httplib.HTTPResponse, trivial"""
|
"""a fake socket implementation for httplib.HTTPResponse, trivial"""
|
||||||
def __init__(self, response_string):
|
def __init__(self, response_string):
|
||||||
|
self.response_string = response_string
|
||||||
self._buffer = StringIO.StringIO(response_string)
|
self._buffer = StringIO.StringIO(response_string)
|
||||||
|
|
||||||
def makefile(self, _mode, _other):
|
def makefile(self, _mode, _other):
|
||||||
@@ -66,13 +67,16 @@ class FakeHttplibConnection(object):
|
|||||||
# For some reason, the response doesn't have "HTTP/1.0 " prepended; I
|
# For some reason, the response doesn't have "HTTP/1.0 " prepended; I
|
||||||
# guess that's a function the web server usually provides.
|
# guess that's a function the web server usually provides.
|
||||||
resp = "HTTP/1.0 %s" % resp
|
resp = "HTTP/1.0 %s" % resp
|
||||||
sock = FakeHttplibSocket(resp)
|
self.sock = FakeHttplibSocket(resp)
|
||||||
self.http_response = httplib.HTTPResponse(sock)
|
self.http_response = httplib.HTTPResponse(self.sock)
|
||||||
self.http_response.begin()
|
self.http_response.begin()
|
||||||
|
|
||||||
def getresponse(self):
|
def getresponse(self):
|
||||||
return self.http_response
|
return self.http_response
|
||||||
|
|
||||||
|
def getresponsebody(self):
|
||||||
|
return self.sock.response_string
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
"""Required for compatibility with boto/tornado"""
|
"""Required for compatibility with boto/tornado"""
|
||||||
pass
|
pass
|
||||||
@@ -104,7 +108,7 @@ class ApiEc2TestCase(test.TestCase):
|
|||||||
self.app = ec2.Authenticate(ec2.Requestify(ec2.Executor(),
|
self.app = ec2.Authenticate(ec2.Requestify(ec2.Executor(),
|
||||||
'nova.api.ec2.cloud.CloudController'))
|
'nova.api.ec2.cloud.CloudController'))
|
||||||
|
|
||||||
def expect_http(self, host=None, is_secure=False):
|
def expect_http(self, host=None, is_secure=False, api_version=None):
|
||||||
"""Returns a new EC2 connection"""
|
"""Returns a new EC2 connection"""
|
||||||
self.ec2 = boto.connect_ec2(
|
self.ec2 = boto.connect_ec2(
|
||||||
aws_access_key_id='fake',
|
aws_access_key_id='fake',
|
||||||
@@ -113,13 +117,31 @@ class ApiEc2TestCase(test.TestCase):
|
|||||||
region=regioninfo.RegionInfo(None, 'test', self.host),
|
region=regioninfo.RegionInfo(None, 'test', self.host),
|
||||||
port=8773,
|
port=8773,
|
||||||
path='/services/Cloud')
|
path='/services/Cloud')
|
||||||
|
if api_version:
|
||||||
|
self.ec2.APIVersion = api_version
|
||||||
|
|
||||||
self.mox.StubOutWithMock(self.ec2, 'new_http_connection')
|
self.mox.StubOutWithMock(self.ec2, 'new_http_connection')
|
||||||
http = FakeHttplibConnection(
|
self.http = FakeHttplibConnection(
|
||||||
self.app, '%s:8773' % (self.host), False)
|
self.app, '%s:8773' % (self.host), False)
|
||||||
# pylint: disable-msg=E1103
|
# pylint: disable-msg=E1103
|
||||||
self.ec2.new_http_connection(host, is_secure).AndReturn(http)
|
self.ec2.new_http_connection(host, is_secure).AndReturn(self.http)
|
||||||
return http
|
return self.http
|
||||||
|
|
||||||
|
def test_xmlns_version_matches_request_version(self):
|
||||||
|
self.expect_http(api_version='2010-10-30')
|
||||||
|
self.mox.ReplayAll()
|
||||||
|
|
||||||
|
user = self.manager.create_user('fake', 'fake', 'fake')
|
||||||
|
project = self.manager.create_project('fake', 'fake', 'fake')
|
||||||
|
|
||||||
|
# Any request should be fine
|
||||||
|
self.ec2.get_all_instances()
|
||||||
|
self.assertTrue(self.ec2.APIVersion in self.http.getresponsebody(),
|
||||||
|
'The version in the xmlns of the response does '
|
||||||
|
'not match the API version given in the request.')
|
||||||
|
|
||||||
|
self.manager.delete_project(project)
|
||||||
|
self.manager.delete_user(user)
|
||||||
|
|
||||||
def test_describe_instances(self):
|
def test_describe_instances(self):
|
||||||
"""Test that, after creating a user and a project, the describe
|
"""Test that, after creating a user and a project, the describe
|
||||||
|
|||||||
@@ -87,6 +87,16 @@ class CloudTestCase(test.TestCase):
|
|||||||
# NOTE(vish): create depends on pool, so just call helper directly
|
# NOTE(vish): create depends on pool, so just call helper directly
|
||||||
return cloud._gen_key(self.context, self.context.user.id, name)
|
return cloud._gen_key(self.context, self.context.user.id, name)
|
||||||
|
|
||||||
|
def test_describe_regions(self):
|
||||||
|
"""Makes sure describe regions runs without raising an exception"""
|
||||||
|
result = self.cloud.describe_regions(self.context)
|
||||||
|
self.assertEqual(len(result['regionInfo']), 1)
|
||||||
|
regions = FLAGS.region_list
|
||||||
|
FLAGS.region_list = ["one=test_host1", "two=test_host2"]
|
||||||
|
result = self.cloud.describe_regions(self.context)
|
||||||
|
self.assertEqual(len(result['regionInfo']), 2)
|
||||||
|
FLAGS.region_list = regions
|
||||||
|
|
||||||
def test_describe_addresses(self):
|
def test_describe_addresses(self):
|
||||||
"""Makes sure describe addresses runs without raising an exception"""
|
"""Makes sure describe addresses runs without raising an exception"""
|
||||||
address = "10.10.10.10"
|
address = "10.10.10.10"
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class ComputeTestCase(test.TestCase):
|
|||||||
self.manager = manager.AuthManager()
|
self.manager = manager.AuthManager()
|
||||||
self.user = self.manager.create_user('fake', 'fake', 'fake')
|
self.user = self.manager.create_user('fake', 'fake', 'fake')
|
||||||
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
||||||
self.context = context.get_admin_context()
|
self.context = context.RequestContext('fake', 'fake', False)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.manager.delete_user(self.user)
|
self.manager.delete_user(self.user)
|
||||||
@@ -69,6 +69,13 @@ class ComputeTestCase(test.TestCase):
|
|||||||
inst['ami_launch_index'] = 0
|
inst['ami_launch_index'] = 0
|
||||||
return db.instance_create(self.context, inst)['id']
|
return db.instance_create(self.context, inst)['id']
|
||||||
|
|
||||||
|
def _create_group(self):
|
||||||
|
values = {'name': 'testgroup',
|
||||||
|
'description': 'testgroup',
|
||||||
|
'user_id': self.user.id,
|
||||||
|
'project_id': self.project.id}
|
||||||
|
return db.security_group_create(self.context, values)
|
||||||
|
|
||||||
def test_create_instance_defaults_display_name(self):
|
def test_create_instance_defaults_display_name(self):
|
||||||
"""Verify that an instance cannot be created without a display_name."""
|
"""Verify that an instance cannot be created without a display_name."""
|
||||||
cases = [dict(), dict(display_name=None)]
|
cases = [dict(), dict(display_name=None)]
|
||||||
@@ -82,23 +89,55 @@ class ComputeTestCase(test.TestCase):
|
|||||||
|
|
||||||
def test_create_instance_associates_security_groups(self):
|
def test_create_instance_associates_security_groups(self):
|
||||||
"""Make sure create associates security groups"""
|
"""Make sure create associates security groups"""
|
||||||
values = {'name': 'default',
|
group = self._create_group()
|
||||||
'description': 'default',
|
|
||||||
'user_id': self.user.id,
|
|
||||||
'project_id': self.project.id}
|
|
||||||
group = db.security_group_create(self.context, values)
|
|
||||||
ref = self.compute_api.create(
|
ref = self.compute_api.create(
|
||||||
self.context,
|
self.context,
|
||||||
instance_type=FLAGS.default_instance_type,
|
instance_type=FLAGS.default_instance_type,
|
||||||
image_id=None,
|
image_id=None,
|
||||||
security_group=['default'])
|
security_group=['testgroup'])
|
||||||
try:
|
try:
|
||||||
self.assertEqual(len(db.security_group_get_by_instance(
|
self.assertEqual(len(db.security_group_get_by_instance(
|
||||||
self.context, ref[0]['id'])), 1)
|
self.context, ref[0]['id'])), 1)
|
||||||
|
group = db.security_group_get(self.context, group['id'])
|
||||||
|
self.assert_(len(group.instances) == 1)
|
||||||
finally:
|
finally:
|
||||||
db.security_group_destroy(self.context, group['id'])
|
db.security_group_destroy(self.context, group['id'])
|
||||||
db.instance_destroy(self.context, ref[0]['id'])
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
|
||||||
|
def test_destroy_instance_disassociates_security_groups(self):
|
||||||
|
"""Make sure destroying disassociates security groups"""
|
||||||
|
group = self._create_group()
|
||||||
|
|
||||||
|
ref = self.compute_api.create(
|
||||||
|
self.context,
|
||||||
|
instance_type=FLAGS.default_instance_type,
|
||||||
|
image_id=None,
|
||||||
|
security_group=['testgroup'])
|
||||||
|
try:
|
||||||
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
group = db.security_group_get(self.context, group['id'])
|
||||||
|
self.assert_(len(group.instances) == 0)
|
||||||
|
finally:
|
||||||
|
db.security_group_destroy(self.context, group['id'])
|
||||||
|
|
||||||
|
def test_destroy_security_group_disassociates_instances(self):
|
||||||
|
"""Make sure destroying security groups disassociates instances"""
|
||||||
|
group = self._create_group()
|
||||||
|
|
||||||
|
ref = self.compute_api.create(
|
||||||
|
self.context,
|
||||||
|
instance_type=FLAGS.default_instance_type,
|
||||||
|
image_id=None,
|
||||||
|
security_group=['testgroup'])
|
||||||
|
|
||||||
|
try:
|
||||||
|
db.security_group_destroy(self.context, group['id'])
|
||||||
|
group = db.security_group_get(context.get_admin_context(
|
||||||
|
read_deleted=True), group['id'])
|
||||||
|
self.assert_(len(group.instances) == 0)
|
||||||
|
finally:
|
||||||
|
db.instance_destroy(self.context, ref[0]['id'])
|
||||||
|
|
||||||
def test_run_terminate(self):
|
def test_run_terminate(self):
|
||||||
"""Make sure it is possible to run and terminate instance"""
|
"""Make sure it is possible to run and terminate instance"""
|
||||||
instance_id = self._create_instance()
|
instance_id = self._create_instance()
|
||||||
|
|||||||
100
nova/tests/test_localization.py
Normal file
100
nova/tests/test_localization.py
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||||
|
#
|
||||||
|
# Copyright 2011 OpenStack LLC
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
import glob
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import nova
|
||||||
|
|
||||||
|
|
||||||
|
class LocalizationTestCase(unittest.TestCase):
|
||||||
|
def test_multiple_positional_format_placeholders(self):
|
||||||
|
pat = re.compile("\W_\(")
|
||||||
|
single_pat = re.compile("\W%\W")
|
||||||
|
root_path = os.path.dirname(nova.__file__)
|
||||||
|
problems = {}
|
||||||
|
for root, dirs, files in os.walk(root_path):
|
||||||
|
for fname in files:
|
||||||
|
if not fname.endswith(".py"):
|
||||||
|
continue
|
||||||
|
pth = os.path.join(root, fname)
|
||||||
|
txt = fulltext = file(pth).read()
|
||||||
|
txt_lines = fulltext.splitlines()
|
||||||
|
if not pat.search(txt):
|
||||||
|
continue
|
||||||
|
problems[pth] = []
|
||||||
|
pos = txt.find("_(")
|
||||||
|
while pos > -1:
|
||||||
|
# Make sure that this isn't part of a dunder;
|
||||||
|
# e.g., __init__(...
|
||||||
|
# or something like 'self.assert_(...'
|
||||||
|
test_txt = txt[pos - 1: pos + 10]
|
||||||
|
if not (pat.search(test_txt)):
|
||||||
|
txt = txt[pos + 2:]
|
||||||
|
pos = txt.find("_(")
|
||||||
|
continue
|
||||||
|
pos += 2
|
||||||
|
txt = txt[pos:]
|
||||||
|
innerChars = []
|
||||||
|
# Count pairs of open/close parens until _() closing
|
||||||
|
# paren is found.
|
||||||
|
parenCount = 1
|
||||||
|
pos = 0
|
||||||
|
while parenCount > 0:
|
||||||
|
char = txt[pos]
|
||||||
|
if char == "(":
|
||||||
|
parenCount += 1
|
||||||
|
elif char == ")":
|
||||||
|
parenCount -= 1
|
||||||
|
innerChars.append(char)
|
||||||
|
pos += 1
|
||||||
|
inner_all = "".join(innerChars)
|
||||||
|
# Filter out '%%' and '%('
|
||||||
|
inner = inner_all.replace("%%", "").replace("%(", "")
|
||||||
|
# Filter out the single '%' operators
|
||||||
|
inner = single_pat.sub("", inner)
|
||||||
|
# Within the remaining content, count %
|
||||||
|
fmtCount = inner.count("%")
|
||||||
|
if fmtCount > 1:
|
||||||
|
inner_first = inner_all.splitlines()[0]
|
||||||
|
lns = ["%s" % (p + 1)
|
||||||
|
for p, t in enumerate(txt_lines)
|
||||||
|
if inner_first in t]
|
||||||
|
lnums = ", ".join(lns)
|
||||||
|
# Using ugly string concatenation to avoid having
|
||||||
|
# this test fail itself.
|
||||||
|
inner_all = "_" + "(" + "%s" % inner_all
|
||||||
|
problems[pth].append("Line: %s Text: %s" %
|
||||||
|
(lnums, inner_all))
|
||||||
|
# Look for more
|
||||||
|
pos = txt.find("_(")
|
||||||
|
if not problems[pth]:
|
||||||
|
del problems[pth]
|
||||||
|
if problems:
|
||||||
|
out = ["Problem(s) found in localized string formatting",
|
||||||
|
"(see http://www.gnu.org/software/hello/manual/"
|
||||||
|
"gettext/Python.html for more information)",
|
||||||
|
"",
|
||||||
|
" ------------ Files to fix ------------"]
|
||||||
|
for pth in problems:
|
||||||
|
out.append(" %s:" % pth)
|
||||||
|
for val in set(problems[pth]):
|
||||||
|
out.append(" %s" % val)
|
||||||
|
raise AssertionError("\n".join(out))
|
||||||
@@ -86,7 +86,8 @@ class RpcTestCase(test.TestCase):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def echo(context, queue, value):
|
def echo(context, queue, value):
|
||||||
"""Calls echo in the passed queue"""
|
"""Calls echo in the passed queue"""
|
||||||
LOG.debug(_("Nested received %s, %s"), queue, value)
|
LOG.debug(_("Nested received %(queue)s, %(value)s")
|
||||||
|
% locals())
|
||||||
ret = rpc.call(context,
|
ret = rpc.call(context,
|
||||||
queue,
|
queue,
|
||||||
{"method": "echo",
|
{"method": "echo",
|
||||||
|
|||||||
@@ -221,7 +221,12 @@ class IptablesFirewallTestCase(test.TestCase):
|
|||||||
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
self.project = self.manager.create_project('fake', 'fake', 'fake')
|
||||||
self.context = context.RequestContext('fake', 'fake')
|
self.context = context.RequestContext('fake', 'fake')
|
||||||
self.network = utils.import_object(FLAGS.network_manager)
|
self.network = utils.import_object(FLAGS.network_manager)
|
||||||
self.fw = libvirt_conn.IptablesFirewallDriver()
|
|
||||||
|
class FakeLibvirtConnection(object):
|
||||||
|
pass
|
||||||
|
self.fake_libvirt_connection = FakeLibvirtConnection()
|
||||||
|
self.fw = libvirt_conn.IptablesFirewallDriver(
|
||||||
|
get_connection=lambda: self.fake_libvirt_connection)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.manager.delete_project(self.project)
|
self.manager.delete_project(self.project)
|
||||||
@@ -256,7 +261,7 @@ class IptablesFirewallTestCase(test.TestCase):
|
|||||||
':FORWARD ACCEPT [0:0]',
|
':FORWARD ACCEPT [0:0]',
|
||||||
':OUTPUT ACCEPT [349256:75777230]',
|
':OUTPUT ACCEPT [349256:75777230]',
|
||||||
'COMMIT',
|
'COMMIT',
|
||||||
'# Completed on Tue Jan 18 23:47:56 2011'
|
'# Completed on Tue Jan 18 23:47:56 2011',
|
||||||
]
|
]
|
||||||
|
|
||||||
def test_static_filters(self):
|
def test_static_filters(self):
|
||||||
@@ -474,6 +479,19 @@ class NWFilterTestCase(test.TestCase):
|
|||||||
'project_id': 'fake'})
|
'project_id': 'fake'})
|
||||||
inst_id = instance_ref['id']
|
inst_id = instance_ref['id']
|
||||||
|
|
||||||
|
ip = '10.11.12.13'
|
||||||
|
|
||||||
|
network_ref = db.project_get_network(self.context,
|
||||||
|
'fake')
|
||||||
|
|
||||||
|
fixed_ip = {'address': ip,
|
||||||
|
'network_id': network_ref['id']}
|
||||||
|
|
||||||
|
admin_ctxt = context.get_admin_context()
|
||||||
|
db.fixed_ip_create(admin_ctxt, fixed_ip)
|
||||||
|
db.fixed_ip_update(admin_ctxt, ip, {'allocated': True,
|
||||||
|
'instance_id': instance_ref['id']})
|
||||||
|
|
||||||
def _ensure_all_called():
|
def _ensure_all_called():
|
||||||
instance_filter = 'nova-instance-%s' % instance_ref['name']
|
instance_filter = 'nova-instance-%s' % instance_ref['name']
|
||||||
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
|
secgroup_filter = 'nova-secgroup-%s' % self.security_group['id']
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ from nose import config
|
|||||||
from nose import result
|
from nose import result
|
||||||
from nose import core
|
from nose import core
|
||||||
|
|
||||||
|
from nova import log as logging
|
||||||
|
|
||||||
|
|
||||||
class NovaTestResult(result.TextTestResult):
|
class NovaTestResult(result.TextTestResult):
|
||||||
def __init__(self, *args, **kw):
|
def __init__(self, *args, **kw):
|
||||||
@@ -58,6 +60,7 @@ class NovaTestRunner(core.TextTestRunner):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
logging.basicConfig()
|
||||||
c = config.Config(stream=sys.stdout,
|
c = config.Config(stream=sys.stdout,
|
||||||
env=os.environ,
|
env=os.environ,
|
||||||
verbosity=3,
|
verbosity=3,
|
||||||
|
|||||||
Reference in New Issue
Block a user