merged trunk
This commit is contained in:
@@ -13,3 +13,7 @@ nova/vcsversion.py
|
||||
clean.sqlite
|
||||
run_tests.log
|
||||
tests.sqlite
|
||||
nova/tests/instance-*
|
||||
tags
|
||||
.coverage
|
||||
covhtml
|
||||
|
||||
1
.mailmap
1
.mailmap
@@ -14,6 +14,7 @@
|
||||
<code@term.ie> <github@anarkystic.com>
|
||||
<code@term.ie> <termie@preciousroy.local>
|
||||
<corywright@gmail.com> <cory.wright@rackspace.com>
|
||||
<dan@nicira.com> <danwent@dan-xs3-cs>
|
||||
<devin.carlen@gmail.com> <devcamcar@illian.local>
|
||||
<ewan.mellor@citrix.com> <emellor@silver>
|
||||
<itoumsn@nttdata.co.jp> <itoumsn@shayol>
|
||||
|
||||
4
Authors
4
Authors
@@ -1,4 +1,5 @@
|
||||
Adam Gandelman <adamg@canonical.com>
|
||||
Adam Johnson <adjohn@gmail.com>
|
||||
Alex Meade <alex.meade@rackspace.com>
|
||||
Alexander Sakhnov <asakhnov@mirantis.com>
|
||||
Andrey Brindeyev <abrindeyev@griddynamics.com>
|
||||
@@ -8,6 +9,7 @@ Anne Gentle <anne@openstack.org>
|
||||
Anthony Young <sleepsonthefloor@gmail.com>
|
||||
Antony Messerli <ant@openstack.org>
|
||||
Armando Migliaccio <Armando.Migliaccio@eu.citrix.com>
|
||||
Arvind Somya <asomya@cisco.com>
|
||||
Bilal Akhtar <bilalakhtar@ubuntu.com>
|
||||
Brian Lamar <brian.lamar@rackspace.com>
|
||||
Brian Schott <bschott@isi.edu>
|
||||
@@ -19,6 +21,7 @@ Christian Berendt <berendt@b1-systems.de>
|
||||
Chuck Short <zulcss@ubuntu.com>
|
||||
Cory Wright <corywright@gmail.com>
|
||||
Dan Prince <dan.prince@rackspace.com>
|
||||
Dan Wendlandt <dan@nicira.com>
|
||||
Dave Walker <DaveWalker@ubuntu.com>
|
||||
David Pravec <David.Pravec@danix.org>
|
||||
Dean Troyer <dtroyer@gmail.com>
|
||||
@@ -83,6 +86,7 @@ Rick Harris <rconradharris@gmail.com>
|
||||
Rob Kost <kost@isi.edu>
|
||||
Ryan Lane <rlane@wikimedia.org>
|
||||
Ryan Lucio <rlucio@internap.com>
|
||||
Ryu Ishimoto <ryu@midokura.jp>
|
||||
Salvatore Orlando <salvatore.orlando@eu.citrix.com>
|
||||
Sandy Walsh <sandy.walsh@rackspace.com>
|
||||
Sateesh Chodapuneedi <sateesh.chodapuneedi@citrix.com>
|
||||
|
||||
407
bin/nova-manage
407
bin/nova-manage
@@ -61,6 +61,7 @@ import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
# If ../nova/__init__.py exists, add ../ to Python search path, so that
|
||||
# it will override what happens to be installed in /usr/(local/)lib/python...
|
||||
@@ -103,6 +104,14 @@ flags.DEFINE_flag(flags.HelpshortFlag())
|
||||
flags.DEFINE_flag(flags.HelpXMLFlag())
|
||||
|
||||
|
||||
# Decorators for actions
|
||||
def args(*args, **kwargs):
|
||||
def _decorator(func):
|
||||
func.__dict__.setdefault('options', []).insert(0, (args, kwargs))
|
||||
return func
|
||||
return _decorator
|
||||
|
||||
|
||||
def param2id(object_id):
|
||||
"""Helper function to convert various id types to internal id.
|
||||
args: [object_id], e.g. 'vol-0000000a' or 'volume-0000000a' or '10'
|
||||
@@ -120,10 +129,11 @@ class VpnCommands(object):
|
||||
self.manager = manager.AuthManager()
|
||||
self.pipe = pipelib.CloudPipe()
|
||||
|
||||
@args('--project', dest="project", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def list(self, project=None):
|
||||
"""Print a listing of the VPN data for one or all projects.
|
||||
"""Print a listing of the VPN data for one or all projects."""
|
||||
|
||||
args: [project=all]"""
|
||||
print "%-12s\t" % 'project',
|
||||
print "%-20s\t" % 'ip:port',
|
||||
print "%-20s\t" % 'private_ip',
|
||||
@@ -165,17 +175,23 @@ class VpnCommands(object):
|
||||
self.pipe.launch_vpn_instance(p.id)
|
||||
time.sleep(10)
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def run(self, project_id):
|
||||
"""Start the VPN for a given project."""
|
||||
self.pipe.launch_vpn_instance(project_id)
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--ip', dest="ip", metavar='<IP Address>', help='IP Address')
|
||||
@args('--port', dest="port", metavar='<Port>', help='Port')
|
||||
def change(self, project_id, ip, port):
|
||||
"""Change the ip and port for a vpn.
|
||||
|
||||
this will update all networks associated with a project
|
||||
not sure if that's the desired behavior or not, patches accepted
|
||||
|
||||
args: project, ip, port"""
|
||||
"""
|
||||
# TODO(tr3buchet): perhaps this shouldn't update all networks
|
||||
# associated with a project in the future
|
||||
project = self.manager.get_project(project_id)
|
||||
@@ -210,10 +226,10 @@ class ShellCommands(object):
|
||||
Falls back to Python shell if unavailable"""
|
||||
self.run('python')
|
||||
|
||||
@args('--shell', dest="shell", metavar='<bpython|ipython|python >',
|
||||
help='Python shell')
|
||||
def run(self, shell=None):
|
||||
"""Runs a Python interactive interpreter.
|
||||
|
||||
args: [shell=bpython]"""
|
||||
"""Runs a Python interactive interpreter."""
|
||||
if not shell:
|
||||
shell = 'bpython'
|
||||
|
||||
@@ -247,6 +263,7 @@ class ShellCommands(object):
|
||||
readline.parse_and_bind("tab:complete")
|
||||
code.interact()
|
||||
|
||||
@args('--path', dest='path', metavar='<path>', help='Script path')
|
||||
def script(self, path):
|
||||
"""Runs the script from the specifed path with flags set properly.
|
||||
arguments: path"""
|
||||
@@ -259,10 +276,13 @@ class RoleCommands(object):
|
||||
def __init__(self):
|
||||
self.manager = manager.AuthManager()
|
||||
|
||||
@args('--user', dest="user", metavar='<user name>', help='User name')
|
||||
@args('--role', dest="role", metavar='<user role>', help='User role')
|
||||
@args('--project', dest="project", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def add(self, user, role, project=None):
|
||||
"""adds role to user
|
||||
if project is specified, adds project specific role
|
||||
arguments: user, role [project]"""
|
||||
if project is specified, adds project specific role"""
|
||||
if project:
|
||||
projobj = self.manager.get_project(project)
|
||||
if not projobj.has_member(user):
|
||||
@@ -270,17 +290,23 @@ class RoleCommands(object):
|
||||
return
|
||||
self.manager.add_role(user, role, project)
|
||||
|
||||
@args('--user', dest="user", metavar='<user name>', help='User name')
|
||||
@args('--role', dest="role", metavar='<user role>', help='User role')
|
||||
@args('--project', dest="project", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def has(self, user, role, project=None):
|
||||
"""checks to see if user has role
|
||||
if project is specified, returns True if user has
|
||||
the global role and the project role
|
||||
arguments: user, role [project]"""
|
||||
the global role and the project role"""
|
||||
print self.manager.has_role(user, role, project)
|
||||
|
||||
@args('--user', dest="user", metavar='<user name>', help='User name')
|
||||
@args('--role', dest="role", metavar='<user role>', help='User role')
|
||||
@args('--project', dest="project", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def remove(self, user, role, project=None):
|
||||
"""removes role from user
|
||||
if project is specified, removes project specific role
|
||||
arguments: user, role [project]"""
|
||||
if project is specified, removes project specific role"""
|
||||
self.manager.remove_role(user, role, project)
|
||||
|
||||
|
||||
@@ -304,32 +330,37 @@ class UserCommands(object):
|
||||
def __init__(self):
|
||||
self.manager = manager.AuthManager()
|
||||
|
||||
@args('--name', dest="name", metavar='<admin name>', help='Admin name')
|
||||
@args('--access', dest="access", metavar='<access>', help='Access')
|
||||
@args('--secret', dest="secret", metavar='<secret>', help='Secret')
|
||||
def admin(self, name, access=None, secret=None):
|
||||
"""creates a new admin and prints exports
|
||||
arguments: name [access] [secret]"""
|
||||
"""creates a new admin and prints exports"""
|
||||
try:
|
||||
user = self.manager.create_user(name, access, secret, True)
|
||||
except exception.DBError, e:
|
||||
_db_error(e)
|
||||
self._print_export(user)
|
||||
|
||||
@args('--name', dest="name", metavar='<name>', help='User name')
|
||||
@args('--access', dest="access", metavar='<access>', help='Access')
|
||||
@args('--secret', dest="secret", metavar='<secret>', help='Secret')
|
||||
def create(self, name, access=None, secret=None):
|
||||
"""creates a new user and prints exports
|
||||
arguments: name [access] [secret]"""
|
||||
"""creates a new user and prints exports"""
|
||||
try:
|
||||
user = self.manager.create_user(name, access, secret, False)
|
||||
except exception.DBError, e:
|
||||
_db_error(e)
|
||||
self._print_export(user)
|
||||
|
||||
@args('--name', dest="name", metavar='<name>', help='User name')
|
||||
def delete(self, name):
|
||||
"""deletes an existing user
|
||||
arguments: name"""
|
||||
self.manager.delete_user(name)
|
||||
|
||||
@args('--name', dest="name", metavar='<admin name>', help='User name')
|
||||
def exports(self, name):
|
||||
"""prints access and secrets for user in export format
|
||||
arguments: name"""
|
||||
"""prints access and secrets for user in export format"""
|
||||
user = self.manager.get_user(name)
|
||||
if user:
|
||||
self._print_export(user)
|
||||
@@ -337,11 +368,17 @@ class UserCommands(object):
|
||||
print "User %s doesn't exist" % name
|
||||
|
||||
def list(self):
|
||||
"""lists all users
|
||||
arguments: <none>"""
|
||||
"""lists all users"""
|
||||
for user in self.manager.get_users():
|
||||
print user.name
|
||||
|
||||
@args('--name', dest="name", metavar='<name>', help='User name')
|
||||
@args('--access', dest="access_key", metavar='<access>',
|
||||
help='Access key')
|
||||
@args('--secret', dest="secret_key", metavar='<secret>',
|
||||
help='Secret key')
|
||||
@args('--is_admin', dest='is_admin', metavar="<'T'|'F'>",
|
||||
help='Is admin?')
|
||||
def modify(self, name, access_key, secret_key, is_admin):
|
||||
"""update a users keys & admin flag
|
||||
arguments: accesskey secretkey admin
|
||||
@@ -355,9 +392,11 @@ class UserCommands(object):
|
||||
is_admin = False
|
||||
self.manager.modify_user(name, access_key, secret_key, is_admin)
|
||||
|
||||
@args('--name', dest="user_id", metavar='<name>', help='User name')
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def revoke(self, user_id, project_id=None):
|
||||
"""revoke certs for a user
|
||||
arguments: user_id [project_id]"""
|
||||
"""revoke certs for a user"""
|
||||
if project_id:
|
||||
crypto.revoke_certs_by_user_and_project(user_id, project_id)
|
||||
else:
|
||||
@@ -370,45 +409,62 @@ class ProjectCommands(object):
|
||||
def __init__(self):
|
||||
self.manager = manager.AuthManager()
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="user_id", metavar='<name>', help='User name')
|
||||
def add(self, project_id, user_id):
|
||||
"""Adds user to project
|
||||
arguments: project_id user_id"""
|
||||
"""Adds user to project"""
|
||||
try:
|
||||
self.manager.add_to_project(user_id, project_id)
|
||||
except exception.UserNotFound as ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||
@args('--project', dest="name", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="project_manager", metavar='<user>',
|
||||
help='Project manager')
|
||||
@args('--desc', dest="description", metavar='<description>',
|
||||
help='Description')
|
||||
def create(self, name, project_manager, description=None):
|
||||
"""Creates a new project
|
||||
arguments: name project_manager [description]"""
|
||||
"""Creates a new project"""
|
||||
try:
|
||||
self.manager.create_project(name, project_manager, description)
|
||||
except exception.UserNotFound as ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||
@args('--project', dest="name", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="project_manager", metavar='<user>',
|
||||
help='Project manager')
|
||||
@args('--desc', dest="description", metavar='<description>',
|
||||
help='Description')
|
||||
def modify(self, name, project_manager, description=None):
|
||||
"""Modifies a project
|
||||
arguments: name project_manager [description]"""
|
||||
"""Modifies a project"""
|
||||
try:
|
||||
self.manager.modify_project(name, project_manager, description)
|
||||
except exception.UserNotFound as ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||
@args('--project', dest="name", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def delete(self, name):
|
||||
"""Deletes an existing project
|
||||
arguments: name"""
|
||||
"""Deletes an existing project"""
|
||||
try:
|
||||
self.manager.delete_project(name)
|
||||
except exception.ProjectNotFound as ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="user_id", metavar='<name>', help='User name')
|
||||
@args('--file', dest="filename", metavar='<filename>',
|
||||
help='File name(Default: novarc)')
|
||||
def environment(self, project_id, user_id, filename='novarc'):
|
||||
"""Exports environment variables to an sourcable file
|
||||
arguments: project_id user_id [filename='novarc]"""
|
||||
"""Exports environment variables to an sourcable file"""
|
||||
try:
|
||||
rc = self.manager.get_environment_rc(user_id, project_id)
|
||||
except (exception.UserNotFound, exception.ProjectNotFound) as ex:
|
||||
@@ -420,15 +476,18 @@ class ProjectCommands(object):
|
||||
with open(filename, 'w') as f:
|
||||
f.write(rc)
|
||||
|
||||
@args('--user', dest="username", metavar='<username>', help='User name')
|
||||
def list(self, username=None):
|
||||
"""Lists all projects
|
||||
arguments: [username]"""
|
||||
"""Lists all projects"""
|
||||
for project in self.manager.get_projects(username):
|
||||
print project.name
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--key', dest="key", metavar='<key>', help='Key')
|
||||
@args('--value', dest="value", metavar='<value>', help='Value')
|
||||
def quota(self, project_id, key=None, value=None):
|
||||
"""Set or display quotas for project
|
||||
arguments: project_id [key] [value]"""
|
||||
"""Set or display quotas for project"""
|
||||
ctxt = context.get_admin_context()
|
||||
if key:
|
||||
if value.lower() == 'unlimited':
|
||||
@@ -443,18 +502,21 @@ class ProjectCommands(object):
|
||||
value = 'unlimited'
|
||||
print '%s: %s' % (key, value)
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="user_id", metavar='<name>', help='User name')
|
||||
def remove(self, project_id, user_id):
|
||||
"""Removes user from project
|
||||
arguments: project_id user_id"""
|
||||
"""Removes user from project"""
|
||||
try:
|
||||
self.manager.remove_from_project(user_id, project_id)
|
||||
except (exception.UserNotFound, exception.ProjectNotFound) as ex:
|
||||
print ex
|
||||
raise
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
def scrub(self, project_id):
|
||||
"""Deletes data associated with project
|
||||
arguments: project_id"""
|
||||
"""Deletes data associated with project"""
|
||||
admin_context = context.get_admin_context()
|
||||
networks = db.project_get_networks(admin_context, project_id)
|
||||
for network in networks:
|
||||
@@ -463,9 +525,13 @@ class ProjectCommands(object):
|
||||
for group in groups:
|
||||
db.security_group_destroy(admin_context, group['id'])
|
||||
|
||||
@args('--project', dest="project_id", metavar='<Project name>',
|
||||
help='Project name')
|
||||
@args('--user', dest="user_id", metavar='<name>', help='User name')
|
||||
@args('--file', dest="filename", metavar='<filename>',
|
||||
help='File name(Default: nova.zip)')
|
||||
def zipfile(self, project_id, user_id, filename='nova.zip'):
|
||||
"""Exports credentials for project to a zip file
|
||||
arguments: project_id user_id [filename='nova.zip]"""
|
||||
"""Exports credentials for project to a zip file"""
|
||||
try:
|
||||
zip_file = self.manager.get_credentials(user_id, project_id)
|
||||
if filename == "-":
|
||||
@@ -482,9 +548,9 @@ class ProjectCommands(object):
|
||||
' nova-manage network create pvt 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.")
|
||||
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.")
|
||||
|
||||
AccountCommands = ProjectCommands
|
||||
|
||||
@@ -492,8 +558,9 @@ AccountCommands = ProjectCommands
|
||||
class FixedIpCommands(object):
|
||||
"""Class for managing fixed ip."""
|
||||
|
||||
@args('--host', dest="host", metavar='<host>', help='Host')
|
||||
def list(self, host=None):
|
||||
"""Lists all fixed ips (optionally by host) arguments: [host]"""
|
||||
"""Lists all fixed ips (optionally by host)"""
|
||||
ctxt = context.get_admin_context()
|
||||
|
||||
try:
|
||||
@@ -528,23 +595,23 @@ class FixedIpCommands(object):
|
||||
class FloatingIpCommands(object):
|
||||
"""Class for managing floating ip."""
|
||||
|
||||
@args('--ip_range', dest="range", metavar='<range>', help='IP range')
|
||||
def create(self, range):
|
||||
"""Creates floating ips for zone by range
|
||||
arguments: ip_range"""
|
||||
"""Creates floating ips for zone by range"""
|
||||
for address in netaddr.IPNetwork(range):
|
||||
db.floating_ip_create(context.get_admin_context(),
|
||||
{'address': str(address)})
|
||||
|
||||
@args('--ip_range', dest="ip_range", metavar='<range>', help='IP range')
|
||||
def delete(self, ip_range):
|
||||
"""Deletes floating ips by range
|
||||
arguments: range"""
|
||||
"""Deletes floating ips by range"""
|
||||
for address in netaddr.IPNetwork(ip_range):
|
||||
db.floating_ip_destroy(context.get_admin_context(),
|
||||
str(address))
|
||||
|
||||
@args('--host', dest="host", metavar='<host>', help='Host')
|
||||
def list(self, host=None):
|
||||
"""Lists all floating ips (optionally by host)
|
||||
arguments: [host]
|
||||
Note: if host is given, only active floating IPs are returned"""
|
||||
ctxt = context.get_admin_context()
|
||||
if host is None:
|
||||
@@ -563,21 +630,32 @@ class FloatingIpCommands(object):
|
||||
class NetworkCommands(object):
|
||||
"""Class for managing networks."""
|
||||
|
||||
@args('--label', dest="label", metavar='<label>',
|
||||
help='Label(ex: public)')
|
||||
@args('--network', dest="fixed_range", metavar='<x.x.x.x/yy>',
|
||||
help='Network')
|
||||
@args('--num_networks', dest="num_networks", metavar='<number>',
|
||||
help='How many networks create')
|
||||
@args('--network_size', dest="network_size", metavar='<number>',
|
||||
help='How many hosts in network')
|
||||
@args('--vlan', dest="vlan_start", metavar='<vlan id>', help='vlan id')
|
||||
@args('--vpn', dest="vpn_start", help='vpn start')
|
||||
@args('--fixed_range_v6', dest="fixed_range_v6", help='fixed ipv6 range')
|
||||
@args('--gateway_v6', dest="gateway_v6", help='ipv6 gateway')
|
||||
@args('--flat_network_bridge', dest="flat_network_bridge",
|
||||
metavar='<flat network bridge>', help='Flat_network_bridge')
|
||||
@args('--bridge_interface', dest="bridge_interface",
|
||||
metavar='<bridge interface>', help='Bridge_interface')
|
||||
@args('--multi_host', dest="multi_host", metavar="<'T'|'F'>",
|
||||
help='Multi host')
|
||||
@args('--dns1', dest="dns1", metavar="<DNS Address>", help='First DNS')
|
||||
@args('--dns2', dest="dns2", metavar="<DNS Address>", help='Second DNS')
|
||||
def create(self, label=None, fixed_range=None, num_networks=None,
|
||||
network_size=None, multi_host=None, vlan_start=None,
|
||||
vpn_start=None, fixed_range_v6=None, gateway_v6=None,
|
||||
flat_network_bridge=None, bridge_interface=None,
|
||||
dns1=None, dns2=None):
|
||||
"""Creates fixed ips for host by range
|
||||
arguments: label, fixed_range, [num_networks=FLAG],
|
||||
[network_size=FLAG], [multi_host=FLAG], [vlan_start=FLAG],
|
||||
[vpn_start=FLAG], [fixed_range_v6=FLAG], [gateway_v6=FLAG],
|
||||
[flat_network_bridge=FLAG], [bridge_interface=FLAG]
|
||||
[dns1=FLAG], [dns2]
|
||||
If you wish to use a later argument fill in the gaps with ""s
|
||||
Ex: network create private 10.0.0.0/8 1 16 T "" "" "" "" xenbr1 eth1
|
||||
network create private 10.0.0.0/8 1 16
|
||||
"""
|
||||
"""Creates fixed ips for host by range"""
|
||||
if not label:
|
||||
msg = _('a label (ex: public) is required to create networks.')
|
||||
print msg
|
||||
@@ -650,6 +728,8 @@ class NetworkCommands(object):
|
||||
network.vlan,
|
||||
network.project_id)
|
||||
|
||||
@args('--network', dest="fixed_range", metavar='<x.x.x.x/yy>',
|
||||
help='Network to delete')
|
||||
def delete(self, fixed_range):
|
||||
"""Deletes a network"""
|
||||
network = db.network_get_by_cidr(context.get_admin_context(), \
|
||||
@@ -663,12 +743,10 @@ class NetworkCommands(object):
|
||||
class VmCommands(object):
|
||||
"""Class for mangaging VM instances."""
|
||||
|
||||
@args('--host', dest="host", metavar='<host>', help='Host')
|
||||
def list(self, host=None):
|
||||
"""Show a list of all instances
|
||||
"""Show a list of all instances"""
|
||||
|
||||
:param host: show all instance on specified host.
|
||||
:param instance: show specificed instance.
|
||||
"""
|
||||
print "%-10s %-15s %-10s %-10s %-26s %-9s %-9s %-9s" \
|
||||
" %-10s %-10s %-10s %-5s" % (
|
||||
_('instance'),
|
||||
@@ -706,13 +784,11 @@ class VmCommands(object):
|
||||
instance['availability_zone'],
|
||||
instance['launch_index'])
|
||||
|
||||
@args('--ec2_id', dest='ec2_id', metavar='<ec2 id>', help='EC2 ID')
|
||||
@args('--dest', dest='dest', metavar='<Destanation>',
|
||||
help='destanation node')
|
||||
def live_migration(self, ec2_id, dest):
|
||||
"""Migrates a running instance to a new machine.
|
||||
|
||||
:param ec2_id: instance id which comes from euca-describe-instance.
|
||||
:param dest: destination host name.
|
||||
|
||||
"""
|
||||
"""Migrates a running instance to a new machine."""
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
instance_id = ec2utils.ec2_id_to_id(ec2_id)
|
||||
@@ -742,9 +818,13 @@ class VmCommands(object):
|
||||
class ServiceCommands(object):
|
||||
"""Enable and disable running services"""
|
||||
|
||||
@args('--host', dest='host', metavar='<host>', help='Host')
|
||||
@args('--service', dest='service', metavar='<service>',
|
||||
help='Nova service')
|
||||
def list(self, host=None, service=None):
|
||||
"""Show a list of all running services. Filter by host & service name.
|
||||
args: [host] [service]"""
|
||||
"""
|
||||
Show a list of all running services. Filter by host & service name.
|
||||
"""
|
||||
ctxt = context.get_admin_context()
|
||||
now = utils.utcnow()
|
||||
services = db.service_get_all(ctxt)
|
||||
@@ -763,9 +843,11 @@ class ServiceCommands(object):
|
||||
active, art,
|
||||
svc['updated_at'])
|
||||
|
||||
@args('--host', dest='host', metavar='<host>', help='Host')
|
||||
@args('--service', dest='service', metavar='<service>',
|
||||
help='Nova service')
|
||||
def enable(self, host, service):
|
||||
"""Enable scheduling for a service
|
||||
args: host service"""
|
||||
"""Enable scheduling for a service"""
|
||||
ctxt = context.get_admin_context()
|
||||
svc = db.service_get_by_args(ctxt, host, service)
|
||||
if not svc:
|
||||
@@ -773,9 +855,11 @@ class ServiceCommands(object):
|
||||
return
|
||||
db.service_update(ctxt, svc['id'], {'disabled': False})
|
||||
|
||||
@args('--host', dest='host', metavar='<host>', help='Host')
|
||||
@args('--service', dest='service', metavar='<service>',
|
||||
help='Nova service')
|
||||
def disable(self, host, service):
|
||||
"""Disable scheduling for a service
|
||||
args: host service"""
|
||||
"""Disable scheduling for a service"""
|
||||
ctxt = context.get_admin_context()
|
||||
svc = db.service_get_by_args(ctxt, host, service)
|
||||
if not svc:
|
||||
@@ -783,12 +867,9 @@ class ServiceCommands(object):
|
||||
return
|
||||
db.service_update(ctxt, svc['id'], {'disabled': True})
|
||||
|
||||
@args('--host', dest='host', metavar='<host>', help='Host')
|
||||
def describe_resource(self, host):
|
||||
"""Describes cpu/memory/hdd info for host.
|
||||
|
||||
:param host: hostname.
|
||||
|
||||
"""
|
||||
"""Describes cpu/memory/hdd info for host."""
|
||||
|
||||
result = rpc.call(context.get_admin_context(),
|
||||
FLAGS.scheduler_topic,
|
||||
@@ -816,12 +897,9 @@ class ServiceCommands(object):
|
||||
val['memory_mb'],
|
||||
val['local_gb'])
|
||||
|
||||
@args('--host', dest='host', metavar='<host>', help='Host')
|
||||
def update_resource(self, host):
|
||||
"""Updates available vcpu/memory/disk info for host.
|
||||
|
||||
:param host: hostname.
|
||||
|
||||
"""
|
||||
"""Updates available vcpu/memory/disk info for host."""
|
||||
|
||||
ctxt = context.get_admin_context()
|
||||
service_refs = db.service_get_all_by_host(ctxt, host)
|
||||
@@ -865,6 +943,8 @@ class DbCommands(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@args('--version', dest='version', metavar='<version>',
|
||||
help='Database version')
|
||||
def sync(self, version=None):
|
||||
"""Sync the database up to the most recent version."""
|
||||
return migration.db_sync(version)
|
||||
@@ -884,14 +964,18 @@ class VersionCommands(object):
|
||||
print _("%s (%s)") %\
|
||||
(version.version_string(), version.version_string_with_vcs())
|
||||
|
||||
def __call__(self):
|
||||
self.list()
|
||||
|
||||
|
||||
class VolumeCommands(object):
|
||||
"""Methods for dealing with a cloud in an odd state"""
|
||||
|
||||
@args('--volume', dest='volume_id', metavar='<volume id>',
|
||||
help='Volume ID')
|
||||
def delete(self, volume_id):
|
||||
"""Delete a volume, bypassing the check that it
|
||||
must be available.
|
||||
args: volume_id_id"""
|
||||
must be available."""
|
||||
ctxt = context.get_admin_context()
|
||||
volume = db.volume_get(ctxt, param2id(volume_id))
|
||||
host = volume['host']
|
||||
@@ -912,11 +996,12 @@ class VolumeCommands(object):
|
||||
{"method": "delete_volume",
|
||||
"args": {"volume_id": volume['id']}})
|
||||
|
||||
@args('--volume', dest='volume_id', metavar='<volume id>',
|
||||
help='Volume ID')
|
||||
def reattach(self, volume_id):
|
||||
"""Re-attach a volume that has previously been attached
|
||||
to an instance. Typically called after a compute host
|
||||
has been rebooted.
|
||||
args: volume_id_id"""
|
||||
has been rebooted."""
|
||||
ctxt = context.get_admin_context()
|
||||
volume = db.volume_get(ctxt, param2id(volume_id))
|
||||
if not volume['instance_id']:
|
||||
@@ -943,12 +1028,23 @@ class InstanceTypeCommands(object):
|
||||
val["flavorid"], val["swap"], val["rxtx_quota"],
|
||||
val["rxtx_cap"], deleted)
|
||||
|
||||
@args('--name', dest='name', metavar='<name>',
|
||||
help='Name of instance type/flavor')
|
||||
@args('--memory', dest='memory', metavar='<memory size>',
|
||||
help='Memory size')
|
||||
@args('--cpu', dest='vcpus', metavar='<num cores>', help='Number cpus')
|
||||
@args('--local_gb', dest='local_gb', metavar='<local_gb>',
|
||||
help='local_gb')
|
||||
@args('--flavor', dest='flavorid', metavar='<flavor id>',
|
||||
help='Flavor ID')
|
||||
@args('--swap', dest='swap', metavar='<swap>', help='Swap')
|
||||
@args('--rxtx_quota', dest='rxtx_quota', metavar='<rxtx_quota>',
|
||||
help='rxtx_quota')
|
||||
@args('--rxtx_cap', dest='rxtx_cap', metavar='<rxtx_cap>',
|
||||
help='rxtx_cap')
|
||||
def create(self, name, memory, vcpus, local_gb, flavorid,
|
||||
swap=0, rxtx_quota=0, rxtx_cap=0):
|
||||
"""Creates instance types / flavors
|
||||
arguments: name memory vcpus local_gb flavorid [swap] [rxtx_quota]
|
||||
[rxtx_cap]
|
||||
"""
|
||||
"""Creates instance types / flavors"""
|
||||
try:
|
||||
instance_types.create(name, memory, vcpus, local_gb,
|
||||
flavorid, swap, rxtx_quota, rxtx_cap)
|
||||
@@ -971,9 +1067,10 @@ class InstanceTypeCommands(object):
|
||||
else:
|
||||
print "%s created" % name
|
||||
|
||||
@args('--name', dest='name', metavar='<name>',
|
||||
help='Name of instance type/flavor')
|
||||
def delete(self, name, purge=None):
|
||||
"""Marks instance types / flavors as deleted
|
||||
arguments: name"""
|
||||
"""Marks instance types / flavors as deleted"""
|
||||
try:
|
||||
if purge == "--purge":
|
||||
instance_types.purge(name)
|
||||
@@ -992,9 +1089,10 @@ class InstanceTypeCommands(object):
|
||||
else:
|
||||
print "%s %s" % (name, verb)
|
||||
|
||||
@args('--name', dest='name', metavar='<name>',
|
||||
help='Name of instance type/flavor')
|
||||
def list(self, name=None):
|
||||
"""Lists all active or specific instance types / flavors
|
||||
arguments: [name]"""
|
||||
"""Lists all active or specific instance types / flavors"""
|
||||
try:
|
||||
if name is None:
|
||||
inst_types = instance_types.get_all_types()
|
||||
@@ -1042,11 +1140,18 @@ class ImageCommands(object):
|
||||
except Exception as exc:
|
||||
print _("Failed to register %(path)s: %(exc)s") % locals()
|
||||
|
||||
@args('--image', dest='image', metavar='<image>', help='Image')
|
||||
@args('--kernel', dest='kernel', metavar='<kernel>', help='Kernel')
|
||||
@args('--ram', dest='ramdisk', metavar='<ramdisk>', help='RAM disk')
|
||||
@args('--owner', dest='owner', metavar='<owner>', help='Image owner')
|
||||
@args('--name', dest='name', metavar='<name>', help='Image name')
|
||||
@args('--public', dest='is_public', metavar="<'T'|'F'>",
|
||||
help='Image public or not')
|
||||
@args('--arch', dest='architecture', metavar='<arch>',
|
||||
help='Architecture')
|
||||
def all_register(self, image, kernel, ramdisk, owner, name=None,
|
||||
is_public='T', architecture='x86_64'):
|
||||
"""Uploads an image, kernel, and ramdisk into the image_service
|
||||
arguments: image kernel ramdisk owner [name] [is_public='T']
|
||||
[architecture='x86_64']"""
|
||||
"""Uploads an image, kernel, and ramdisk into the image_service"""
|
||||
kernel_id = self.kernel_register(kernel, owner, None,
|
||||
is_public, architecture)
|
||||
ramdisk_id = self.ramdisk_register(ramdisk, owner, None,
|
||||
@@ -1055,31 +1160,51 @@ class ImageCommands(object):
|
||||
architecture, 'ami', 'ami',
|
||||
kernel_id, ramdisk_id)
|
||||
|
||||
@args('--path', dest='path', metavar='<path>', help='Image path')
|
||||
@args('--owner', dest='owner', metavar='<owner>', help='Image owner')
|
||||
@args('--name', dest='name', metavar='<name>', help='Image name')
|
||||
@args('--public', dest='is_public', metavar="<'T'|'F'>",
|
||||
help='Image public or not')
|
||||
@args('--arch', dest='architecture', metavar='<arch>',
|
||||
help='Architecture')
|
||||
@args('--cont_format', dest='container_format',
|
||||
metavar='<container format>',
|
||||
help='Container format(default bare)')
|
||||
@args('--disk_format', dest='disk_format', metavar='<disk format>',
|
||||
help='Disk format(default: raw)')
|
||||
@args('--kernel', dest='kernel_id', metavar='<kernel>', help='Kernel')
|
||||
@args('--ram', dest='ramdisk_id', metavar='<ramdisk>', help='RAM disk')
|
||||
def image_register(self, path, owner, name=None, is_public='T',
|
||||
architecture='x86_64', container_format='bare',
|
||||
disk_format='raw', kernel_id=None, ramdisk_id=None):
|
||||
"""Uploads an image into the image_service
|
||||
arguments: path owner [name] [is_public='T'] [architecture='x86_64']
|
||||
[container_format='bare'] [disk_format='raw']
|
||||
[kernel_id=None] [ramdisk_id=None]
|
||||
"""
|
||||
"""Uploads an image into the image_service"""
|
||||
return self._register(container_format, disk_format, path,
|
||||
owner, name, is_public, architecture,
|
||||
kernel_id, ramdisk_id)
|
||||
|
||||
@args('--path', dest='path', metavar='<path>', help='Image path')
|
||||
@args('--owner', dest='owner', metavar='<owner>', help='Image owner')
|
||||
@args('--name', dest='name', metavar='<name>', help='Image name')
|
||||
@args('--public', dest='is_public', metavar="<'T'|'F'>",
|
||||
help='Image public or not')
|
||||
@args('--arch', dest='architecture', metavar='<arch>',
|
||||
help='Architecture')
|
||||
def kernel_register(self, path, owner, name=None, is_public='T',
|
||||
architecture='x86_64'):
|
||||
"""Uploads a kernel into the image_service
|
||||
arguments: path owner [name] [is_public='T'] [architecture='x86_64']
|
||||
"""
|
||||
"""Uploads a kernel into the image_service"""
|
||||
return self._register('aki', 'aki', path, owner, name,
|
||||
is_public, architecture)
|
||||
|
||||
@args('--path', dest='path', metavar='<path>', help='Image path')
|
||||
@args('--owner', dest='owner', metavar='<owner>', help='Image owner')
|
||||
@args('--name', dest='name', metavar='<name>', help='Image name')
|
||||
@args('--public', dest='is_public', metavar="<'T'|'F'>",
|
||||
help='Image public or not')
|
||||
@args('--arch', dest='architecture', metavar='<arch>',
|
||||
help='Architecture')
|
||||
def ramdisk_register(self, path, owner, name=None, is_public='T',
|
||||
architecture='x86_64'):
|
||||
"""Uploads a ramdisk into the image_service
|
||||
arguments: path owner [name] [is_public='T'] [architecture='x86_64']
|
||||
"""
|
||||
"""Uploads a ramdisk into the image_service"""
|
||||
return self._register('ari', 'ari', path, owner, name,
|
||||
is_public, architecture)
|
||||
|
||||
@@ -1128,9 +1253,10 @@ class ImageCommands(object):
|
||||
except Exception as exc:
|
||||
print _("Failed to convert %(old)s: %(exc)s") % locals()
|
||||
|
||||
@args('--dir', dest='directory', metavar='<path>',
|
||||
help='Images directory')
|
||||
def convert(self, directory):
|
||||
"""Uploads old objectstore images in directory to new service
|
||||
arguments: directory"""
|
||||
"""Uploads old objectstore images in directory to new service"""
|
||||
machine_images = {}
|
||||
other_images = {}
|
||||
directory = os.path.abspath(directory)
|
||||
@@ -1155,8 +1281,7 @@ class AgentBuildCommands(object):
|
||||
|
||||
def create(self, os, architecture, version, url, md5hash,
|
||||
hypervisor='xen'):
|
||||
"""Creates a new agent build.
|
||||
arguments: os architecture version url md5hash [hypervisor='xen']"""
|
||||
"""Creates a new agent build."""
|
||||
ctxt = context.get_admin_context()
|
||||
agent_build = db.agent_build_create(ctxt,
|
||||
{'hypervisor': hypervisor,
|
||||
@@ -1167,8 +1292,7 @@ class AgentBuildCommands(object):
|
||||
'md5hash': md5hash})
|
||||
|
||||
def delete(self, os, architecture, hypervisor='xen'):
|
||||
"""Deletes an existing agent build.
|
||||
arguments: os architecture [hypervisor='xen']"""
|
||||
"""Deletes an existing agent build."""
|
||||
ctxt = context.get_admin_context()
|
||||
agent_build_ref = db.agent_build_get_by_triple(ctxt,
|
||||
hypervisor, os, architecture)
|
||||
@@ -1202,9 +1326,7 @@ class AgentBuildCommands(object):
|
||||
|
||||
def modify(self, os, architecture, version, url, md5hash,
|
||||
hypervisor='xen'):
|
||||
"""Update an existing agent build.
|
||||
arguments: os architecture version url md5hash [hypervisor='xen']
|
||||
"""
|
||||
"""Update an existing agent build."""
|
||||
ctxt = context.get_admin_context()
|
||||
agent_build_ref = db.agent_build_get_by_triple(ctxt,
|
||||
hypervisor, os, architecture)
|
||||
@@ -1300,21 +1422,42 @@ def main():
|
||||
command_object = fn()
|
||||
actions = methods_of(command_object)
|
||||
if len(argv) < 1:
|
||||
print script_name + " category action [<args>]"
|
||||
print _("Available actions for %s category:") % category
|
||||
for k, _v in actions:
|
||||
print "\t%s" % k
|
||||
sys.exit(2)
|
||||
action = argv.pop(0)
|
||||
matches = lazy_match(action, actions)
|
||||
action, fn = matches[0]
|
||||
if hasattr(command_object, '__call__'):
|
||||
action = ''
|
||||
fn = command_object.__call__
|
||||
else:
|
||||
print script_name + " category action [<args>]"
|
||||
print _("Available actions for %s category:") % category
|
||||
for k, _v in actions:
|
||||
print "\t%s" % k
|
||||
sys.exit(2)
|
||||
else:
|
||||
action = argv.pop(0)
|
||||
matches = lazy_match(action, actions)
|
||||
action, fn = matches[0]
|
||||
|
||||
# For not decorated methods
|
||||
options = getattr(fn, 'options', [])
|
||||
|
||||
usage = "%%prog %s %s <args> [options]" % (category, action)
|
||||
parser = OptionParser(usage=usage)
|
||||
for ar, kw in options:
|
||||
parser.add_option(*ar, **kw)
|
||||
(opts, fn_args) = parser.parse_args(argv)
|
||||
fn_kwargs = vars(opts)
|
||||
|
||||
for k, v in fn_kwargs.items():
|
||||
if v is None:
|
||||
del fn_kwargs[k]
|
||||
|
||||
# call the action with the remaining arguments
|
||||
try:
|
||||
fn(*argv)
|
||||
fn(*fn_args, **fn_kwargs)
|
||||
sys.exit(0)
|
||||
except TypeError:
|
||||
print _("Possible wrong number of arguments supplied")
|
||||
print "%s %s: %s" % (category, action, fn.__doc__)
|
||||
print fn.__doc__
|
||||
parser.print_help()
|
||||
raise
|
||||
except Exception:
|
||||
print _("Command failed, please check log for more info")
|
||||
|
||||
@@ -269,25 +269,64 @@ class CloudTestCase(test.TestCase):
|
||||
delete = self.cloud.delete_security_group
|
||||
self.assertRaises(exception.ApiError, delete, self.context)
|
||||
|
||||
def test_authorize_revoke_security_group_ingress(self):
|
||||
def test_authorize_security_group_ingress(self):
|
||||
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
|
||||
sec = db.security_group_create(self.context, kwargs)
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
|
||||
authz(self.context, group_name=sec['name'], **kwargs)
|
||||
self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs))
|
||||
|
||||
def test_authorize_security_group_ingress_ip_permissions_ip_ranges(self):
|
||||
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
|
||||
sec = db.security_group_create(self.context, kwargs)
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81,
|
||||
'ip_ranges':
|
||||
{'1': {'cidr_ip': u'0.0.0.0/0'},
|
||||
'2': {'cidr_ip': u'10.10.10.10/32'}},
|
||||
'ip_protocol': u'tcp'}]}
|
||||
self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs))
|
||||
|
||||
def test_authorize_security_group_ingress_ip_permissions_groups(self):
|
||||
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
|
||||
sec = db.security_group_create(self.context, kwargs)
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'ip_permissions': [{'to_port': 81, 'from_port': 81,
|
||||
'ip_ranges':{'1': {'cidr_ip': u'0.0.0.0/0'},
|
||||
'2': {'cidr_ip': u'10.10.10.10/32'}},
|
||||
'groups': {'1': {'user_id': u'someuser',
|
||||
'group_name': u'somegroup1'},
|
||||
'2': {'user_id': u'someuser',
|
||||
'group_name': u'othergroup2'}},
|
||||
'ip_protocol': u'tcp'}]}
|
||||
self.assertTrue(authz(self.context, group_name=sec['name'], **kwargs))
|
||||
|
||||
def test_revoke_security_group_ingress(self):
|
||||
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
|
||||
sec = db.security_group_create(self.context, kwargs)
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
|
||||
authz(self.context, group_id=sec['id'], **kwargs)
|
||||
revoke = self.cloud.revoke_security_group_ingress
|
||||
self.assertTrue(revoke(self.context, group_name=sec['name'], **kwargs))
|
||||
|
||||
def test_authorize_revoke_security_group_ingress_by_id(self):
|
||||
sec = db.security_group_create(self.context,
|
||||
{'project_id': self.context.project_id,
|
||||
'name': 'test'})
|
||||
def test_revoke_security_group_ingress_by_id(self):
|
||||
kwargs = {'project_id': self.context.project_id, 'name': 'test'}
|
||||
sec = db.security_group_create(self.context, kwargs)
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
|
||||
authz(self.context, group_id=sec['id'], **kwargs)
|
||||
revoke = self.cloud.revoke_security_group_ingress
|
||||
self.assertTrue(revoke(self.context, group_id=sec['id'], **kwargs))
|
||||
|
||||
def test_authorize_security_group_ingress_by_id(self):
|
||||
sec = db.security_group_create(self.context,
|
||||
{'project_id': self.context.project_id,
|
||||
'name': 'test'})
|
||||
authz = self.cloud.authorize_security_group_ingress
|
||||
kwargs = {'to_port': '999', 'from_port': '999', 'ip_protocol': 'tcp'}
|
||||
self.assertTrue(authz(self.context, group_id=sec['id'], **kwargs))
|
||||
|
||||
def test_authorize_security_group_ingress_missing_protocol_params(self):
|
||||
sec = db.security_group_create(self.context,
|
||||
{'project_id': self.context.project_id,
|
||||
@@ -908,6 +947,21 @@ class CloudTestCase(test.TestCase):
|
||||
self._wait_for_running(ec2_instance_id)
|
||||
return ec2_instance_id
|
||||
|
||||
def test_rescue_unrescue_instance(self):
|
||||
instance_id = self._run_instance(
|
||||
image_id='ami-1',
|
||||
instance_type=FLAGS.default_instance_type,
|
||||
max_count=1)
|
||||
self.cloud.rescue_instance(context=self.context,
|
||||
instance_id=instance_id)
|
||||
# NOTE(vish): This currently does no validation, it simply makes sure
|
||||
# that the code path doesn't throw an exception.
|
||||
self.cloud.unrescue_instance(context=self.context,
|
||||
instance_id=instance_id)
|
||||
# TODO(soren): We need this until we can stop polling in the rpc code
|
||||
# for unit tests.
|
||||
self.cloud.terminate_instances(self.context, [instance_id])
|
||||
|
||||
def test_console_output(self):
|
||||
instance_id = self._run_instance(
|
||||
image_id='ami-1',
|
||||
|
||||
@@ -624,7 +624,6 @@ class ComputeTestCase(test.TestCase):
|
||||
self._setup_other_managers()
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
volmock = self.mox.CreateMock(self.volume_manager)
|
||||
netmock = self.mox.CreateMock(self.network_manager)
|
||||
drivermock = self.mox.CreateMock(self.compute_driver)
|
||||
|
||||
dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
|
||||
@@ -632,12 +631,11 @@ class ComputeTestCase(test.TestCase):
|
||||
for i in range(len(i_ref['volumes'])):
|
||||
vid = i_ref['volumes'][i]['id']
|
||||
volmock.setup_compute_volume(c, vid).InAnyOrder('g1')
|
||||
netmock.setup_compute_network(c, i_ref['id'])
|
||||
drivermock.plug_vifs(i_ref, [])
|
||||
drivermock.ensure_filtering_rules_for_instance(i_ref)
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.compute.volume_manager = volmock
|
||||
self.compute.network_manager = netmock
|
||||
self.compute.driver = drivermock
|
||||
|
||||
self.mox.ReplayAll()
|
||||
@@ -652,18 +650,16 @@ class ComputeTestCase(test.TestCase):
|
||||
|
||||
self._setup_other_managers()
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
netmock = self.mox.CreateMock(self.network_manager)
|
||||
drivermock = self.mox.CreateMock(self.compute_driver)
|
||||
|
||||
dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
|
||||
dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy')
|
||||
self.mox.StubOutWithMock(compute_manager.LOG, 'info')
|
||||
compute_manager.LOG.info(_("%s has no volume."), i_ref['hostname'])
|
||||
netmock.setup_compute_network(c, i_ref['id'])
|
||||
drivermock.plug_vifs(i_ref, [])
|
||||
drivermock.ensure_filtering_rules_for_instance(i_ref)
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.compute.network_manager = netmock
|
||||
self.compute.driver = drivermock
|
||||
|
||||
self.mox.ReplayAll()
|
||||
@@ -684,18 +680,20 @@ class ComputeTestCase(test.TestCase):
|
||||
dbmock = self.mox.CreateMock(db)
|
||||
netmock = self.mox.CreateMock(self.network_manager)
|
||||
volmock = self.mox.CreateMock(self.volume_manager)
|
||||
drivermock = self.mox.CreateMock(self.compute_driver)
|
||||
|
||||
dbmock.instance_get(c, i_ref['id']).AndReturn(i_ref)
|
||||
dbmock.instance_get_fixed_addresses(c, i_ref['id']).AndReturn('dummy')
|
||||
for i in range(len(i_ref['volumes'])):
|
||||
volmock.setup_compute_volume(c, i_ref['volumes'][i]['id'])
|
||||
for i in range(FLAGS.live_migration_retry_count):
|
||||
netmock.setup_compute_network(c, i_ref['id']).\
|
||||
drivermock.plug_vifs(i_ref, []).\
|
||||
AndRaise(exception.ProcessExecutionError())
|
||||
|
||||
self.compute.db = dbmock
|
||||
self.compute.network_manager = netmock
|
||||
self.compute.volume_manager = volmock
|
||||
self.compute.driver = drivermock
|
||||
|
||||
self.mox.ReplayAll()
|
||||
self.assertRaises(exception.ProcessExecutionError,
|
||||
@@ -830,7 +828,7 @@ class ComputeTestCase(test.TestCase):
|
||||
for v in i_ref['volumes']:
|
||||
self.compute.volume_manager.remove_compute_volume(c, v['id'])
|
||||
self.mox.StubOutWithMock(self.compute.driver, 'unfilter_instance')
|
||||
self.compute.driver.unfilter_instance(i_ref)
|
||||
self.compute.driver.unfilter_instance(i_ref, [])
|
||||
|
||||
# executing
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@@ -54,9 +54,13 @@ def _create_network_info(count=1, ipv6=None):
|
||||
fake_ip = '0.0.0.0/0'
|
||||
fake_ip_2 = '0.0.0.1/0'
|
||||
fake_ip_3 = '0.0.0.1/0'
|
||||
fake_vlan = 100
|
||||
fake_bridge_interface = 'eth0'
|
||||
network = {'bridge': fake,
|
||||
'cidr': fake_ip,
|
||||
'cidr_v6': fake_ip}
|
||||
'cidr_v6': fake_ip,
|
||||
'vlan': fake_vlan,
|
||||
'bridge_interface': fake_bridge_interface}
|
||||
mapping = {'mac': fake,
|
||||
'dhcp_server': fake,
|
||||
'gateway': fake,
|
||||
@@ -219,9 +223,19 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
def setattr(self, key, val):
|
||||
self.__setattr__(key, val)
|
||||
|
||||
# A fake VIF driver
|
||||
class FakeVIFDriver(object):
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
pass
|
||||
|
||||
def setattr(self, key, val):
|
||||
self.__setattr__(key, val)
|
||||
|
||||
# Creating mocks
|
||||
fake = FakeLibvirtConnection()
|
||||
fakeip = FakeIptablesFirewallDriver
|
||||
fakevif = FakeVIFDriver()
|
||||
# Customizing above fake if necessary
|
||||
for key, val in kwargs.items():
|
||||
fake.__setattr__(key, val)
|
||||
@@ -229,6 +243,8 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
# Inevitable mocks for connection.LibvirtConnection
|
||||
self.mox.StubOutWithMock(connection.utils, 'import_class')
|
||||
connection.utils.import_class(mox.IgnoreArg()).AndReturn(fakeip)
|
||||
self.mox.StubOutWithMock(connection.utils, 'import_object')
|
||||
connection.utils.import_object(mox.IgnoreArg()).AndReturn(fakevif)
|
||||
self.mox.StubOutWithMock(connection.LibvirtConnection, '_conn')
|
||||
connection.LibvirtConnection._conn = fake
|
||||
|
||||
@@ -280,22 +296,6 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
_create_network_info(2))
|
||||
self.assertTrue(len(result['nics']) == 2)
|
||||
|
||||
def test_get_nic_for_xml_v4(self):
|
||||
conn = connection.LibvirtConnection(True)
|
||||
network, mapping = _create_network_info()[0]
|
||||
self.flags(use_ipv6=False)
|
||||
params = conn._get_nic_for_xml(network, mapping)['extra_params']
|
||||
self.assertTrue(params.find('PROJNETV6') == -1)
|
||||
self.assertTrue(params.find('PROJMASKV6') == -1)
|
||||
|
||||
def test_get_nic_for_xml_v6(self):
|
||||
conn = connection.LibvirtConnection(True)
|
||||
network, mapping = _create_network_info()[0]
|
||||
self.flags(use_ipv6=True)
|
||||
params = conn._get_nic_for_xml(network, mapping)['extra_params']
|
||||
self.assertTrue(params.find('PROJNETV6') > -1)
|
||||
self.assertTrue(params.find('PROJMASKV6') > -1)
|
||||
|
||||
@test.skip_test("skipping libvirt tests depends on get_network_info shim")
|
||||
def test_xml_and_uri_no_ramdisk_no_kernel(self):
|
||||
instance_data = dict(self.test_instance)
|
||||
@@ -722,6 +722,9 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
return vdmock
|
||||
|
||||
self.create_fake_libvirt_mock(lookupByName=fake_lookup)
|
||||
self.mox.StubOutWithMock(self.compute, "recover_live_migration")
|
||||
self.compute.recover_live_migration(self.context, instance_ref,
|
||||
dest='dest')
|
||||
|
||||
# Start test
|
||||
self.mox.ReplayAll()
|
||||
|
||||
@@ -149,7 +149,10 @@ class FlatNetworkTestCase(test.TestCase):
|
||||
'cidr': '192.168.%s.0/24' % i,
|
||||
'cidr_v6': '2001:db%s::/64' % i8,
|
||||
'id': i,
|
||||
'injected': 'DONTCARE'}
|
||||
'multi_host': False,
|
||||
'injected': 'DONTCARE',
|
||||
'bridge_interface': 'fake_fa%s' % i,
|
||||
'vlan': None}
|
||||
|
||||
self.assertDictMatch(nw[0], check)
|
||||
|
||||
@@ -162,7 +165,9 @@ class FlatNetworkTestCase(test.TestCase):
|
||||
'ips': 'DONTCARE',
|
||||
'label': 'test%s' % i,
|
||||
'mac': 'DE:AD:BE:EF:00:0%s' % i,
|
||||
'rxtx_cap': 'DONTCARE'}
|
||||
'rxtx_cap': 'DONTCARE',
|
||||
'should_create_vlan': False,
|
||||
'should_create_bridge': False}
|
||||
self.assertDictMatch(nw[1], check)
|
||||
|
||||
check = [{'enabled': 'DONTCARE',
|
||||
|
||||
@@ -647,7 +647,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
self.flags(xenapi_inject_image=False)
|
||||
instance = self._create_instance()
|
||||
conn = xenapi_conn.get_connection(False)
|
||||
conn.rescue(instance, None)
|
||||
conn.rescue(instance, None, [])
|
||||
|
||||
def test_unrescue(self):
|
||||
instance = self._create_instance()
|
||||
|
||||
Reference in New Issue
Block a user