~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/tests/test_compute.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Chuck Short, Adam Gandleman
  • Date: 2012-01-13 09:51:10 UTC
  • mfrom: (1.1.40)
  • Revision ID: package-import@ubuntu.com-20120113095110-ffd6163drcg77wez
Tags: 2012.1~e3~20120113.12049-0ubuntu1
[Chuck Short]
* New upstream version.
* debian/nova_sudoers, debian/nova-common.install, 
  Switch out to nova-rootwrap. (LP: #681774)
* Add "get-origsource-git" which allows developers to 
  generate a tarball from github, by doing:
  fakeroot debian/rules get-orig-source-git
* debian/debian/nova-objectstore.logrotate: Dont determine
  if we are running Debian or Ubuntu. (LP: #91379)

[Adam Gandleman]
* Removed python-nova.postinst, let dh_python2 generate instead since
  python-support is not a dependency. (LP: #907543)

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
Tests For Compute
21
21
"""
22
22
from copy import copy
 
23
import datetime
 
24
import time
23
25
from webob import exc
24
26
 
25
27
import mox
 
28
import webob.exc
26
29
 
27
30
import nova
 
31
import nova.common.policy
28
32
from nova import compute
 
33
import nova.compute.api
29
34
from nova.compute import instance_types
30
35
from nova.compute import manager as compute_manager
31
36
from nova.compute import power_state
39
44
from nova import log as logging
40
45
from nova.network.quantum import client as quantum_client
41
46
from nova.notifier import test_notifier
 
47
import nova.policy
 
48
from nova import rpc
42
49
from nova.scheduler import driver as scheduler_driver
43
 
from nova import rpc
44
50
from nova import test
45
51
from nova.tests import fake_network
46
52
from nova import utils
108
114
        self.compute = utils.import_object(FLAGS.compute_manager)
109
115
        self.user_id = 'fake'
110
116
        self.project_id = 'fake'
111
 
        self.context = context.RequestContext(self.user_id, self.project_id)
 
117
        self.context = context.RequestContext(self.user_id,
 
118
                                              self.project_id)
112
119
        test_notifier.NOTIFICATIONS = []
113
120
        self.mox = mox.Mox()
114
121
        self.total_waits = 0
177
184
 
178
185
class ComputeTestCase(BaseTestCase):
179
186
 
 
187
    def test_wrap_instance_fault(self):
 
188
        inst_uuid = "fake_uuid"
 
189
 
 
190
        called = {'fault_added': False}
 
191
 
 
192
        def did_it_add_fault(_ctxt, _inst_uuid, _e):
 
193
            called['fault_added'] = True
 
194
 
 
195
        self.stubs.Set(self.compute, 'add_instance_fault_from_exc',
 
196
                       did_it_add_fault)
 
197
 
 
198
        @nova.compute.manager.wrap_instance_fault
 
199
        def failer(self2, context, instance_uuid):
 
200
            raise NotImplementedError()
 
201
 
 
202
        self.assertRaises(NotImplementedError, failer,
 
203
                          self.compute, self.context, inst_uuid)
 
204
 
 
205
        self.assertTrue(called['fault_added'])
 
206
 
 
207
    def test_wrap_instance_fault_no_instance(self):
 
208
        inst_uuid = "fake_uuid"
 
209
 
 
210
        called = {'fault_added': False}
 
211
 
 
212
        def did_it_add_fault(_ctxt, _inst_uuid, _e):
 
213
            called['fault_added'] = True
 
214
 
 
215
        self.stubs.Set(self.compute, 'add_instance_fault_from_exc',
 
216
                       did_it_add_fault)
 
217
 
 
218
        @nova.compute.manager.wrap_instance_fault
 
219
        def failer(self2, context, instance_uuid):
 
220
            raise exception.InstanceNotFound()
 
221
 
 
222
        self.assertRaises(exception.InstanceNotFound, failer,
 
223
                          self.compute, self.context, inst_uuid)
 
224
 
 
225
        self.assertFalse(called['fault_added'])
 
226
 
180
227
    def test_create_instance_with_img_ref_associates_config_drive(self):
181
228
        """Make sure create associates a config drive."""
182
229
 
473
520
 
474
521
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
475
522
 
 
523
    def test_set_admin_password_driver_error(self):
 
524
        """Ensure error is raised admin password set"""
 
525
 
 
526
        def fake_sleep(_time):
 
527
            pass
 
528
 
 
529
        self.stubs.Set(time, 'sleep', fake_sleep)
 
530
 
 
531
        def fake_driver_set_pass(self2, _instance, _pwd):
 
532
            raise exception.NotAuthorized(_('Internal error'))
 
533
 
 
534
        self.stubs.Set(nova.virt.fake.FakeConnection, 'set_admin_password',
 
535
                       fake_driver_set_pass)
 
536
 
 
537
        instance = self._create_fake_instance()
 
538
        instance_uuid = instance['uuid']
 
539
        self.compute.run_instance(self.context, instance_uuid)
 
540
        db.instance_update(self.context, instance_uuid,
 
541
                           {'task_state': task_states.UPDATING_PASSWORD})
 
542
 
 
543
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
 
544
        self.assertEqual(inst_ref['vm_state'], vm_states.ACTIVE)
 
545
        self.assertEqual(inst_ref['task_state'], task_states.UPDATING_PASSWORD)
 
546
 
 
547
        #error raised from the driver should not reveal internal information
 
548
        #so a new error is raised
 
549
        self.assertRaises(exception.Error,
 
550
                          self.compute.set_admin_password,
 
551
                          self.context, instance_uuid)
 
552
 
 
553
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
 
554
        self.assertEqual(inst_ref['vm_state'], vm_states.ERROR)
 
555
        self.assertEqual(inst_ref['task_state'], None)
 
556
 
 
557
        self.compute.terminate_instance(self.context, inst_ref['uuid'])
 
558
 
476
559
    def test_inject_file(self):
477
560
        """Ensure we can write a file to an instance"""
478
561
        called = {'inject': False}
587
670
        instance = self._create_fake_instance()
588
671
        self.compute.run_instance(self.context, instance['uuid'])
589
672
 
590
 
        console = self.compute.get_console_output(self.context,
 
673
        output = self.compute.get_console_output(self.context,
591
674
                                                  instance['uuid'])
592
 
        self.assert_(console)
 
675
        self.assertEqual(output, 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE')
 
676
        self.compute.terminate_instance(self.context, instance['uuid'])
 
677
 
 
678
    def test_console_output_tail(self):
 
679
        """Make sure we can get console output from instance"""
 
680
        instance = self._create_fake_instance()
 
681
        self.compute.run_instance(self.context, instance['uuid'])
 
682
 
 
683
        output = self.compute.get_console_output(self.context,
 
684
                                                instance['uuid'],
 
685
                                                tail_length=2)
 
686
        self.assertEqual(output, 'ANOTHER\nLAST LINE')
593
687
        self.compute.terminate_instance(self.context, instance['uuid'])
594
688
 
595
689
    def test_ajax_console(self):
786
880
        instance_uuid = instance['uuid']
787
881
        self.compute.run_instance(self.context, instance_uuid)
788
882
 
789
 
        non_admin_context = context.RequestContext(None, None, is_admin=False)
 
883
        non_admin_context = context.RequestContext(None,
 
884
                                                   None,
 
885
                                                   is_admin=False)
790
886
 
791
887
        # decorator should return False (fail) with locked nonadmin context
792
888
        self.compute.lock_instance(self.context, instance_uuid)
883
979
        self.assertEquals(payload['image_ref_url'], image_ref_url)
884
980
        self.compute.terminate_instance(context, instance_uuid)
885
981
 
 
982
    def test_prep_resize_instance_migration_error(self):
 
983
        """Ensure prep_resize raise a migration error"""
 
984
        self.flags(host="foo", allow_resize_to_same_host=False)
 
985
 
 
986
        instance = self._create_fake_instance()
 
987
        instance_uuid = instance['uuid']
 
988
        context = self.context.elevated()
 
989
 
 
990
        self.compute.run_instance(self.context, instance_uuid)
 
991
        db.instance_update(self.context, instance_uuid, {'host': 'foo'})
 
992
 
 
993
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
 
994
                          context, instance_uuid, 1)
 
995
        self.compute.terminate_instance(context, instance_uuid)
 
996
 
 
997
    def test_resize_instance_driver_error(self):
 
998
        """Ensure instance status set to Error on resize error"""
 
999
 
 
1000
        def throw_up(*args, **kwargs):
 
1001
            raise Exception()
 
1002
 
 
1003
        self.stubs.Set(self.compute.driver, 'migrate_disk_and_power_off',
 
1004
                       throw_up)
 
1005
 
 
1006
        instance = self._create_fake_instance()
 
1007
        instance_uuid = instance['uuid']
 
1008
        context = self.context.elevated()
 
1009
 
 
1010
        self.compute.run_instance(self.context, instance_uuid)
 
1011
        db.instance_update(self.context, instance_uuid, {'host': 'foo'})
 
1012
        self.compute.prep_resize(context, instance_uuid, 1)
 
1013
        migration_ref = db.migration_get_by_instance_and_status(context,
 
1014
                instance_uuid, 'pre-migrating')
 
1015
 
 
1016
        #verify
 
1017
        self.assertRaises(Exception, self.compute.resize_instance, context,
 
1018
                          instance_uuid, migration_ref['id'])
 
1019
        instance = db.instance_get_by_uuid(context, instance_uuid)
 
1020
        self.assertEqual(instance['vm_state'], vm_states.ERROR)
 
1021
 
 
1022
        self.compute.terminate_instance(context, instance_uuid)
 
1023
 
886
1024
    def test_resize_instance(self):
887
1025
        """Ensure instance can be migrated/resized"""
888
1026
        instance = self._create_fake_instance()
964
1102
        instance = self._create_fake_instance()
965
1103
        self.compute.run_instance(self.context, instance['uuid'])
966
1104
        instance = db.instance_get_by_uuid(self.context, instance['uuid'])
967
 
        self.assertRaises(exception.Error, self.compute.prep_resize,
 
1105
        self.assertRaises(exception.MigrationError, self.compute.prep_resize,
968
1106
                self.context, instance['uuid'], 1)
969
1107
        self.compute.terminate_instance(self.context, instance['uuid'])
970
1108
 
1007
1145
                          self.compute.pre_live_migration,
1008
1146
                          c, inst_ref['id'], time=FakeTime())
1009
1147
        # cleanup
1010
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1148
        db.instance_destroy(c, inst_ref['id'])
1011
1149
 
1012
1150
    def test_pre_live_migration_works_correctly(self):
1013
1151
        """Confirm setup_compute_volume is called when volume is mounted."""
1036
1174
        self.assertEqual(ret, None)
1037
1175
 
1038
1176
        # cleanup
1039
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1177
        db.instance_destroy(c, inst_ref['id'])
1040
1178
 
1041
1179
    def test_live_migration_dest_raises_exception(self):
1042
1180
        """Confirm exception when pre_live_migration fails."""
1056
1194
        self.mox.StubOutWithMock(rpc, 'call')
1057
1195
        rpc.call(c, FLAGS.volume_topic, {"method": "check_for_export",
1058
1196
                                         "args": {'instance_id': instance_id}})
 
1197
 
 
1198
        self.mox.StubOutWithMock(self.compute.driver, 'get_instance_disk_info')
 
1199
        self.compute.driver.get_instance_disk_info(inst_ref.name)
 
1200
 
1059
1201
        rpc.call(c, topic, {"method": "pre_live_migration",
1060
1202
                            "args": {'instance_id': instance_id,
1061
1203
                                     'block_migration': True,
1079
1221
                                                                instance_id):
1080
1222
            db.block_device_mapping_destroy(c, bdms['id'])
1081
1223
        db.volume_destroy(c, volume_id)
1082
 
        db.instance_destroy(c, inst_ref['uuid'])
 
1224
        db.instance_destroy(c, inst_ref['id'])
1083
1225
 
1084
1226
    def test_live_migration_works_correctly(self):
1085
1227
        """Confirm live_migration() works as expected correctly."""
1182
1324
 
1183
1325
        def fake_db_fault_create(ctxt, values):
1184
1326
            expected = {
1185
 
                'code': 404,
1186
 
                'message': 'HTTPNotFound',
1187
 
                'details': 'Error Details',
1188
 
                'instance_uuid': instance_uuid,
1189
 
            }
1190
 
            self.assertEquals(expected, values)
1191
 
 
1192
 
        self.stubs.Set(nova.db, 'instance_fault_create', fake_db_fault_create)
1193
 
 
1194
 
        ctxt = context.get_admin_context()
1195
 
        self.compute.add_instance_fault(ctxt, instance_uuid, 404,
1196
 
                                        'HTTPNotFound', 'Error Details')
1197
 
 
1198
 
    def test_add_instance_fault_error(self):
1199
 
        instance_uuid = str(utils.gen_uuid())
1200
 
 
1201
 
        def fake_db_fault_create(ctxt, values):
1202
 
            expected = {
1203
1327
                'code': 500,
1204
1328
                'message': 'NotImplementedError',
1205
1329
                'details': '',
1242
1366
            'properties': {'kernel_id': 1, 'ramdisk_id': 1},
1243
1367
        }
1244
1368
 
 
1369
    def _run_instance(self):
 
1370
        instance = self._create_fake_instance()
 
1371
        instance_uuid = instance['uuid']
 
1372
        self.compute.run_instance(self.context, instance_uuid)
 
1373
 
 
1374
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1375
        self.assertEqual(instance['task_state'], None)
 
1376
        return instance, instance_uuid
 
1377
 
1245
1378
    def test_create_with_too_little_ram(self):
1246
1379
        """Test an instance type with too little memory"""
1247
1380
 
1421
1554
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1422
1555
        self.assertEqual(instance['task_state'], task_states.STARTING)
1423
1556
 
1424
 
        db.instance_destroy(self.context, instance_uuid)
 
1557
        db.instance_destroy(self.context, instance['id'])
1425
1558
 
1426
1559
    def test_stop(self):
1427
1560
        instance = self._create_fake_instance()
1436
1569
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1437
1570
        self.assertEqual(instance['task_state'], task_states.STOPPING)
1438
1571
 
1439
 
        db.instance_destroy(self.context, instance_uuid)
 
1572
        db.instance_destroy(self.context, instance['id'])
 
1573
 
 
1574
    def test_start_shutdown(self):
 
1575
        def check_state(instance_uuid, power_state_, vm_state_, task_state_):
 
1576
            instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1577
            self.assertEqual(instance['power_state'], power_state_)
 
1578
            self.assertEqual(instance['vm_state'], vm_state_)
 
1579
            self.assertEqual(instance['task_state'], task_state_)
 
1580
 
 
1581
        def start_check_state(instance_uuid,
 
1582
                              power_state_, vm_state_, task_state_):
 
1583
            instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1584
            self.compute_api.start(self.context, instance)
 
1585
            check_state(instance_uuid, power_state_, vm_state_, task_state_)
 
1586
 
 
1587
        instance = self._create_fake_instance()
 
1588
        instance_uuid = instance['uuid']
 
1589
        self.compute.run_instance(self.context, instance_uuid)
 
1590
 
 
1591
        check_state(instance_uuid, power_state.RUNNING, vm_states.ACTIVE, None)
 
1592
 
 
1593
        # NOTE(yamahata): emulate compute.manager._sync_power_state() that
 
1594
        # the instance is shutdown by itself
 
1595
        db.instance_update(self.context, instance_uuid,
 
1596
                           {'power_state': power_state.NOSTATE,
 
1597
                            'vm_state': vm_states.SHUTOFF})
 
1598
        check_state(instance_uuid, power_state.NOSTATE, vm_states.SHUTOFF,
 
1599
                    None)
 
1600
 
 
1601
        start_check_state(instance_uuid,
 
1602
                          power_state.NOSTATE, vm_states.SHUTOFF, None)
 
1603
 
 
1604
        db.instance_update(self.context, instance_uuid,
 
1605
                           {'shutdown_terminate': False})
 
1606
        start_check_state(instance_uuid, power_state.NOSTATE,
 
1607
                          vm_states.STOPPED, task_states.STARTING)
 
1608
 
 
1609
        db.instance_destroy(self.context, instance['id'])
1440
1610
 
1441
1611
    def test_delete(self):
1442
 
        instance = self._create_fake_instance()
1443
 
        instance_uuid = instance['uuid']
1444
 
        self.compute.run_instance(self.context, instance_uuid)
 
1612
        instance, instance_uuid = self._run_instance()
 
1613
 
 
1614
        self.compute_api.delete(self.context, instance)
 
1615
 
 
1616
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1617
        self.assertEqual(instance['task_state'], task_states.DELETING)
 
1618
 
 
1619
        db.instance_destroy(self.context, instance['id'])
 
1620
 
 
1621
    def test_delete_fail(self):
 
1622
        instance, instance_uuid = self._run_instance()
 
1623
 
 
1624
        instance = db.instance_update(self.context, instance_uuid,
 
1625
                                      {'disable_terminate': True})
 
1626
        self.compute_api.delete(self.context, instance)
1445
1627
 
1446
1628
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1447
1629
        self.assertEqual(instance['task_state'], None)
1448
1630
 
1449
 
        self.compute_api.delete(self.context, instance)
1450
 
 
1451
 
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1452
 
        self.assertEqual(instance['task_state'], task_states.DELETING)
1453
 
 
1454
 
        db.instance_destroy(self.context, instance_uuid)
 
1631
        db.instance_destroy(self.context, instance['id'])
1455
1632
 
1456
1633
    def test_delete_soft(self):
1457
 
        instance = self._create_fake_instance()
1458
 
        instance_uuid = instance['uuid']
1459
 
        self.compute.run_instance(self.context, instance['uuid'])
 
1634
        instance, instance_uuid = self._run_instance()
 
1635
 
 
1636
        self.compute_api.soft_delete(self.context, instance)
 
1637
 
 
1638
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
 
1639
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
 
1640
 
 
1641
        db.instance_destroy(self.context, instance['id'])
 
1642
 
 
1643
    def test_delete_soft_fail(self):
 
1644
        instance, instance_uuid = self._run_instance()
 
1645
 
 
1646
        instance = db.instance_update(self.context, instance_uuid,
 
1647
                                      {'disable_terminate': True})
 
1648
        self.compute_api.soft_delete(self.context, instance)
1460
1649
 
1461
1650
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1462
1651
        self.assertEqual(instance['task_state'], None)
1463
1652
 
1464
 
        self.compute_api.soft_delete(self.context, instance)
1465
 
 
1466
 
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1467
 
        self.assertEqual(instance['task_state'], task_states.POWERING_OFF)
1468
 
 
1469
 
        db.instance_destroy(self.context, instance_uuid)
 
1653
        db.instance_destroy(self.context, instance['id'])
1470
1654
 
1471
1655
    def test_force_delete(self):
1472
1656
        """Ensure instance can be deleted after a soft delete"""
1498
1682
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1499
1683
        self.assertEqual(instance['task_state'], task_states.SUSPENDING)
1500
1684
 
1501
 
        db.instance_destroy(self.context, instance_uuid)
 
1685
        db.instance_destroy(self.context, instance['id'])
1502
1686
 
1503
1687
    def test_resume(self):
1504
1688
        """Ensure instance can be resumed (if suspended)"""
1505
1689
        instance = self._create_fake_instance()
1506
1690
        instance_uuid = instance['uuid']
1507
1691
        instance_id = instance['id']
1508
 
        self.compute.run_instance(self.context, instance_uuid )
 
1692
        self.compute.run_instance(self.context, instance_uuid)
1509
1693
        db.instance_update(self.context, instance_id,
1510
1694
                           {'vm_state': vm_states.SUSPENDED})
1511
1695
        instance = db.instance_get(self.context, instance_id)
1517
1701
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1518
1702
        self.assertEqual(instance['task_state'], task_states.RESUMING)
1519
1703
 
1520
 
        db.instance_destroy(self.context, instance_uuid)
 
1704
        db.instance_destroy(self.context, instance['id'])
1521
1705
 
1522
1706
    def test_pause(self):
1523
1707
        """Ensure instance can be paused"""
1532
1716
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1533
1717
        self.assertEqual(instance['task_state'], task_states.PAUSING)
1534
1718
 
1535
 
        db.instance_destroy(self.context, instance_uuid)
 
1719
        db.instance_destroy(self.context, instance['id'])
1536
1720
 
1537
1721
    def test_unpause(self):
1538
1722
        """Ensure instance can be unpaused"""
1553
1737
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1554
1738
        self.assertEqual(instance['task_state'], task_states.UNPAUSING)
1555
1739
 
1556
 
        db.instance_destroy(self.context, instance_uuid)
 
1740
        db.instance_destroy(self.context, instance['id'])
1557
1741
 
1558
1742
    def test_restore(self):
1559
1743
        """Ensure instance can be restored from a soft delete"""
1572
1756
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1573
1757
        self.assertEqual(instance['task_state'], task_states.POWERING_ON)
1574
1758
 
1575
 
        db.instance_destroy(self.context, instance_uuid)
 
1759
        db.instance_destroy(self.context, instance['id'])
1576
1760
 
1577
1761
    def test_rebuild(self):
1578
1762
        inst_ref = self._create_fake_instance()
1587
1771
        self.compute_api.rebuild(self.context, instance, image_ref, password)
1588
1772
 
1589
1773
        instance = db.instance_get_by_uuid(self.context, instance_uuid)
1590
 
        self.assertEqual(instance['task_state'], task_states.REBUILDING)
 
1774
        self.assertEqual(instance['vm_state'], vm_states.REBUILDING)
1591
1775
 
1592
 
        db.instance_destroy(self.context, instance_uuid)
 
1776
        db.instance_destroy(self.context, instance['id'])
1593
1777
 
1594
1778
    def test_reboot_soft(self):
1595
1779
        """Ensure instance can be soft rebooted"""
1606
1790
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
1607
1791
        self.assertEqual(inst_ref['task_state'], task_states.REBOOTING)
1608
1792
 
1609
 
        db.instance_destroy(self.context, instance_uuid)
 
1793
        db.instance_destroy(self.context, inst_ref['id'])
1610
1794
 
1611
1795
    def test_reboot_hard(self):
1612
1796
        """Ensure instance can be hard rebooted"""
1623
1807
        inst_ref = db.instance_get_by_uuid(self.context, instance_uuid)
1624
1808
        self.assertEqual(inst_ref['task_state'], task_states.REBOOTING_HARD)
1625
1809
 
1626
 
        db.instance_destroy(self.context, instance_uuid)
 
1810
        db.instance_destroy(self.context, inst_ref['id'])
1627
1811
 
1628
1812
    def test_hostname_create(self):
1629
1813
        """Ensure instance hostname is set during creation."""
1681
1865
        self.compute.terminate_instance(self.context, instance_uuid)
1682
1866
 
1683
1867
    def test_snapshot(self):
1684
 
        """Can't backup an instance which is already being backed up."""
1685
 
        instance = self._create_fake_instance()
1686
 
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
1687
 
                                        {'extra_param': 'value1'})
1688
 
 
1689
 
        self.assertEqual(image['name'], 'snap1')
 
1868
        """Ensure a snapshot of an instance can be created"""
 
1869
        instance = self._create_fake_instance()
 
1870
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
1871
                                        {'extra_param': 'value1'})
 
1872
 
 
1873
        self.assertEqual(image['name'], 'snap1')
 
1874
        properties = image['properties']
 
1875
        self.assertTrue('backup_type' not in properties)
 
1876
        self.assertEqual(properties['image_type'], 'snapshot')
 
1877
        self.assertEqual(properties['instance_uuid'], instance['uuid'])
 
1878
        self.assertEqual(properties['extra_param'], 'value1')
 
1879
 
 
1880
        db.instance_destroy(self.context, instance['id'])
 
1881
 
 
1882
    def test_snapshot_minram_mindisk_VHD(self):
 
1883
        """Ensure a snapshots min_ram and min_disk are correct.
 
1884
 
 
1885
        A snapshot of a non-shrinkable VHD should have min_ram
 
1886
        and min_disk set to that of the original instances flavor.
 
1887
        """
 
1888
 
 
1889
        def fake_show(*args):
 
1890
            img = copy(self.fake_image)
 
1891
            img['disk_format'] = 'vhd'
 
1892
            return img
 
1893
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
1894
 
 
1895
        instance = self._create_fake_instance()
 
1896
        inst_params = {'local_gb': 2, 'memory_mb': 256}
 
1897
        instance['instance_type'].update(inst_params)
 
1898
 
 
1899
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
1900
                                        {'extra_param': 'value1'})
 
1901
 
 
1902
        self.assertEqual(image['name'], 'snap1')
 
1903
        self.assertEqual(image['min_ram'], 256)
 
1904
        self.assertEqual(image['min_disk'], 2)
 
1905
        properties = image['properties']
 
1906
        self.assertTrue('backup_type' not in properties)
 
1907
        self.assertEqual(properties['image_type'], 'snapshot')
 
1908
        self.assertEqual(properties['instance_uuid'], instance['uuid'])
 
1909
        self.assertEqual(properties['extra_param'], 'value1')
 
1910
 
 
1911
        db.instance_destroy(self.context, instance['id'])
 
1912
 
 
1913
    def test_snapshot_minram_mindisk(self):
 
1914
        """Ensure a snapshots min_ram and min_disk are correct.
 
1915
 
 
1916
        A snapshot of an instance should have min_ram and min_disk
 
1917
        set to that of the instances original image unless that
 
1918
        image had a disk format of vhd.
 
1919
        """
 
1920
 
 
1921
        def fake_show(*args):
 
1922
            img = copy(self.fake_image)
 
1923
            img['disk_format'] = 'raw'
 
1924
            img['min_ram'] = 512
 
1925
            img['min_disk'] = 1
 
1926
            return img
 
1927
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
1928
 
 
1929
        instance = self._create_fake_instance()
 
1930
 
 
1931
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
1932
                                        {'extra_param': 'value1'})
 
1933
 
 
1934
        self.assertEqual(image['name'], 'snap1')
 
1935
        self.assertEqual(image['min_ram'], 512)
 
1936
        self.assertEqual(image['min_disk'], 1)
 
1937
        properties = image['properties']
 
1938
        self.assertTrue('backup_type' not in properties)
 
1939
        self.assertEqual(properties['image_type'], 'snapshot')
 
1940
        self.assertEqual(properties['instance_uuid'], instance['uuid'])
 
1941
        self.assertEqual(properties['extra_param'], 'value1')
 
1942
 
 
1943
        db.instance_destroy(self.context, instance['id'])
 
1944
 
 
1945
    def test_snapshot_minram_mindisk_img_missing_minram(self):
 
1946
        """Ensure a snapshots min_ram and min_disk are correct.
 
1947
 
 
1948
        Do not show an attribute that the orig img did not have.
 
1949
        """
 
1950
 
 
1951
        def fake_show(*args):
 
1952
            img = copy(self.fake_image)
 
1953
            img['disk_format'] = 'raw'
 
1954
            img['min_disk'] = 1
 
1955
            return img
 
1956
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
1957
 
 
1958
        instance = self._create_fake_instance()
 
1959
 
 
1960
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
1961
                                        {'extra_param': 'value1'})
 
1962
 
 
1963
        self.assertEqual(image['name'], 'snap1')
 
1964
        self.assertFalse('min_ram' in image)
 
1965
        self.assertEqual(image['min_disk'], 1)
 
1966
        properties = image['properties']
 
1967
        self.assertTrue('backup_type' not in properties)
 
1968
        self.assertEqual(properties['image_type'], 'snapshot')
 
1969
        self.assertEqual(properties['instance_uuid'], instance['uuid'])
 
1970
        self.assertEqual(properties['extra_param'], 'value1')
 
1971
 
 
1972
        db.instance_destroy(self.context, instance['id'])
 
1973
 
 
1974
    def test_snapshot_minram_mindisk_no_image(self):
 
1975
        """Ensure a snapshots min_ram and min_disk are correct.
 
1976
 
 
1977
        A snapshots min_ram and min_disk should be set to default if
 
1978
        an instances original image cannot be found.
 
1979
        """
 
1980
 
 
1981
        def fake_show(*args):
 
1982
            raise webob.exc.HTTPNotFound()
 
1983
 
 
1984
        self.stubs.Set(fake_image._FakeImageService, 'show', fake_show)
 
1985
 
 
1986
        instance = self._create_fake_instance()
 
1987
 
 
1988
        image = self.compute_api.snapshot(self.context, instance, 'snap1',
 
1989
                                        {'extra_param': 'value1'})
 
1990
 
 
1991
        self.assertEqual(image['name'], 'snap1')
 
1992
 
 
1993
        # min_ram and min_disk are not returned when set to default
 
1994
        self.assertFalse('min_ram' in image)
 
1995
        self.assertFalse('min_disk' in image)
 
1996
 
1690
1997
        properties = image['properties']
1691
1998
        self.assertTrue('backup_type' not in properties)
1692
1999
        self.assertEqual(properties['image_type'], 'snapshot')
1727
2034
                          None,
1728
2035
                          None)
1729
2036
 
1730
 
        db.instance_destroy(self.context, instance_uuid)
 
2037
        db.instance_destroy(self.context, instance['id'])
1731
2038
 
1732
2039
    def test_snapshot_conflict(self):
1733
2040
        """Can't snapshot an instance which is already being snapshotted."""
1743
2050
                          instance,
1744
2051
                          None)
1745
2052
 
1746
 
        db.instance_destroy(self.context, instance_uuid)
 
2053
        db.instance_destroy(self.context, instance['id'])
1747
2054
 
1748
2055
    def test_resize_confirm_through_api(self):
1749
2056
        instance = self._create_fake_instance()
1823
2130
    def test_resize_request_spec(self):
1824
2131
        def _fake_cast(context, args):
1825
2132
            request_spec = args['args']['request_spec']
1826
 
            self.assertEqual(request_spec['original_host'], 'host2')
 
2133
            instance_properties = request_spec['instance_properties']
 
2134
            self.assertEqual(instance_properties['host'], 'host2')
1827
2135
            self.assertEqual(request_spec['avoid_original_host'], True)
1828
2136
 
1829
2137
        self.stubs.Set(self.compute_api, '_cast_scheduler_message',
1841
2149
    def test_resize_request_spec_noavoid(self):
1842
2150
        def _fake_cast(context, args):
1843
2151
            request_spec = args['args']['request_spec']
1844
 
            self.assertEqual(request_spec['original_host'], 'host2')
 
2152
            instance_properties = request_spec['instance_properties']
 
2153
            self.assertEqual(instance_properties['host'], 'host2')
1845
2154
            self.assertEqual(request_spec['avoid_original_host'], False)
1846
2155
 
1847
2156
        self.stubs.Set(self.compute_api, '_cast_scheduler_message',
1867
2176
 
1868
2177
        nw_info = fake_network.fake_get_instance_nw_info(self.stubs, 1)
1869
2178
 
1870
 
        def fake_get_nw_info(self, ctxt, instance):
 
2179
        def fake_get_nw_info(cls, ctxt, instance):
 
2180
            self.assertTrue(ctxt.is_admin)
1871
2181
            return nw_info
1872
2182
 
1873
2183
        self.stubs.Set(nova.network.API, 'associate_floating_ip',
1979
2289
                search_opts={'name': 'noth.*'})
1980
2290
        self.assertEqual(len(instances), 0)
1981
2291
 
1982
 
        db.instance_destroy(c, instance1['uuid'])
1983
 
        db.instance_destroy(c, instance2['uuid'])
1984
 
        db.instance_destroy(c, instance3['uuid'])
 
2292
        db.instance_destroy(c, instance1['id'])
 
2293
        db.instance_destroy(c, instance2['id'])
 
2294
        db.instance_destroy(c, instance3['id'])
1985
2295
 
1986
2296
    def test_get_all_by_instance_name_regexp(self):
1987
2297
        """Test searching instances by name"""
2008
2318
        self.assertEqual(len(instances), 1)
2009
2319
        self.assertEqual(instances[0]['uuid'], instance2['uuid'])
2010
2320
 
2011
 
        db.instance_destroy(c, instance1['uuid'])
2012
 
        db.instance_destroy(c, instance2['uuid'])
2013
 
        db.instance_destroy(c, instance3['uuid'])
 
2321
        db.instance_destroy(c, instance1['id'])
 
2322
        db.instance_destroy(c, instance2['id'])
 
2323
        db.instance_destroy(c, instance3['id'])
2014
2324
 
2015
2325
    def test_get_all_by_multiple_options_at_once(self):
2016
2326
        """Test searching by multiple options at once"""
2061
2371
        self.assertEqual(len(instances), 1)
2062
2372
        self.assertEqual(instances[0]['uuid'], instance3['uuid'])
2063
2373
 
2064
 
        db.instance_destroy(c, instance1['uuid'])
2065
 
        db.instance_destroy(c, instance2['uuid'])
2066
 
        db.instance_destroy(c, instance3['uuid'])
 
2374
        db.instance_destroy(c, instance1['id'])
 
2375
        db.instance_destroy(c, instance2['id'])
 
2376
        db.instance_destroy(c, instance3['id'])
2067
2377
 
2068
2378
    def test_get_all_by_image(self):
2069
2379
        """Test searching instances by image"""
2091
2401
                                    search_opts={'image': ['1234', '4567']})
2092
2402
        self.assertEqual(len(instances), 3)
2093
2403
 
2094
 
        db.instance_destroy(c, instance1['uuid'])
2095
 
        db.instance_destroy(c, instance2['uuid'])
2096
 
        db.instance_destroy(c, instance3['uuid'])
 
2404
        db.instance_destroy(c, instance1['id'])
 
2405
        db.instance_destroy(c, instance2['id'])
 
2406
        db.instance_destroy(c, instance3['id'])
2097
2407
 
2098
2408
    def test_get_all_by_flavor(self):
2099
2409
        """Test searching instances by image"""
2130
2440
        self.assertTrue(instance2['uuid'] in instance_uuids)
2131
2441
        self.assertTrue(instance3['uuid'] in instance_uuids)
2132
2442
 
2133
 
        db.instance_destroy(c, instance1['uuid'])
2134
 
        db.instance_destroy(c, instance2['uuid'])
2135
 
        db.instance_destroy(c, instance3['uuid'])
 
2443
        db.instance_destroy(c, instance1['id'])
 
2444
        db.instance_destroy(c, instance2['id'])
 
2445
        db.instance_destroy(c, instance3['id'])
2136
2446
 
2137
2447
    def test_get_all_by_state(self):
2138
2448
        """Test searching instances by state"""
2170
2480
                        power_state.RUNNING]})
2171
2481
        self.assertEqual(len(instances), 3)
2172
2482
 
2173
 
        db.instance_destroy(c, instance1['uuid'])
2174
 
        db.instance_destroy(c, instance2['uuid'])
2175
 
        db.instance_destroy(c, instance3['uuid'])
 
2483
        db.instance_destroy(c, instance1['id'])
 
2484
        db.instance_destroy(c, instance2['id'])
 
2485
        db.instance_destroy(c, instance3['id'])
2176
2486
 
2177
2487
    def test_get_all_by_metadata(self):
2178
2488
        """Test searching instances by metadata"""
2231
2541
        self.assertEqual(len(instances), 1)
2232
2542
        self.assertEqual(instances[0]['uuid'], instance4['uuid'])
2233
2543
 
2234
 
        db.instance_destroy(c, instance0['uuid'])
2235
 
        db.instance_destroy(c, instance1['uuid'])
2236
 
        db.instance_destroy(c, instance2['uuid'])
2237
 
        db.instance_destroy(c, instance3['uuid'])
2238
 
        db.instance_destroy(c, instance4['uuid'])
 
2544
        db.instance_destroy(c, instance0['id'])
 
2545
        db.instance_destroy(c, instance1['id'])
 
2546
        db.instance_destroy(c, instance2['id'])
 
2547
        db.instance_destroy(c, instance3['id'])
 
2548
        db.instance_destroy(c, instance4['id'])
2239
2549
 
2240
2550
    def test_instance_metadata(self):
2241
2551
        """Test searching instances by state"""
2260
2570
        metadata = self.compute_api.get_instance_metadata(_context, instance)
2261
2571
        self.assertEqual(metadata, {'key3': 'value3'})
2262
2572
 
2263
 
        db.instance_destroy(_context, instance['uuid'])
 
2573
        db.instance_destroy(_context, instance['id'])
 
2574
 
 
2575
    def test_get_instance_faults(self):
 
2576
        """Get an instances latest fault"""
 
2577
        instance = self._create_fake_instance()
 
2578
 
 
2579
        fault_fixture = {
 
2580
                'code': 404,
 
2581
                'instance_uuid': instance['uuid'],
 
2582
                'message': "HTTPNotFound",
 
2583
                'details': "Stock details for test",
 
2584
                'created_at': datetime.datetime(2010, 10, 10, 12, 0, 0),
 
2585
            }
 
2586
 
 
2587
        def return_fault(_ctxt, instance_uuids):
 
2588
            return dict.fromkeys(instance_uuids, [fault_fixture])
 
2589
 
 
2590
        self.stubs.Set(nova.db,
 
2591
                       'instance_fault_get_by_instance_uuids',
 
2592
                       return_fault)
 
2593
 
 
2594
        _context = context.get_admin_context()
 
2595
        output = self.compute_api.get_instance_faults(_context, [instance])
 
2596
        expected = {instance['uuid']: [fault_fixture]}
 
2597
        self.assertEqual(output, expected)
 
2598
 
 
2599
        db.instance_destroy(_context, instance['id'])
2264
2600
 
2265
2601
    @staticmethod
2266
2602
    def _parse_db_block_device_mapping(bdm_ref):
2419
2755
        finally:
2420
2756
            for instance in refs:
2421
2757
                self.assertEqual(instance['reservation_id'], resv_id)
2422
 
                db.instance_destroy(self.context, instance['id'])
 
2758
 
 
2759
        db.instance_destroy(self.context, refs[0]['id'])
2423
2760
 
2424
2761
    def test_create_with_specified_reservation_id(self):
2425
2762
        """Verify building instances with a specified
2439
2776
            self.assertEqual(resv_id, 'meow')
2440
2777
        finally:
2441
2778
            self.assertEqual(refs[0]['reservation_id'], resv_id)
2442
 
            db.instance_destroy(self.context, refs[0]['id'])
2443
2779
 
2444
2780
        # 2 instances
2445
2781
        (refs, resv_id) = self.compute_api.create(context,
2451
2787
        finally:
2452
2788
            for instance in refs:
2453
2789
                self.assertEqual(instance['reservation_id'], resv_id)
2454
 
                db.instance_destroy(self.context, instance['id'])
 
2790
            db.instance_destroy(self.context, refs[0]['id'])
2455
2791
 
2456
2792
    def test_instance_name_template(self):
2457
2793
        """Test the instance_name template"""
2459
2795
        i_ref = self._create_fake_instance()
2460
2796
        instance_id = i_ref['id']
2461
2797
        self.assertEqual(i_ref['name'], 'instance-%d' % i_ref['id'])
2462
 
        db.instance_destroy(self.context, i_ref['uuid'])
 
2798
        db.instance_destroy(self.context, i_ref['id'])
2463
2799
 
2464
2800
        self.flags(instance_name_template='instance-%(uuid)s')
2465
2801
        i_ref = self._create_fake_instance()
2466
2802
        self.assertEqual(i_ref['name'], 'instance-%s' % i_ref['uuid'])
2467
 
        db.instance_destroy(self.context, i_ref['uuid'])
 
2803
        db.instance_destroy(self.context, i_ref['id'])
2468
2804
 
2469
2805
        self.flags(instance_name_template='%(id)d-%(uuid)s')
2470
2806
        i_ref = self._create_fake_instance()
2471
2807
        self.assertEqual(i_ref['name'], '%d-%s' %
2472
2808
                (i_ref['id'], i_ref['uuid']))
2473
 
        db.instance_destroy(self.context, i_ref['uuid'])
 
2809
        db.instance_destroy(self.context, i_ref['id'])
2474
2810
 
2475
2811
        # not allowed.. default is uuid
2476
2812
        self.flags(instance_name_template='%(name)s')
2477
2813
        i_ref = self._create_fake_instance()
2478
2814
        self.assertEqual(i_ref['name'], i_ref['uuid'])
2479
 
        db.instance_destroy(self.context, i_ref['uuid'])
 
2815
        db.instance_destroy(self.context, i_ref['id'])
2480
2816
 
2481
2817
    def test_add_remove_fixed_ip(self):
2482
2818
        instance = self._create_fake_instance()
2487
2823
    def test_attach_volume_invalid(self):
2488
2824
        self.assertRaises(exception.ApiError,
2489
2825
                self.compute_api.attach_volume,
2490
 
                None,
 
2826
                self.context,
2491
2827
                None,
2492
2828
                None,
2493
2829
                '/dev/invalid')
2637
2973
        instance = self._create_fake_instance()
2638
2974
        self.compute_api.inject_file(self.context, instance,
2639
2975
                                     "/tmp/test", "File Contents")
2640
 
        db.instance_destroy(self.context, instance['uuid'])
 
2976
        db.instance_destroy(self.context, instance['id'])
 
2977
 
 
2978
 
 
2979
class ComputePolicyTestCase(BaseTestCase):
 
2980
 
 
2981
    def setUp(self):
 
2982
        super(ComputePolicyTestCase, self).setUp()
 
2983
        nova.policy.reset()
 
2984
        nova.policy.init()
 
2985
 
 
2986
        self.compute_api = compute.API()
 
2987
 
 
2988
    def tearDown(self):
 
2989
        super(ComputePolicyTestCase, self).tearDown()
 
2990
        nova.policy.reset()
 
2991
 
 
2992
    def _set_rules(self, rules):
 
2993
        nova.common.policy.set_brain(nova.common.policy.HttpBrain(rules))
 
2994
 
 
2995
    def test_actions_are_prefixed(self):
 
2996
        self.mox.StubOutWithMock(nova.policy, 'enforce')
 
2997
        nova.policy.enforce(self.context, 'compute:reboot', {})
 
2998
        self.mox.ReplayAll()
 
2999
        nova.compute.api.check_policy(self.context, 'reboot', {})
 
3000
        self.mox.UnsetStubs()
 
3001
        self.mox.VerifyAll()
 
3002
 
 
3003
    def test_wrapped_method(self):
 
3004
        instance = self._create_fake_instance()
 
3005
        self.compute.run_instance(self.context, instance['uuid'])
 
3006
 
 
3007
        # force delete to fail
 
3008
        rules = {"compute:delete": [["false:false"]]}
 
3009
        self._set_rules(rules)
 
3010
 
 
3011
        self.assertRaises(exception.PolicyNotAuthorized,
 
3012
                          self.compute_api.delete, self.context, instance)
 
3013
 
 
3014
        # reset rules to allow deletion
 
3015
        rules = {"compute:delete": []}
 
3016
        self._set_rules(rules)
 
3017
 
 
3018
        self.compute_api.delete(self.context, instance)
 
3019
 
 
3020
    def test_create_fail(self):
 
3021
        rules = {"compute:create": [["false:false"]]}
 
3022
        self._set_rules(rules)
 
3023
 
 
3024
        self.assertRaises(exception.PolicyNotAuthorized,
 
3025
                          self.compute_api.create, self.context, '1', '1')
 
3026
 
 
3027
    def test_create_attach_volume_fail(self):
 
3028
        rules = {
 
3029
            "compute:create": [],
 
3030
            "compute:create:attach_network": [["false:false"]],
 
3031
            "compute:create:attach_volume": [],
 
3032
        }
 
3033
        self._set_rules(rules)
 
3034
 
 
3035
        self.assertRaises(exception.PolicyNotAuthorized,
 
3036
                          self.compute_api.create, self.context, '1', '1',
 
3037
                          requested_networks='blah',
 
3038
                          block_device_mapping='blah')
 
3039
 
 
3040
    def test_create_attach_network_fail(self):
 
3041
        rules = {
 
3042
            "compute:create": [],
 
3043
            "compute:create:attach_network": [],
 
3044
            "compute:create:attach_volume": [["false:false"]],
 
3045
        }
 
3046
        self._set_rules(rules)
 
3047
 
 
3048
        self.assertRaises(exception.PolicyNotAuthorized,
 
3049
                          self.compute_api.create, self.context, '1', '1',
 
3050
                          requested_networks='blah',
 
3051
                          block_device_mapping='blah')
 
3052
 
 
3053
    def test_get_fail(self):
 
3054
        instance = self._create_fake_instance()
 
3055
 
 
3056
        rules = {
 
3057
            "compute:get": [["false:false"]],
 
3058
        }
 
3059
        self._set_rules(rules)
 
3060
 
 
3061
        self.assertRaises(exception.PolicyNotAuthorized,
 
3062
                          self.compute_api.get, self.context, instance['uuid'])
 
3063
 
 
3064
    def test_get_all_fail(self):
 
3065
        rules = {
 
3066
            "compute:get_all": [["false:false"]],
 
3067
        }
 
3068
        self._set_rules(rules)
 
3069
 
 
3070
        self.assertRaises(exception.PolicyNotAuthorized,
 
3071
                          self.compute_api.get_all, self.context)
 
3072
 
 
3073
    def test_get_instance_faults(self):
 
3074
        instance1 = self._create_fake_instance()
 
3075
        instance2 = self._create_fake_instance()
 
3076
        instances = [instance1, instance2]
 
3077
 
 
3078
        rules = {
 
3079
            "compute:get_instance_faults": [["false:false"]],
 
3080
        }
 
3081
        self._set_rules(rules)
 
3082
 
 
3083
        self.assertRaises(exception.PolicyNotAuthorized,
 
3084
                          self.compute_api.get_instance_faults,
 
3085
                          self.context, instances)