예제 #1
0
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_PASSWORD': '******',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.0',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient
예제 #2
0
파일: main.py 프로젝트: clayg/ham
def get_clients():
    """
    Get compute and volume clients from novaclient using envrionment vars.

    STEAL THIS FUNCTION
    """
    shell = OpenStackComputeShell()
    parser = shell.get_base_parser()
    options, args = parser.parse_known_args()
    kwargs = dict(vars(options))
    del kwargs["help"]
    shell.setup_debugging(kwargs.pop("debug"))
    # some options can show up under multiple names
    multi_name_keys = (
        ("os_username", "username"),
        ("os_password", "apikey"),
        ("os_tenant_name", "projectid"),
        ("os_auth_url", "url"),
        ("region_name", "os_region_name"),
    )
    for k, alias in multi_name_keys:
        val = kwargs.pop(alias, None)
        if val and not kwargs.get(k):
            kwargs[k] = val
    # required args
    required_args = ("os_compute_api_version", "os_username", "os_password", "os_tenant_name", "os_auth_url")
    args = []
    for arg in required_args:
        val = kwargs.pop(arg)
        if not val:
            raise ClientBuildError("missing required env %s" % arg.upper())
        args.append(val)

    # setup auth systems
    os_auth_system = kwargs.pop("os_auth_system", None)
    kwargs["auth_system"] = os_auth_system
    if os_auth_system and os_auth_system != "keystone":
        # Discover available auth plugins
        discover_auth_systems()
        kwargs["auth_plugin"] = load_plugin(os_auth_system)

    # invalid args
    invalid_args = ("os_cacert", "os_user_id", "os_auth_token", "os_tenant_id")
    for arg in invalid_args:
        kwargs.pop(arg, None)
    kwargs["no_cache"] = True

    kwargs["service_type"] = "compute"
    compute = Client(*args, **kwargs)
    # XXX figure out what cinder is doing these days
    volume = None
    return compute, volume
예제 #3
0
    def setUp(self):
        global _old_env
        fake_env = {
            'NOVA_USERNAME': '******',
            'NOVA_API_KEY': 'password',
            'NOVA_PROJECT_ID': 'project_id',
        }
        _old_env, os.environ = os.environ, fake_env.copy()

        # Make a fake shell object, a helping wrapper to call it, and a quick
        # way of asserting that certain API calls were made.
        global shell, _shell, assert_called, assert_called_anytime
        _shell = OpenStackComputeShell()
        shell = lambda cmd: _shell.main(cmd.split())
예제 #4
0
    def setUp(self):
        global _old_env
        fake_env = {
            'NOVA_USERNAME': '******',
            'NOVA_PASSWORD': '******',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_URL': 'http://no.where',
        }
        _old_env, os.environ = os.environ, fake_env.copy()

        # Make a fake shell object, a helping wrapper to call it, and a quick
        # way of asserting that certain API calls were made.
        global shell, _shell, assert_called, assert_called_anytime
        _shell = OpenStackComputeShell()
        shell = lambda cmd: _shell.main(cmd.split())
예제 #5
0
파일: nova.py 프로젝트: crimv42/saltstack
    def _old_init(self, username, project_id, auth_url, region_name, password,
                  os_auth_plugin, **kwargs):
        self.kwargs = kwargs.copy()
        if not self.extensions:
            if hasattr(OpenStackComputeShell, '_discover_extensions'):
                self.extensions = OpenStackComputeShell()._discover_extensions(
                    '2.0')
            else:
                self.extensions = client.discover_extensions('2.0')
            for extension in self.extensions:
                extension.run_hooks('__pre_parse_args__')
            self.kwargs['extensions'] = self.extensions

        self.kwargs['username'] = username
        self.kwargs['project_id'] = project_id
        self.kwargs['auth_url'] = auth_url
        self.kwargs['region_name'] = region_name
        self.kwargs['service_type'] = 'compute'

        # used in novaclient extensions to see if they are rackspace or not, to know if it needs to load
        # the hooks for that extension or not.  This is cleaned up by sanatize_novaclient
        self.kwargs['os_auth_url'] = auth_url

        if os_auth_plugin is not None:
            novaclient.auth_plugin.discover_auth_systems()
            auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_plugin)
            self.kwargs['auth_plugin'] = auth_plugin
            self.kwargs['auth_system'] = os_auth_plugin

        if not self.kwargs.get('api_key', None):
            self.kwargs['api_key'] = password

        # This has to be run before sanatize_novaclient before extra variables are cleaned out.
        if hasattr(self, 'extensions'):
            # needs an object, not a dictionary
            self.kwargstruct = KwargsStruct(**self.kwargs)
            for extension in self.extensions:
                extension.run_hooks('__post_parse_args__', self.kwargstruct)
            self.kwargs = self.kwargstruct.__dict__

        self.kwargs = sanatize_novaclient(self.kwargs)

        # Requires novaclient version >= 2.6.1
        self.kwargs['version'] = six.text_type(kwargs.get('version', 2))

        conn = client.Client(**self.kwargs)
        try:
            conn.client.authenticate()
        except novaclient.exceptions.AmbiguousEndpoints:
            raise SaltCloudSystemExit(
                "Nova provider requires a 'region_name' to be specified")

        self.kwargs['auth_token'] = conn.client.auth_token
        self.catalog = conn.client.service_catalog.catalog['access'][
            'serviceCatalog']

        self._v2_setup(region_name)
예제 #6
0
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_API_KEY': 'password',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.0',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient
예제 #7
0
    def _new_init(self, username, project_id, auth_url, region_name, password, os_auth_plugin, auth=None, verify=True, **kwargs):
        if auth is None:
            auth = {}

        loader = keystoneauth1.loading.get_plugin_loader(os_auth_plugin or 'password')

        self.client_kwargs = kwargs.copy()
        self.kwargs = auth.copy()
        if not self.extensions:
            if hasattr(OpenStackComputeShell, '_discover_extensions'):
                self.extensions = OpenStackComputeShell()._discover_extensions('2.0')
            else:
                self.extensions = client.discover_extensions('2.0')
            for extension in self.extensions:
                extension.run_hooks('__pre_parse_args__')
            self.client_kwargs['extensions'] = self.extensions

        self.kwargs['username'] = username
        self.kwargs['project_name'] = project_id
        self.kwargs['auth_url'] = auth_url
        self.kwargs['password'] = password
        if auth_url.endswith('3'):
            self.kwargs['user_domain_name'] = kwargs.get('user_domain_name', 'default')
            self.kwargs['project_domain_name'] = kwargs.get('project_domain_name', 'default')

        self.client_kwargs['region_name'] = region_name
        self.client_kwargs['service_type'] = 'compute'

        if hasattr(self, 'extensions'):
            # needs an object, not a dictionary
            self.kwargstruct = KwargsStruct(**self.client_kwargs)
            for extension in self.extensions:
                extension.run_hooks('__post_parse_args__', self.kwargstruct)
            self.client_kwargs = self.kwargstruct.__dict__

        # Requires novaclient version >= 2.6.1
        self.version = str(kwargs.get('version', 2))

        self.client_kwargs = sanatize_novaclient(self.client_kwargs)
        options = loader.load_from_options(**self.kwargs)
        self.session = keystoneauth1.session.Session(auth=options, verify=verify)
        conn = client.Client(version=self.version, session=self.session, **self.client_kwargs)
        self.kwargs['auth_token'] = conn.client.session.get_token()
        identity_service_type = kwargs.get('identity_service_type', 'identity')
        self.catalog = conn.client.session.get('/auth/catalog', endpoint_filter={'service_type': identity_service_type}).json().get('catalog', [])
        if conn.client.get_endpoint(service_type=identity_service_type).endswith('v3'):
            self._v3_setup(region_name)
        else:
            self._v2_setup(region_name)
예제 #8
0
class ShellTest(utils.TestCase):

    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_API_KEY': 'password',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.0',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient

    def tearDown(self):
        os.environ = self.old_environment

    def run_command(self, cmd):
        self.shell.main(cmd.split())

    def assert_called(self, method, url, body=None):
        return self.shell.cs.assert_called(method, url, body)

    def assert_called_anytime(self, method, url, body=None):
        return self.shell.cs.assert_called_anytime(method, url, body)

    def test_backup_schedule(self):
        self.run_command('backup-schedule 1234')
        self.assert_called('GET', '/servers/1234/backup_schedule')

        self.run_command('backup-schedule sample-server --weekly monday')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule',
            {'backupSchedule': {'enabled': True, 'daily': 'DISABLED',
                                'weekly': 'MONDAY'}}
        )

        self.run_command('backup-schedule sample-server '
              '--weekly disabled --daily h_0000_0200')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule',
            {'backupSchedule': {'enabled': True, 'daily': 'H_0000_0200',
                                'weekly': 'DISABLED'}}
        )

        self.run_command('backup-schedule sample-server --disable')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule',
            {'backupSchedule': {'enabled': False, 'daily': 'DISABLED',
                                'weekly': 'DISABLED'}}
        )

    def test_backup_schedule_delete(self):
        self.run_command('backup-schedule-delete 1234')
        self.assert_called('DELETE', '/servers/1234/backup_schedule')

    def test_boot(self):
        self.run_command('boot --image 1 some-server')
        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
             'min_count': 1, 'max_count': 1}}
        )

        self.run_command('boot --image 1 --meta foo=bar'
                         ' --meta spam=eggs some-server ')
        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
                        'min_count': 1, 'max_count': 1,
                        'metadata': {'foo': 'bar', 'spam': 'eggs'}}}
        )

    def test_boot_files(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')

        self.run_command('boot some-server --image 1 '
                         '--file /tmp/foo=%s --file /tmp/bar=%s' %
                         (testfile, testfile))

        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
                        'min_count': 1, 'max_count': 1,
                        'personality': [
                          {'path': '/tmp/bar', 'contents': expected_file_data},
                          {'path': '/tmp/foo', 'contents': expected_file_data}
                        ]}
            }
        )

    def test_boot_invalid_file(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        self.assertRaises(exceptions.CommandError, self.run_command,
                          'boot some-server --image 1 '
                          '--file /foo=%s' % invalid_file)

    def test_boot_key_auto(self):
        mock_exists = mock.Mock(return_value=True)
        mock_open = mock.Mock()
        mock_open.return_value = mock.Mock()
        mock_open.return_value.read = mock.Mock(return_value='SSHKEY')

        @mock.patch('os.path.exists', mock_exists)
        @mock.patch('__builtin__.open', mock_open)
        def test_shell_call():
            self.run_command('boot some-server --image 1 --key')
            self.assert_called(
                'POST', '/servers',
                {'server': {'flavorId': 1, 'name': 'some-server',
                            'imageId': 1, 'min_count': 1, 'max_count': 1,
                            'personality': [{
                                'path': '/root/.ssh/authorized_keys2',
                                'contents': ('SSHKEY').encode('base64')},
                            ]}
                }
            )

        test_shell_call()

    def test_boot_key_auto_no_keys(self):
        mock_exists = mock.Mock(return_value=False)

        @mock.patch('os.path.exists', mock_exists)
        def test_shell_call():
            self.assertRaises(exceptions.CommandError, self.run_command,
                              'boot some-server --image 1 --key')

        test_shell_call()

    def test_boot_key_file(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')
        self.run_command('boot some-server --image 1 --key %s' % testfile)
        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
                        'min_count': 1, 'max_count': 1,
                        'personality': [
                            {'path': '/root/.ssh/authorized_keys2', 'contents':
                             expected_file_data},
                        ]}
            }
        )

    def test_boot_invalid_keyfile(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        self.assertRaises(exceptions.CommandError, self.run_command,
                          'boot some-server --image 1 --key %s' % invalid_file)

    def test_boot_ipgroup(self):
        self.run_command('boot --image 1 --ipgroup 1 some-server')
        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
                        'sharedIpGroupId': 1, 'min_count': 1, 'max_count': 1}}
        )

    def test_boot_ipgroup_name(self):
        self.run_command('boot --image 1 --ipgroup group1 some-server')
        self.assert_called(
            'POST', '/servers',
            {'server': {'flavorId': 1, 'name': 'some-server', 'imageId': 1,
                        'sharedIpGroupId': 1, 'min_count': 1, 'max_count': 1}}
        )

    def test_flavor_list(self):
        self.run_command('flavor-list')
        self.assert_called_anytime('GET', '/flavors/detail')

    def test_image_list(self):
        self.run_command('image-list')
        self.assert_called('GET', '/images/detail')

    def test_snapshot_create(self):
        self.run_command('image-create sample-server mysnapshot')
        self.assert_called(
            'POST', '/images',
            {'image': {'name': 'mysnapshot', 'serverId': 1234}}
        )

    def test_image_delete(self):
        self.run_command('image-delete 1')
        self.assert_called('DELETE', '/images/1')

    def test_ip_share(self):
        self.run_command('ip-share sample-server 1 1.2.3.4')
        self.assert_called(
            'PUT', '/servers/1234/ips/public/1.2.3.4',
            {'shareIp': {'sharedIpGroupId': 1, 'configureServer': True}}
        )

    def test_ip_unshare(self):
        self.run_command('ip-unshare sample-server 1.2.3.4')
        self.assert_called('DELETE', '/servers/1234/ips/public/1.2.3.4')

    def test_ipgroup_list(self):
        self.run_command('ipgroup-list')
        assert ('GET', '/shared_ip_groups/detail', None) in \
                  self.shell.cs.client.callstack
        self.assert_called('GET', '/servers/5678')

    def test_ipgroup_show(self):
        self.run_command('ipgroup-show 1')
        self.assert_called('GET', '/shared_ip_groups/1')
        self.run_command('ipgroup-show group2')
        # does a search, not a direct GET
        self.assert_called('GET', '/shared_ip_groups/detail')

    def test_ipgroup_create(self):
        self.run_command('ipgroup-create a-group')
        self.assert_called(
            'POST', '/shared_ip_groups',
            {'sharedIpGroup': {'name': 'a-group'}}
        )
        self.run_command('ipgroup-create a-group sample-server')
        self.assert_called(
            'POST', '/shared_ip_groups',
            {'sharedIpGroup': {'name': 'a-group', 'server': 1234}}
        )

    def test_ipgroup_delete(self):
        self.run_command('ipgroup-delete group1')
        self.assert_called('DELETE', '/shared_ip_groups/1')

    def test_list(self):
        self.run_command('list')
        self.assert_called('GET', '/servers/detail')

    def test_reboot(self):
        self.run_command('reboot sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'SOFT'}})
        self.run_command('reboot sample-server --hard')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'HARD'}})

    def test_rebuild(self):
        self.run_command('rebuild sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'rebuild': {'imageId': 1}})

    def test_rename(self):
        self.run_command('rename sample-server newname')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {'name': 'newname'}})

    def test_resize(self):
        self.run_command('resize sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'resize': {'flavorId': 1}})

    def test_resize_confirm(self):
        self.run_command('resize-confirm sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'confirmResize': None})

    def test_resize_revert(self):
        self.run_command('resize-revert sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'revertResize': None})

    def test_backup(self):
        self.run_command('backup sample-server mybackup daily 1')
        self.assert_called(
            'POST', '/servers/1234/action',
            {'createBackup': {'name': 'mybackup', 'backup_type': 'daily',
                              'rotation': 1}}
        )

    @mock.patch('getpass.getpass', mock.Mock(return_value='p'))
    def test_root_password(self):
        self.run_command('root-password sample-server')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {'adminPass': '******'}})

    def test_show(self):
        self.run_command('show 1234')
        # XXX need a way to test multiple calls
        # self.assert_called('GET', '/servers/1234')
        self.assert_called('GET', '/images/2')

    def test_delete(self):
        self.run_command('delete 1234')
        self.assert_called('DELETE', '/servers/1234')
        self.run_command('delete sample-server')
        self.assert_called('DELETE', '/servers/1234')

    def test_zone(self):
        self.run_command('zone 1')
        self.assert_called('GET', '/zones/1')

        self.run_command('zone 1 --api_url=http://zzz '
                         '--zone_username=frank --password=xxx')
        self.assert_called(
            'PUT', '/zones/1',
            {'zone': {'username': '******', 'password': '******',
             'api_url': 'http://zzz'}}
        )

    def test_zone_add(self):
        self.run_command('zone-add child_zone http://zzz '
                         '--zone_username=frank --password=xxx '
                         '--weight_offset=0.0 --weight_scale=1.0')
        self.assert_called(
            'POST', '/zones',
            {'zone': {'name': 'child_zone',
                      'api_url': 'http://zzz', 'username': '******',
                      'password': '******',
                      'weight_offset': '0.0', 'weight_scale': '1.0'}}
        )

    def test_zone_add_optional(self):
        self.run_command('zone-add child_zone http://zzz')
        self.assert_called(
            'POST', '/zones',
             {'zone': {'name': 'child_zone',
                      'api_url': 'http://zzz',
                      'username': None,
                      'password': None,
                      'weight_offset': 0.0, 'weight_scale': 1.0}}
        )


    def test_zone_delete(self):
        self.run_command('zone-delete 1')
        self.assert_called('DELETE', '/zones/1')

    def test_zone_list(self):
        self.run_command('zone-list')
        assert ('GET', '/zones/detail', None) in self.shell.cs.client.callstack
예제 #9
0
    def _new_init(self,
                  username,
                  project_id,
                  auth_url,
                  region_name,
                  password,
                  os_auth_plugin,
                  auth=None,
                  verify=True,
                  **kwargs):
        if auth is None:
            auth = {}

        loader = keystoneauth1.loading.get_plugin_loader(os_auth_plugin
                                                         or "password")

        self.client_kwargs = kwargs.copy()
        self.kwargs = auth.copy()
        if not self.extensions:
            if hasattr(OpenStackComputeShell, "_discover_extensions"):
                self.extensions = OpenStackComputeShell()._discover_extensions(
                    "2.0")
            else:
                self.extensions = client.discover_extensions("2.0")
            for extension in self.extensions:
                extension.run_hooks("__pre_parse_args__")
            self.client_kwargs["extensions"] = self.extensions

        self.kwargs["username"] = username
        self.kwargs["project_name"] = project_id
        self.kwargs["auth_url"] = auth_url
        self.kwargs["password"] = password
        if auth_url.endswith("3"):
            self.kwargs["user_domain_name"] = kwargs.get(
                "user_domain_name", "default")
            self.kwargs["project_domain_name"] = kwargs.get(
                "project_domain_name", "default")

        self.client_kwargs["region_name"] = region_name
        self.client_kwargs["service_type"] = "compute"

        if hasattr(self, "extensions"):
            # needs an object, not a dictionary
            self.kwargstruct = KwargsStruct(**self.client_kwargs)
            for extension in self.extensions:
                extension.run_hooks("__post_parse_args__", self.kwargstruct)
            self.client_kwargs = self.kwargstruct.__dict__

        # Requires novaclient version >= 2.6.1
        self.version = str(kwargs.get("version", 2))

        self.client_kwargs = sanatize_novaclient(self.client_kwargs)
        options = loader.load_from_options(**self.kwargs)
        self.session = keystoneauth1.session.Session(auth=options,
                                                     verify=verify)
        conn = client.Client(version=self.version,
                             session=self.session,
                             **self.client_kwargs)
        self.kwargs["auth_token"] = conn.client.session.get_token()
        identity_service_type = kwargs.get("identity_service_type", "identity")
        self.catalog = (conn.client.session.get("/auth/catalog",
                                                endpoint_filter={
                                                    "service_type":
                                                    identity_service_type
                                                }).json().get("catalog", []))
        if conn.client.get_endpoint(
                service_type=identity_service_type).endswith("v3"):
            self._v3_setup(region_name)
        else:
            self._v2_setup(region_name)
예제 #10
0
class ShellTest(utils.TestCase):

    # Patch os.environ to avoid required auth info.
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_API_KEY': 'password',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.1',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient

    def tearDown(self):
        os.environ = self.old_environment

    def run_command(self, cmd):
        self.shell.main(cmd.split())

    def assert_called(self, method, url, body=None):
        return self.shell.cs.assert_called(method, url, body)

    def assert_called_anytime(self, method, url, body=None):
        return self.shell.cs.assert_called_anytime(method, url, body)

    def test_boot(self):
        self.run_command('boot --image 1 some-server')
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': 1,
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
            }}
        )

        self.run_command('boot --image 1 --meta foo=bar'
                         ' --meta spam=eggs some-server ')
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': 1,
                'name': 'some-server',
                'imageRef': '1',
                'metadata': {'foo': 'bar', 'spam': 'eggs'},
                'min_count': 1,
                'max_count': 1,
            }}
        )

    def test_boot_files(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')

        cmd = 'boot some-server --image 1 ' \
              '--file /tmp/foo=%s --file /tmp/bar=%s'
        self.run_command(cmd % (testfile, testfile))

        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': 1,
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
                'personality': [
                   {'path': '/tmp/bar', 'contents': expected_file_data},
                   {'path': '/tmp/foo', 'contents': expected_file_data}
                ]}
            }
        )

    def test_boot_invalid_file(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        cmd = 'boot some-server --image 1 --file /foo=%s' % invalid_file
        self.assertRaises(exceptions.CommandError, self.run_command, cmd)

    def test_boot_key_auto(self):
        mock_exists = mock.Mock(return_value=True)
        mock_open = mock.Mock()
        mock_open.return_value = mock.Mock()
        mock_open.return_value.read = mock.Mock(return_value='SSHKEY')

        @mock.patch('os.path.exists', mock_exists)
        @mock.patch('__builtin__.open', mock_open)
        def test_shell_call():
            self.run_command('boot some-server --image 1 --key')
            self.assert_called_anytime(
                'POST', '/servers',
                {'server': {
                    'flavorRef': 1,
                    'name': 'some-server',
                    'imageRef': '1',
                    'min_count': 1,
                    'max_count': 1,
                    'personality': [{
                        'path': '/root/.ssh/authorized_keys2',
                        'contents': ('SSHKEY').encode('base64')},
                    ]}
                }
            )

        test_shell_call()

    def test_boot_key_auto_no_keys(self):
        mock_exists = mock.Mock(return_value=False)

        @mock.patch('os.path.exists', mock_exists)
        def test_shell_call():
            self.assertRaises(exceptions.CommandError, self.run_command,
                              'boot some-server --image 1 --key')

        test_shell_call()

    def test_boot_key_file(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')
        self.run_command('boot some-server --image 1 --key %s' % testfile)
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': 1,
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
                'personality': [
                    {'path': '/root/.ssh/authorized_keys2',
                     'contents':expected_file_data},
                 ]}
            }
        )

    def test_boot_invalid_keyfile(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        self.assertRaises(exceptions.CommandError, self.run_command,
                          'boot some-server --image 1 --key %s' % invalid_file)

    def test_flavor_list(self):
        self.run_command('flavor-list')
        self.assert_called_anytime('GET', '/flavors/detail')

    def test_image_list(self):
        self.run_command('image-list')
        self.assert_called('GET', '/images/detail')

    def test_create_image(self):
        self.run_command('image-create sample-server mysnapshot')
        self.assert_called(
            'POST', '/servers/1234/action',
            {'createImage': {'name': 'mysnapshot', 'metadata': {}}}
        )

    def test_image_delete(self):
        self.run_command('image-delete 1')
        self.assert_called('DELETE', '/images/1')

    def test_list(self):
        self.run_command('list')
        self.assert_called('GET', '/servers/detail')

    def test_reboot(self):
        self.run_command('reboot sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'SOFT'}})
        self.run_command('reboot sample-server --hard')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'HARD'}})

    def test_rebuild(self):
        self.run_command('rebuild sample-server 1')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1}})
        self.assert_called('GET', '/images/2')

        self.run_command('rebuild sample-server 1 --password asdf')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1, 'adminPass': '******'}})
        self.assert_called('GET', '/images/2')


    def test_rename(self):
        self.run_command('rename sample-server newname')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {'name': 'newname'}})

    def test_resize(self):
        self.run_command('resize sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'resize': {'flavorRef': 1}})

    def test_resize_confirm(self):
        self.run_command('resize-confirm sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'confirmResize': None})

    def test_resize_revert(self):
        self.run_command('resize-revert sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'revertResize': None})

    @mock.patch('getpass.getpass', mock.Mock(return_value='p'))
    def test_root_password(self):
        self.run_command('root-password sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'changePassword': {'adminPass': '******'}})

    def test_show(self):
        self.run_command('show 1234')
        # XXX need a way to test multiple calls
        # assert_called('GET', '/servers/1234')
        self.assert_called('GET', '/images/2')

    def test_delete(self):
        self.run_command('delete 1234')
        self.assert_called('DELETE', '/servers/1234')
        self.run_command('delete sample-server')
        self.assert_called('DELETE', '/servers/1234')
예제 #11
0
class ShellTest(utils.TestCase):

    # Patch os.environ to avoid required auth info.
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_API_KEY': 'password',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.1',
            'NOVA_URL': 'http://no.where',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient

    def tearDown(self):
        os.environ = self.old_environment
        # For some method like test_image_meta_bad_action we are
        # testing a SystemExit to be thrown and object self.shell has
        # no time to get instantatiated which is OK in this case, so
        # we make sure the method is there before launching it.
        if hasattr(self.shell, 'cs'):
            self.shell.cs.clear_callstack()

    def run_command(self, cmd):
        self.shell.main(cmd.split())

    def assert_called(self, method, url, body=None, **kwargs):
        return self.shell.cs.assert_called(method, url, body, **kwargs)

    def assert_called_anytime(self, method, url, body=None):
        return self.shell.cs.assert_called_anytime(method, url, body)

    def test_boot(self):
        self.run_command('boot --flavor 1 --image 1 some-server')
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': '1',
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
                }},
        )

        self.run_command('boot --image 1 --flavor 1 --meta foo=bar'
                         ' --meta spam=eggs some-server ')
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': '1',
                'name': 'some-server',
                'imageRef': '1',
                'metadata': {'foo': 'bar', 'spam': 'eggs'},
                'min_count': 1,
                'max_count': 1,
            }},
        )

    def test_boot_files(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')

        cmd = 'boot some-server --flavor 1 --image 1 ' \
              '--file /tmp/foo=%s --file /tmp/bar=%s'
        self.run_command(cmd % (testfile, testfile))

        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': '1',
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
                'personality': [
                   {'path': '/tmp/bar', 'contents': expected_file_data},
                   {'path': '/tmp/foo', 'contents': expected_file_data},
                ]},
            },
        )

    def test_boot_invalid_file(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        cmd = 'boot some-server --image 1 --file /foo=%s' % invalid_file
        self.assertRaises(exceptions.CommandError, self.run_command, cmd)

    def test_boot_key_auto(self):
        mock_exists = mock.Mock(return_value=True)
        mock_open = mock.Mock()
        mock_open.return_value = mock.Mock()
        mock_open.return_value.read = mock.Mock(return_value='SSHKEY')

        @mock.patch('os.path.exists', mock_exists)
        @mock.patch('__builtin__.open', mock_open)
        def test_shell_call():
            self.run_command('boot some-server --flavor 1 --image 1 --key_path')
            self.assert_called_anytime(
                'POST', '/servers',
                {'server': {
                    'flavorRef': '1',
                    'name': 'some-server',
                    'imageRef': '1',
                    'min_count': 1,
                    'max_count': 1,
                    'personality': [{
                        'path': '/root/.ssh/authorized_keys2',
                        'contents': ('SSHKEY').encode('base64')},
                    ]},
                },
            )

        test_shell_call()

    def test_boot_key_auto_no_keys(self):
        mock_exists = mock.Mock(return_value=False)

        @mock.patch('os.path.exists', mock_exists)
        def test_shell_call():
            self.assertRaises(exceptions.CommandError, self.run_command,
                              'boot some-server --flavor 1 --image 1 --key_path')

        test_shell_call()

    def test_boot_key_file(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')
        cmd = 'boot some-server --flavor 1 --image 1 --key_path %s'
        self.run_command(cmd % testfile)
        self.assert_called_anytime(
            'POST', '/servers',
            {'server': {
                'flavorRef': '1',
                'name': 'some-server',
                'imageRef': '1',
                'min_count': 1,
                'max_count': 1,
                'personality': [
                    {'path': '/root/.ssh/authorized_keys2',
                     'contents':expected_file_data},
                 ]},
            },
        )

    def test_boot_invalid_keyfile(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        cmd = 'boot some-server --flavor 1 --image 1 --key_path %s'
        self.assertRaises(exceptions.CommandError, self.run_command,
                          cmd % invalid_file)

    def test_flavor_list(self):
        self.run_command('flavor-list')
        self.assert_called_anytime('GET', '/flavors/detail')

    def test_image_show(self):
        self.run_command('image-show 1')
        self.assert_called('GET', '/images/1')

    def test_image_meta_set(self):
        self.run_command('image-meta 1 set test_key=test_value')
        self.assert_called('POST', '/images/1/metadata',
            {'metadata': {'test_key': 'test_value'}})

    def test_image_meta_del(self):
        self.run_command('image-meta 1 delete test_key=test_value')
        self.assert_called('DELETE', '/images/1/metadata/test_key')

    def test_image_meta_bad_action(self):
        tmp = tempfile.TemporaryFile()

        # Suppress stdout and stderr
        (stdout, stderr) = (sys.stdout, sys.stderr)
        (sys.stdout, sys.stderr) = (tmp, tmp)

        self.assertRaises(SystemExit, self.run_command,
                          'image-meta 1 BAD_ACTION test_key=test_value')

        # Put stdout and stderr back
        sys.stdout, sys.stderr = (stdout, stderr)

    def test_image_list(self):
        self.run_command('image-list')
        self.assert_called('GET', '/images/detail')

    def test_create_image(self):
        self.run_command('image-create sample-server mysnapshot')
        self.assert_called(
            'POST', '/servers/1234/action',
            {'createImage': {'name': 'mysnapshot', 'metadata': {}}},
        )

    def test_image_delete(self):
        self.run_command('image-delete 1')
        self.assert_called('DELETE', '/images/1')

    def test_list(self):
        self.run_command('list')
        self.assert_called('GET', '/servers/detail')

    def test_reboot(self):
        self.run_command('reboot sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'SOFT'}})
        self.run_command('reboot sample-server --hard')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {'type': 'HARD'}})

    def test_rebuild(self):
        self.run_command('rebuild sample-server 1')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1}})
        self.assert_called('GET', '/images/2')

        self.run_command('rebuild sample-server 1 --password asdf')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1, 'adminPass': '******'}})
        self.assert_called('GET', '/images/2')

    def test_rename(self):
        self.run_command('rename sample-server newname')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {'name': 'newname'}})

    def test_resize(self):
        self.run_command('resize sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'resize': {'flavorRef': 1}})

    def test_resize_confirm(self):
        self.run_command('resize-confirm sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'confirmResize': None})

    def test_resize_revert(self):
        self.run_command('resize-revert sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'revertResize': None})

    @mock.patch('getpass.getpass', mock.Mock(return_value='p'))
    def test_root_password(self):
        self.run_command('root-password sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'changePassword': {'adminPass': '******'}})

    def test_show(self):
        self.run_command('show 1234')
        self.assert_called('GET', '/servers/1234', pos=-3)
        self.assert_called('GET', '/flavors/1', pos=-2)
        self.assert_called('GET', '/images/2')

    def test_show_bad_id(self):
        self.assertRaises(exceptions.CommandError, 
                          self.run_command, 'show xxx')

    def test_delete(self):
        self.run_command('delete 1234')
        self.assert_called('DELETE', '/servers/1234')
        self.run_command('delete sample-server')
        self.assert_called('DELETE', '/servers/1234')


    def test_set_meta_set(self):
        self.run_command('meta 1234 set key1=val1 key2=val2')
        self.assert_called('POST', '/servers/1234/metadata',
                           {'metadata': {'key1': 'val1', 'key2': 'val2'}})

    def test_set_meta_delete_dict(self):
        self.run_command('meta 1234 delete key1=val1 key2=val2')
        self.assert_called('DELETE', '/servers/1234/metadata/key1')
        self.assert_called('DELETE', '/servers/1234/metadata/key2', pos=-2)

    def test_set_meta_delete_keys(self):
        self.run_command('meta 1234 delete key1 key2')
        self.assert_called('DELETE', '/servers/1234/metadata/key1')
        self.assert_called('DELETE', '/servers/1234/metadata/key2', pos=-2)
예제 #12
0
파일: nova.py 프로젝트: fake-name/salt
    def _new_init(self, username, project_id, auth_url, region_name, password, os_auth_plugin, auth=None, **kwargs):
        if auth is None:
            auth = {}

        ks_version = self._get_version_from_url(auth_url)
        if not ks_version:
            ks_version = self._discover_ks_version(auth_url)
            auth_url = '{0}/{1}'.format(auth_url, ks_version)

        loader = keystoneauth1.loading.get_plugin_loader(os_auth_plugin or 'password')

        self.client_kwargs = kwargs.copy()
        self.kwargs = auth.copy()
        if not self.extensions:
            if hasattr(OpenStackComputeShell, "_discover_extensions"):
                self.extensions = OpenStackComputeShell()._discover_extensions("2.0")
            else:
                self.extensions = client.discover_extensions("2.0")
            for extension in self.extensions:
                extension.run_hooks('__pre_parse_args__')
            self.client_kwargs['extensions'] = self.extensions

        self.kwargs['username'] = username
        self.kwargs['project_name'] = project_id
        self.kwargs['auth_url'] = auth_url
        self.kwargs['password'] = password
        if ks_version == 'v3':
            self.kwargs['project_id'] = kwargs.get('project_id')
            self.kwargs['project_name'] = kwargs.get('project_name')
            self.kwargs['user_domain_name'] = kwargs.get('user_domain_name', 'default')
            self.kwargs['project_domain_name'] = kwargs.get('project_domain_name', 'default')

        self.client_kwargs["region_name"] = region_name
        self.client_kwargs["service_type"] = "compute"

        if hasattr(self, "extensions"):
            # needs an object, not a dictionary
            self.kwargstruct = KwargsStruct(**self.client_kwargs)
            for extension in self.extensions:
                extension.run_hooks("__post_parse_args__", self.kwargstruct)
            self.client_kwargs = self.kwargstruct.__dict__

        # Requires novaclient version >= 2.6.1
        self.version = six.text_type(kwargs.get("version", 2))

        self.client_kwargs = sanatize_novaclient(self.client_kwargs)
        options = loader.load_from_options(**self.kwargs)
        self.session = keystoneauth1.session.Session(auth=options)
        conn = client.Client(version=self.version, session=self.session, **self.client_kwargs)
        self.kwargs['auth_token'] = conn.client.session.get_token()
        identity_service_type = kwargs.get('identity_service_type', 'identity')
        self.catalog = conn.client.session.get('/' + ks_version + '/auth/catalog',
                                               endpoint_filter={'service_type': identity_service_type}
                                               ).json().get('catalog', [])
        for ep_type in self.catalog:
            if ep_type['type'] == identity_service_type:
                for ep_id in ep_type['endpoints']:
                    ep_ks_version = self._get_version_from_url(ep_id['url'])
                    if not ep_ks_version:
                        ep_id['url'] = '{0}/{1}'.format(ep_id['url'], ks_version)
        if ks_version == 'v3':
            self._v3_setup(region_name)
        else:
            self._v2_setup(region_name)
예제 #13
0
class ShellTest(utils.TestCase):
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_PASSWORD': '******',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.0',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient

    def tearDown(self):
        os.environ = self.old_environment

    def run_command(self, cmd):
        self.shell.main(cmd.split())

    def assert_called(self, method, url, body=None):
        return self.shell.cs.assert_called(method, url, body)

    def assert_called_anytime(self, method, url, body=None):
        return self.shell.cs.assert_called_anytime(method, url, body)

    def test_backup_schedule(self):
        self.run_command('backup-schedule 1234')
        self.assert_called('GET', '/servers/1234/backup_schedule')

        self.run_command('backup-schedule sample-server --weekly monday')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule', {
                'backupSchedule': {
                    'enabled': True,
                    'daily': 'DISABLED',
                    'weekly': 'MONDAY'
                }
            })

        self.run_command('backup-schedule sample-server '
                         '--weekly disabled --daily h_0000_0200')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule', {
                'backupSchedule': {
                    'enabled': True,
                    'daily': 'H_0000_0200',
                    'weekly': 'DISABLED'
                }
            })

        self.run_command('backup-schedule sample-server --disable')
        self.assert_called(
            'POST', '/servers/1234/backup_schedule', {
                'backupSchedule': {
                    'enabled': False,
                    'daily': 'DISABLED',
                    'weekly': 'DISABLED'
                }
            })

    def test_backup_schedule_delete(self):
        self.run_command('backup-schedule-delete 1234')
        self.assert_called('DELETE', '/servers/1234/backup_schedule')

    def test_boot(self):
        self.run_command('boot --image 1 some-server')
        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId': 1,
                    'name': 'some-server',
                    'imageId': 1,
                    'min_count': 1,
                    'max_count': 1
                }
            })

        self.run_command('boot --image 1 --meta foo=bar'
                         ' --meta spam=eggs some-server ')
        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId': 1,
                    'name': 'some-server',
                    'imageId': 1,
                    'min_count': 1,
                    'max_count': 1,
                    'metadata': {
                        'foo': 'bar',
                        'spam': 'eggs'
                    }
                }
            })

    def test_boot_files(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')

        self.run_command('boot some-server --image 1 '
                         '--file /tmp/foo=%s --file /tmp/bar=%s' %
                         (testfile, testfile))

        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId':
                    1,
                    'name':
                    'some-server',
                    'imageId':
                    1,
                    'min_count':
                    1,
                    'max_count':
                    1,
                    'personality': [{
                        'path': '/tmp/bar',
                        'contents': expected_file_data
                    }, {
                        'path': '/tmp/foo',
                        'contents': expected_file_data
                    }]
                }
            })

    def test_boot_invalid_file(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        self.assertRaises(
            exceptions.CommandError, self.run_command,
            'boot some-server --image 1 '
            '--file /foo=%s' % invalid_file)

    def test_boot_key_auto(self):
        mock_exists = mock.Mock(return_value=True)
        mock_open = mock.Mock()
        mock_open.return_value = mock.Mock()
        mock_open.return_value.read = mock.Mock(return_value='SSHKEY')

        @mock.patch('os.path.exists', mock_exists)
        @mock.patch('__builtin__.open', mock_open)
        def test_shell_call():
            self.run_command('boot some-server --image 1 --key')
            self.assert_called(
                'POST', '/servers', {
                    'server': {
                        'flavorId':
                        1,
                        'name':
                        'some-server',
                        'imageId':
                        1,
                        'min_count':
                        1,
                        'max_count':
                        1,
                        'personality': [
                            {
                                'path': '/root/.ssh/authorized_keys2',
                                'contents': ('SSHKEY').encode('base64')
                            },
                        ]
                    }
                })

        test_shell_call()

    def test_boot_key_auto_no_keys(self):
        mock_exists = mock.Mock(return_value=False)

        @mock.patch('os.path.exists', mock_exists)
        def test_shell_call():
            self.assertRaises(exceptions.CommandError, self.run_command,
                              'boot some-server --image 1 --key')

        test_shell_call()

    def test_boot_key_file(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')
        self.run_command('boot some-server --image 1 --key %s' % testfile)
        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId':
                    1,
                    'name':
                    'some-server',
                    'imageId':
                    1,
                    'min_count':
                    1,
                    'max_count':
                    1,
                    'personality': [
                        {
                            'path': '/root/.ssh/authorized_keys2',
                            'contents': expected_file_data
                        },
                    ]
                }
            })

    def test_boot_invalid_keyfile(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        self.assertRaises(exceptions.CommandError, self.run_command,
                          'boot some-server --image 1 --key %s' % invalid_file)

    def test_boot_ipgroup(self):
        self.run_command('boot --image 1 --ipgroup 1 some-server')
        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId': 1,
                    'name': 'some-server',
                    'imageId': 1,
                    'sharedIpGroupId': 1,
                    'min_count': 1,
                    'max_count': 1
                }
            })

    def test_boot_ipgroup_name(self):
        self.run_command('boot --image 1 --ipgroup group1 some-server')
        self.assert_called(
            'POST', '/servers', {
                'server': {
                    'flavorId': 1,
                    'name': 'some-server',
                    'imageId': 1,
                    'sharedIpGroupId': 1,
                    'min_count': 1,
                    'max_count': 1
                }
            })

    def test_flavor_list(self):
        self.run_command('flavor-list')
        self.assert_called_anytime('GET', '/flavors/detail')

    def test_image_list(self):
        self.run_command('image-list')
        self.assert_called('GET', '/images/detail')

    def test_snapshot_create(self):
        self.run_command('image-create sample-server mysnapshot')
        self.assert_called('POST', '/images',
                           {'image': {
                               'name': 'mysnapshot',
                               'serverId': 1234
                           }})

    def test_image_delete(self):
        self.run_command('image-delete 1')
        self.assert_called('DELETE', '/images/1')

    def test_ip_share(self):
        self.run_command('ip-share sample-server 1 1.2.3.4')
        self.assert_called(
            'PUT', '/servers/1234/ips/public/1.2.3.4',
            {'shareIp': {
                'sharedIpGroupId': 1,
                'configureServer': True
            }})

    def test_ip_unshare(self):
        self.run_command('ip-unshare sample-server 1.2.3.4')
        self.assert_called('DELETE', '/servers/1234/ips/public/1.2.3.4')

    def test_ipgroup_list(self):
        self.run_command('ipgroup-list')
        assert ('GET', '/shared_ip_groups/detail', None) in \
                  self.shell.cs.client.callstack
        self.assert_called('GET', '/servers/5678')

    def test_ipgroup_show(self):
        self.run_command('ipgroup-show 1')
        self.assert_called('GET', '/shared_ip_groups/1')
        self.run_command('ipgroup-show group2')
        # does a search, not a direct GET
        self.assert_called('GET', '/shared_ip_groups/detail')

    def test_ipgroup_create(self):
        self.run_command('ipgroup-create a-group')
        self.assert_called('POST', '/shared_ip_groups',
                           {'sharedIpGroup': {
                               'name': 'a-group'
                           }})
        self.run_command('ipgroup-create a-group sample-server')
        self.assert_called(
            'POST', '/shared_ip_groups',
            {'sharedIpGroup': {
                'name': 'a-group',
                'server': 1234
            }})

    def test_ipgroup_delete(self):
        self.run_command('ipgroup-delete group1')
        self.assert_called('DELETE', '/shared_ip_groups/1')

    def test_list(self):
        self.run_command('list')
        self.assert_called('GET', '/servers/detail')

    def test_reboot(self):
        self.run_command('reboot sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {
                               'type': 'SOFT'
                           }})
        self.run_command('reboot sample-server --hard')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {
                               'type': 'HARD'
                           }})

    def test_rebuild(self):
        self.run_command('rebuild sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'rebuild': {
                               'imageId': 1
                           }})

    def test_rename(self):
        self.run_command('rename sample-server newname')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {
                               'name': 'newname'
                           }})

    def test_resize(self):
        self.run_command('resize sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'resize': {
                               'flavorId': 1
                           }})

    def test_resize_confirm(self):
        self.run_command('resize-confirm sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'confirmResize': None})

    def test_resize_revert(self):
        self.run_command('resize-revert sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'revertResize': None})

    def test_backup(self):
        self.run_command('backup sample-server mybackup daily 1')
        self.assert_called(
            'POST', '/servers/1234/action', {
                'createBackup': {
                    'name': 'mybackup',
                    'backup_type': 'daily',
                    'rotation': 1
                }
            })

    @mock.patch('getpass.getpass', mock.Mock(return_value='p'))
    def test_root_password(self):
        self.run_command('root-password sample-server')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {
                               'adminPass': '******'
                           }})

    def test_show(self):
        self.run_command('show 1234')
        # XXX need a way to test multiple calls
        # self.assert_called('GET', '/servers/1234')
        self.assert_called('GET', '/images/2')

    def test_delete(self):
        self.run_command('delete 1234')
        self.assert_called('DELETE', '/servers/1234')
        self.run_command('delete sample-server')
        self.assert_called('DELETE', '/servers/1234')

    def test_zone(self):
        self.run_command('zone 1')
        self.assert_called('GET', '/zones/1')

        self.run_command('zone 1 --api_url=http://zzz '
                         '--zone_username=frank --zone_password=xxx')
        self.assert_called(
            'PUT', '/zones/1', {
                'zone': {
                    'username': '******',
                    'password': '******',
                    'api_url': 'http://zzz'
                }
            })

    def test_zone_add(self):
        self.run_command('zone-add child_zone http://zzz '
                         '--zone_username=frank --zone_password=xxx '
                         '--weight_offset=0.0 --weight_scale=1.0')
        self.assert_called(
            'POST', '/zones', {
                'zone': {
                    'name': 'child_zone',
                    'api_url': 'http://zzz',
                    'username': '******',
                    'password': '******',
                    'weight_offset': '0.0',
                    'weight_scale': '1.0'
                }
            })

    def test_zone_add_optional(self):
        self.run_command('zone-add child_zone http://zzz')
        self.assert_called(
            'POST', '/zones', {
                'zone': {
                    'name': 'child_zone',
                    'api_url': 'http://zzz',
                    'username': None,
                    'password': None,
                    'weight_offset': 0.0,
                    'weight_scale': 1.0
                }
            })

    def test_zone_delete(self):
        self.run_command('zone-delete 1')
        self.assert_called('DELETE', '/zones/1')

    def test_zone_list(self):
        self.run_command('zone-list')
        assert ('GET', '/zones/detail', None) in self.shell.cs.client.callstack
예제 #14
0
class ShellTest(utils.TestCase):

    # Patch os.environ to avoid required auth info.
    def setUp(self):
        """Run before each test."""
        self.old_environment = os.environ.copy()
        os.environ = {
            'NOVA_USERNAME': '******',
            'NOVA_PASSWORD': '******',
            'NOVA_PROJECT_ID': 'project_id',
            'NOVA_VERSION': '1.1',
            'NOVA_URL': 'http://no.where',
        }

        self.shell = OpenStackComputeShell()
        self.shell.get_api_class = lambda *_: fakes.FakeClient

    def tearDown(self):
        os.environ = self.old_environment
        # For some method like test_image_meta_bad_action we are
        # testing a SystemExit to be thrown and object self.shell has
        # no time to get instantatiated which is OK in this case, so
        # we make sure the method is there before launching it.
        if hasattr(self.shell, 'cs'):
            self.shell.cs.clear_callstack()

    def run_command(self, cmd):
        self.shell.main(cmd.split())

    def assert_called(self, method, url, body=None, **kwargs):
        return self.shell.cs.assert_called(method, url, body, **kwargs)

    def assert_called_anytime(self, method, url, body=None):
        return self.shell.cs.assert_called_anytime(method, url, body)

    def test_boot(self):
        self.run_command('boot --flavor 1 --image 1 some-server')
        self.assert_called_anytime(
            'POST',
            '/servers',
            {
                'server': {
                    'flavorRef': '1',
                    'name': 'some-server',
                    'imageRef': '1',
                    'min_count': 1,
                    'max_count': 1,
                }
            },
        )

        self.run_command('boot --image 1 --flavor 1 --meta foo=bar'
                         ' --meta spam=eggs some-server ')
        self.assert_called_anytime(
            'POST',
            '/servers',
            {
                'server': {
                    'flavorRef': '1',
                    'name': 'some-server',
                    'imageRef': '1',
                    'metadata': {
                        'foo': 'bar',
                        'spam': 'eggs'
                    },
                    'min_count': 1,
                    'max_count': 1,
                }
            },
        )

    def test_boot_files(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')

        cmd = 'boot some-server --flavor 1 --image 1 ' \
              '--file /tmp/foo=%s --file /tmp/bar=%s'
        self.run_command(cmd % (testfile, testfile))

        self.assert_called_anytime(
            'POST',
            '/servers',
            {
                'server': {
                    'flavorRef':
                    '1',
                    'name':
                    'some-server',
                    'imageRef':
                    '1',
                    'min_count':
                    1,
                    'max_count':
                    1,
                    'personality': [
                        {
                            'path': '/tmp/bar',
                            'contents': expected_file_data
                        },
                        {
                            'path': '/tmp/foo',
                            'contents': expected_file_data
                        },
                    ]
                },
            },
        )

    def test_boot_invalid_file(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        cmd = 'boot some-server --image 1 --file /foo=%s' % invalid_file
        self.assertRaises(exceptions.CommandError, self.run_command, cmd)

    def test_boot_key_auto(self):
        mock_exists = mock.Mock(return_value=True)
        mock_open = mock.Mock()
        mock_open.return_value = mock.Mock()
        mock_open.return_value.read = mock.Mock(return_value='SSHKEY')

        @mock.patch('os.path.exists', mock_exists)
        @mock.patch('__builtin__.open', mock_open)
        def test_shell_call():
            self.run_command(
                'boot some-server --flavor 1 --image 1 --key_path')
            self.assert_called_anytime(
                'POST',
                '/servers',
                {
                    'server': {
                        'flavorRef':
                        '1',
                        'name':
                        'some-server',
                        'imageRef':
                        '1',
                        'min_count':
                        1,
                        'max_count':
                        1,
                        'personality': [
                            {
                                'path': '/root/.ssh/authorized_keys2',
                                'contents': ('SSHKEY').encode('base64')
                            },
                        ]
                    },
                },
            )

        test_shell_call()

    def test_boot_key_auto_no_keys(self):
        mock_exists = mock.Mock(return_value=False)

        @mock.patch('os.path.exists', mock_exists)
        def test_shell_call():
            self.assertRaises(
                exceptions.CommandError, self.run_command,
                'boot some-server --flavor 1 --image 1 --key_path')

        test_shell_call()

    def test_boot_key_file(self):
        testfile = os.path.join(os.path.dirname(__file__), 'testfile.txt')
        expected_file_data = open(testfile).read().encode('base64')
        cmd = 'boot some-server --flavor 1 --image 1 --key_path %s'
        self.run_command(cmd % testfile)
        self.assert_called_anytime(
            'POST',
            '/servers',
            {
                'server': {
                    'flavorRef':
                    '1',
                    'name':
                    'some-server',
                    'imageRef':
                    '1',
                    'min_count':
                    1,
                    'max_count':
                    1,
                    'personality': [
                        {
                            'path': '/root/.ssh/authorized_keys2',
                            'contents': expected_file_data
                        },
                    ]
                },
            },
        )

    def test_boot_invalid_keyfile(self):
        invalid_file = os.path.join(os.path.dirname(__file__),
                                    'asdfasdfasdfasdf')
        cmd = 'boot some-server --flavor 1 --image 1 --key_path %s'
        self.assertRaises(exceptions.CommandError, self.run_command,
                          cmd % invalid_file)

    def test_flavor_list(self):
        self.run_command('flavor-list')
        self.assert_called_anytime('GET', '/flavors/detail')

    def test_image_show(self):
        self.run_command('image-show 1')
        self.assert_called('GET', '/images/1')

    def test_image_meta_set(self):
        self.run_command('image-meta 1 set test_key=test_value')
        self.assert_called('POST', '/images/1/metadata',
                           {'metadata': {
                               'test_key': 'test_value'
                           }})

    def test_image_meta_del(self):
        self.run_command('image-meta 1 delete test_key=test_value')
        self.assert_called('DELETE', '/images/1/metadata/test_key')

    def test_image_meta_bad_action(self):
        tmp = tempfile.TemporaryFile()

        # Suppress stdout and stderr
        (stdout, stderr) = (sys.stdout, sys.stderr)
        (sys.stdout, sys.stderr) = (tmp, tmp)

        self.assertRaises(SystemExit, self.run_command,
                          'image-meta 1 BAD_ACTION test_key=test_value')

        # Put stdout and stderr back
        sys.stdout, sys.stderr = (stdout, stderr)

    def test_image_list(self):
        self.run_command('image-list')
        self.assert_called('GET', '/images/detail')

    def test_create_image(self):
        self.run_command('image-create sample-server mysnapshot')
        self.assert_called(
            'POST',
            '/servers/1234/action',
            {'createImage': {
                'name': 'mysnapshot',
                'metadata': {}
            }},
        )

    def test_image_delete(self):
        self.run_command('image-delete 1')
        self.assert_called('DELETE', '/images/1')

    def test_list(self):
        self.run_command('list')
        self.assert_called('GET', '/servers/detail')

    def test_reboot(self):
        self.run_command('reboot sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {
                               'type': 'SOFT'
                           }})
        self.run_command('reboot sample-server --hard')
        self.assert_called('POST', '/servers/1234/action',
                           {'reboot': {
                               'type': 'HARD'
                           }})

    def test_rebuild(self):
        self.run_command('rebuild sample-server 1')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1}})
        self.assert_called('GET', '/images/2')

        self.run_command('rebuild sample-server 1 --rebuild_password asdf')
        # XXX need a way to test multiple calls
        #self.assert_called('POST', '/servers/1234/action',
        #                   {'rebuild': {'imageRef': 1, 'adminPass': '******'}})
        self.assert_called('GET', '/images/2')

    def test_rename(self):
        self.run_command('rename sample-server newname')
        self.assert_called('PUT', '/servers/1234',
                           {'server': {
                               'name': 'newname'
                           }})

    def test_resize(self):
        self.run_command('resize sample-server 1')
        self.assert_called('POST', '/servers/1234/action',
                           {'resize': {
                               'flavorRef': 1
                           }})

    def test_resize_confirm(self):
        self.run_command('resize-confirm sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'confirmResize': None})

    def test_resize_revert(self):
        self.run_command('resize-revert sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'revertResize': None})

    @mock.patch('getpass.getpass', mock.Mock(return_value='p'))
    def test_root_password(self):
        self.run_command('root-password sample-server')
        self.assert_called('POST', '/servers/1234/action',
                           {'changePassword': {
                               'adminPass': '******'
                           }})

    def test_show(self):
        self.run_command('show 1234')
        self.assert_called('GET', '/servers/1234', pos=-3)
        self.assert_called('GET', '/flavors/1', pos=-2)
        self.assert_called('GET', '/images/2')

    def test_show_bad_id(self):
        self.assertRaises(exceptions.CommandError, self.run_command,
                          'show xxx')

    def test_delete(self):
        self.run_command('delete 1234')
        self.assert_called('DELETE', '/servers/1234')
        self.run_command('delete sample-server')
        self.assert_called('DELETE', '/servers/1234')

    def test_set_meta_set(self):
        self.run_command('meta 1234 set key1=val1 key2=val2')
        self.assert_called('POST', '/servers/1234/metadata',
                           {'metadata': {
                               'key1': 'val1',
                               'key2': 'val2'
                           }})

    def test_set_meta_delete_dict(self):
        self.run_command('meta 1234 delete key1=val1 key2=val2')
        self.assert_called('DELETE', '/servers/1234/metadata/key1')
        self.assert_called('DELETE', '/servers/1234/metadata/key2', pos=-2)

    def test_set_meta_delete_keys(self):
        self.run_command('meta 1234 delete key1 key2')
        self.assert_called('DELETE', '/servers/1234/metadata/key1')
        self.assert_called('DELETE', '/servers/1234/metadata/key2', pos=-2)