diff --git a/bin/nova-manage b/bin/nova-manage index 31b8669c54db..e3fd5e11a4e9 100755 --- a/bin/nova-manage +++ b/bin/nova-manage @@ -61,7 +61,6 @@ import math import netaddr import optparse import os -import StringIO import sys @@ -81,14 +80,12 @@ from nova.compat import flagfile from nova.compute import instance_types from nova.compute import rpcapi as compute_rpcapi from nova import context -from nova import crypto from nova import db from nova.db import migration from nova import exception from nova import flags from nova.openstack.common import cfg from nova.openstack.common import importutils -from nova.openstack.common import jsonutils from nova.openstack.common import log as logging from nova.openstack.common import rpc from nova.openstack.common import timeutils @@ -219,98 +216,6 @@ class ShellCommands(object): arguments: path""" exec(compile(open(path).read(), path, 'exec'), locals(), globals()) - @args('--filename', dest='filename', metavar='', default=False, - help='Export file path') - def export(self, filename): - """Export Nova users into a file that can be consumed by Keystone""" - - def create_file(filename): - data = generate_data() - with open(filename, 'w') as f: - f.write(data.getvalue()) - - def tenants(data, am): - for project in am.get_projects(): - print >> data, ("tenant add '%s'" % - (project.name)) - for u in project.member_ids: - user = am.get_user(u) - print >> data, ("user add '%s' '%s' '%s'" % - (user.name, user.access, project.name)) - print >> data, ("credentials add 'EC2' '%s:%s' '%s' '%s'" % - (user.access, project.id, user.secret, project.id)) - - def roles(data, am): - for role in am.get_roles(): - print >> data, ("role add '%s'" % (role)) - - def grant_roles(data, am): - roles = am.get_roles() - for project in am.get_projects(): - for u in project.member_ids: - user = am.get_user(u) - for role in db.user_get_roles_for_project(ctxt, u, - project.id): - print >> data, ("role grant '%s', '%s', '%s')," % - (user.name, role, project.name)) - print >> data - - def generate_data(): - data = StringIO.StringIO() - am = manager.AuthManager() - tenants(data, am) - roles(data, am) - grant_roles(data, am) - data.seek(0) - return data - - ctxt = context.get_admin_context() - if filename: - create_file(filename) - else: - data = generate_data() - print data.getvalue() - - -class RoleCommands(object): - """Class for managing roles.""" - - def __init__(self): - self.manager = manager.AuthManager() - - @args('--user', dest="user", metavar='', help='User name') - @args('--role', dest="role", metavar='', help='User role') - @args('--project', dest="project", metavar='', - help='Project name') - def add(self, user, role, project=None): - """adds role to user - if project is specified, adds project specific role""" - if project: - projobj = self.manager.get_project(project) - if not projobj.has_member(user): - print "%s not a member of %s" % (user, project) - return - self.manager.add_role(user, role, project) - - @args('--user', dest="user", metavar='', help='User name') - @args('--role', dest="role", metavar='', help='User role') - @args('--project', dest="project", metavar='', - 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""" - print self.manager.has_role(user, role, project) - - @args('--user', dest="user", metavar='', help='User name') - @args('--role', dest="role", metavar='', help='User role') - @args('--project', dest="project", metavar='', - help='Project name') - def remove(self, user, role, project=None): - """removes role from user - if project is specified, removes project specific role""" - self.manager.remove_role(user, role, project) - def _db_error(caught_exception): print caught_exception @@ -320,174 +225,12 @@ def _db_error(caught_exception): exit(1) -class UserCommands(object): - """Class for managing users.""" - - @staticmethod - def _print_export(user): - """Print export variables to use with API.""" - print 'export EC2_ACCESS_KEY=%s' % user.access - print 'export EC2_SECRET_KEY=%s' % user.secret - - def __init__(self): - self.manager = manager.AuthManager() - - @args('--name', dest="name", metavar='', help='Admin name') - @args('--access', dest="access", metavar='', help='Access') - @args('--secret', dest="secret", metavar='', help='Secret') - def admin(self, name, access=None, secret=None): - """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='', help='User name') - @args('--access', dest="access", metavar='', help='Access') - @args('--secret', dest="secret", metavar='', help='Secret') - def create(self, name, access=None, secret=None): - """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='', help='User name') - def delete(self, name): - """deletes an existing user - arguments: name""" - self.manager.delete_user(name) - - @args('--name', dest="name", metavar='', help='User name') - def exports(self, name): - """prints access and secrets for user in export format""" - user = self.manager.get_user(name) - if user: - self._print_export(user) - else: - print "User %s doesn't exist" % name - - def list(self): - """lists all users""" - for user in self.manager.get_users(): - print user.name - - @args('--name', dest="name", metavar='', help='User name') - @args('--access', dest="access_key", metavar='', - help='Access key') - @args('--secret', dest="secret_key", metavar='', - 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 - leave any field blank to ignore it, admin should be 'T', 'F', or blank - """ - if not is_admin: - is_admin = None - elif is_admin.upper()[0] == 'T': - is_admin = True - else: - is_admin = False - self.manager.modify_user(name, access_key, secret_key, is_admin) - - @args('--name', dest="user_id", metavar='', help='User name') - @args('--project', dest="project_id", metavar='', - help='Project name') - def revoke(self, user_id, project_id=None): - """revoke certs for a user""" - if project_id: - crypto.revoke_certs_by_user_and_project(user_id, project_id) - else: - crypto.revoke_certs_by_user(user_id) - - class ProjectCommands(object): """Class for managing projects.""" def __init__(self): self.manager = manager.AuthManager() - @args('--project', dest="project_id", metavar='', - help='Project name') - @args('--user', dest="user_id", metavar='', help='User name') - def add(self, 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='', - help='Project name') - @args('--user', dest="project_manager", metavar='', - help='Project manager') - @args('--desc', dest="description", metavar='', - help='Description') - def create(self, name, project_manager, description=None): - """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='', - help='Project name') - @args('--user', dest="project_manager", metavar='', - help='Project manager') - @args('--desc', dest="description", metavar='', - help='Description') - def modify(self, name, project_manager, description=None): - """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='', - help='Project name') - def delete(self, 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='', - help='Project name') - @args('--user', dest="user_id", metavar='', help='User name') - @args('--file', dest="filename", metavar='', - help='File name(Default: novarc)') - def environment(self, project_id, user_id, filename='novarc'): - """Exports environment variables to a sourceable file""" - try: - rc = self.manager.get_environment_rc(user_id, project_id) - except (exception.UserNotFound, exception.ProjectNotFound) as ex: - print ex - raise - if filename == "-": - sys.stdout.write(rc) - else: - with open(filename, 'w') as f: - f.write(rc) - - @args('--user', dest="username", metavar='', help='User name') - def list(self, username=None): - """Lists all projects""" - for project in self.manager.get_projects(username): - print project.name - - @args('--project', dest="project_id", metavar='', - help='Project name') - @args('--key', dest="key", metavar='', help='Key') - @args('--value', dest="value", metavar='', help='Value') def quota(self, project_id, key=None, value=None): """Set or display quotas for project""" ctxt = context.get_admin_context() @@ -504,17 +247,6 @@ class ProjectCommands(object): value['limit'] = 'unlimited' print '%s: %s' % (key, value['limit']) - @args('--project', dest="project_id", metavar='', - help='Project name') - @args('--user', dest="user_id", metavar='', help='User name') - def remove(self, 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='', help='Project name') def scrub(self, project_id): @@ -527,32 +259,6 @@ class ProjectCommands(object): for group in groups: db.security_group_destroy(admin_context, group['id']) - @args('--project', dest="project_id", metavar='', - help='Project name') - @args('--user', dest="user_id", metavar='', help='User name') - @args('--file', dest="filename", metavar='', - help='File name(Default: nova.zip)') - def zipfile(self, 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 == "-": - sys.stdout.write(zip_file) - else: - with open(filename, 'w') as f: - f.write(zip_file) - except (exception.UserNotFound, exception.ProjectNotFound) as ex: - print ex - raise - except db.api.NoMoreNetworks: - print _('No more networks available. If this is a new ' - 'installation, you need\nto call something like this:\n\n' - ' 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-cert server on this host.") AccountCommands = ProjectCommands @@ -1531,86 +1237,11 @@ class GetLogCommands(object): print "No nova entries in syslog!" -class ExportCommands(object): - """Commands used to export data from Nova""" - - def auth(self): - """Export Nova auth data in format that can be consumed by Keystone""" - print jsonutils.dumps(self._get_auth_data()) - - def _get_auth_data(self): - output = { - 'users': [], - 'tenants': [], - 'user_tenant_list': [], - 'ec2_credentials': [], - 'roles': [], - 'role_user_tenant_list': [], - } - - am = manager.AuthManager() - - for user in am.get_users(): - # NOTE(vish): Deprecated auth uses an access key, no auth uses a - # the user_id in place of it. - if FLAGS.auth_strategy == 'deprecated': - access = user.access - else: - access = user.id - - user_dict = { - 'id': user.id, - 'name': user.name, - 'password': access, - } - output['users'].append(user_dict) - - ec2_cred = { - 'user_id': user.id, - 'access_key': access, - 'secret_key': user.secret, - } - output['ec2_credentials'].append(ec2_cred) - - for project in am.get_projects(): - tenant = { - 'id': project.id, - 'name': project.name, - 'description': project.description, - } - output['tenants'].append(tenant) - - for user_id in project.member_ids: - membership = { - 'tenant_id': project.id, - 'user_id': user_id, - } - output['user_tenant_list'].append(membership) - - for role in am.get_roles(): - if role not in output['roles']: - output['roles'].append(role) - - for project in am.get_projects(): - for user_id in project.member_ids: - user = am.get_user(user_id) - for role in am.get_user_roles(user_id, project.id): - role_grant = { - 'role': role, - 'user_id': user_id, - 'tenant_id': project.id, - } - output['role_user_tenant_list'].append(role_grant) - - return output - - CATEGORIES = [ ('account', AccountCommands), ('agent', AgentBuildCommands), ('config', ConfigCommands), ('db', DbCommands), - ('export', ExportCommands), ('fixed', FixedIpCommands), ('flavor', InstanceTypeCommands), ('floating', FloatingIpCommands), @@ -1619,11 +1250,9 @@ CATEGORIES = [ ('logs', GetLogCommands), ('network', NetworkCommands), ('project', ProjectCommands), - ('role', RoleCommands), ('service', ServiceCommands), ('shell', ShellCommands), ('sm', StorageManagerCommands), - ('user', UserCommands), ('version', VersionCommands), ('vm', VmCommands), ('volume', VolumeCommands), diff --git a/doc/source/man/nova-manage.rst b/doc/source/man/nova-manage.rst index 65b9c0d65f73..4a8169d65f0b 100644 --- a/doc/source/man/nova-manage.rst +++ b/doc/source/man/nova-manage.rst @@ -21,7 +21,7 @@ SYNOPSIS DESCRIPTION =========== -nova-manage controls cloud computing instances by managing nova users, nova projects, nova roles, shell selection, vpn connections, and floating IP address configuration. More information about OpenStack Nova is at http://nova.openstack.org. +nova-manage controls cloud computing instances by managing shell selection, vpn connections, and floating IP address configuration. More information about OpenStack Nova is at http://nova.openstack.org. OPTIONS ======= @@ -29,16 +29,13 @@ OPTIONS The standard pattern for executing a nova-manage command is: ``nova-manage []`` -For example, to obtain a list of all projects: -``nova-manage project list`` - Run without arguments to see a list of available command categories: ``nova-manage`` -Categories are user, project, role, shell, vpn, and floating. Detailed descriptions are below. +Categories are project, shell, vpn, and floating. Detailed descriptions are below. You can also run with a category argument such as user to see a list of all commands in that category: -``nova-manage user`` +``nova-manage floating`` These sections describe the available categories and arguments for nova-manage. @@ -53,81 +50,6 @@ Nova Db Sync the database up to the most recent version. This is the standard way to create the db as well. -Nova User -~~~~~~~~~ - -``nova-manage user admin `` - - Create an admin user with the name . - -``nova-manage user create `` - - Create a normal user with the name . - -``nova-manage user delete `` - - Delete the user with the name . - -``nova-manage user exports `` - - Outputs a list of access key and secret keys for user to the screen - -``nova-manage user list`` - - Outputs a list of all the user names to the screen. - -``nova-manage user modify `` - - Updates the indicated user keys, indicating with T or F if the user is an admin user. Leave any argument blank if you do not want to update it. - -Nova Project -~~~~~~~~~~~~ - -``nova-manage project add `` - - Add a nova project with the name to the database. - -``nova-manage project create `` - - Create a new nova project with the name (you still need to do nova-manage project add to add it to the database). - -``nova-manage project delete `` - - Delete a nova project with the name . - -``nova-manage project environment `` - - Exports environment variables for the named project to a file named novarc. - -``nova-manage project list`` - - Outputs a list of all the projects to the screen. - -``nova-manage project quota `` - - Outputs the size and specs of the project's instances including gigabytes, instances, floating IPs, volumes, and cores. - -``nova-manage project remove `` - - Deletes the project with the name . - -``nova-manage project zipfile`` - - Compresses all related files for a created project into a zip file nova.zip. - -Nova Role -~~~~~~~~~ - -``nova-manage role add <(optional) projectname>`` - - Add a user to either a global or project-based role with the indicated assigned to the named user. Role names can be one of the following five roles: cloudadmin, itsec, sysadmin, netadmin, developer. If you add the project name as the last argument then the role is assigned just for that project, otherwise the user is assigned the named role for all projects. - -``nova-manage role has `` - Checks the user or project and responds with True if the user has a global role with a particular project. - -``nova-manage role remove `` - Remove the indicated role from the user. - Nova Logs ~~~~~~~~~ diff --git a/nova/tests/test_nova_manage.py b/nova/tests/test_nova_manage.py index c9e2f1bbf5d9..e515bd51d010 100644 --- a/nova/tests/test_nova_manage.py +++ b/nova/tests/test_nova_manage.py @@ -234,62 +234,3 @@ class NetworkCommandsTestCase(test.TestCase): self._test_modify_base(update_value={'project_id': None, 'host': None}, project=None, host=None, dis_project=True, dis_host=True) - - -class ExportAuthTestCase(test.TestCase): - - def test_export_with_noauth(self): - self._do_test_export() - - def test_export_with_deprecated_auth(self): - self.flags(auth_strategy='deprecated') - self._do_test_export(noauth=False) - - def _do_test_export(self, noauth=True): - self.flags(allowed_roles=['role1', 'role2']) - am = nova.auth.manager.AuthManager(new=True) - user1 = am.create_user('user1', 'a1', 's1') - user2 = am.create_user('user2', 'a2', 's2') - user3 = am.create_user('user3', 'a3', 's3') - proj1 = am.create_project('proj1', user1, member_users=[user1, user2]) - proj2 = am.create_project('proj2', user2, member_users=[user2, user3]) - am.add_role(user1, 'role1', proj1) - am.add_role(user1, 'role1', proj2) - am.add_role(user3, 'role1', proj1) - am.add_role(user3, 'role2', proj2) - - commands = nova_manage.ExportCommands() - output = commands._get_auth_data() - - def pw(idx): - return ('user' if noauth else 'a') + str(idx) - - expected = { - "users": [ - {"id": "user1", "name": "user1", 'password': pw(1)}, - {"id": "user2", "name": "user2", 'password': pw(2)}, - {"id": "user3", "name": "user3", 'password': pw(3)}, - ], - "roles": ["role1", "role2"], - "role_user_tenant_list": [ - {"user_id": "user1", "role": "role1", "tenant_id": "proj1"}, - {"user_id": "user3", "role": "role2", "tenant_id": "proj2"}, - ], - "user_tenant_list": [ - {"tenant_id": "proj1", "user_id": "user1"}, - {"tenant_id": "proj1", "user_id": "user2"}, - {"tenant_id": "proj2", "user_id": "user2"}, - {"tenant_id": "proj2", "user_id": "user3"}, - ], - "ec2_credentials": [ - {"access_key": pw(1), "secret_key": "s1", "user_id": "user1"}, - {"access_key": pw(2), "secret_key": "s2", "user_id": "user2"}, - {"access_key": pw(3), "secret_key": "s3", "user_id": "user3"}, - ], - "tenants": [ - {"description": "proj1", "id": "proj1", "name": "proj1"}, - {"description": "proj2", "id": "proj2", "name": "proj2"}, - ], - } - - self.assertDictMatch(output, expected)