~cloudbuilders/nova/os-keypair-integration

« back to all changes in this revision

Viewing changes to nova/tests/api/openstack/test_server_actions.py

  • Committer: Jesse Andrews
  • Date: 2011-08-26 21:57:53 UTC
  • mfrom: (1455.1.45 nova)
  • Revision ID: anotherjesse@gmail.com-20110826215753-0sfp6dubujsl23wa
merge trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import base64
 
2
import datetime
2
3
import json
3
 
import unittest
4
 
from xml.dom import minidom
5
4
 
6
5
import stubout
7
6
import webob
8
7
 
9
8
from nova import context
10
 
from nova import db
11
9
from nova import utils
 
10
from nova import exception
12
11
from nova import flags
13
12
from nova.api.openstack import create_instance_helper
14
13
from nova.compute import instance_types
23
22
 
24
23
 
25
24
def return_server_by_id(context, id):
26
 
    return _get_instance()
 
25
    return stub_instance(id)
27
26
 
28
27
 
29
28
def instance_update(context, instance_id, kwargs):
30
 
    return _get_instance()
 
29
    return stub_instance(instance_id)
 
30
 
 
31
 
 
32
def return_server_with_attributes(**kwargs):
 
33
    def _return_server(context, id):
 
34
        return stub_instance(id, **kwargs)
 
35
    return _return_server
31
36
 
32
37
 
33
38
def return_server_with_power_state(power_state):
34
 
    def _return_server(context, id):
35
 
        instance = _get_instance()
36
 
        instance['state'] = power_state
37
 
        return instance
38
 
    return _return_server
 
39
    return return_server_with_attributes(power_state=power_state)
39
40
 
40
41
 
41
42
def return_server_with_uuid_and_power_state(power_state):
42
 
    def _return_server(context, id):
43
 
        return return_server_with_power_state(power_state)
44
 
    return _return_server
45
 
 
46
 
 
47
 
class MockSetAdminPassword(object):
48
 
    def __init__(self):
49
 
        self.instance_id = None
50
 
        self.password = None
51
 
 
52
 
    def __call__(self, context, instance_id, password):
53
 
        self.instance_id = instance_id
54
 
        self.password = password
55
 
 
56
 
 
57
 
def _get_instance():
 
43
    return return_server_with_power_state(power_state)
 
44
 
 
45
 
 
46
def stub_instance(id, power_state=0, metadata=None,
 
47
                  image_ref="10", flavor_id="1", name=None):
 
48
 
 
49
    if metadata is not None:
 
50
        metadata_items = [{'key':k, 'value':v} for k, v in metadata.items()]
 
51
    else:
 
52
        metadata_items = [{'key':'seq', 'value':id}]
 
53
 
 
54
    inst_type = instance_types.get_instance_type_by_flavor_id(int(flavor_id))
 
55
 
58
56
    instance = {
59
 
        "id": 1,
60
 
        "created_at": "2010-10-10 12:00:00",
61
 
        "updated_at": "2010-11-11 11:00:00",
 
57
        "id": int(id),
 
58
        "created_at": datetime.datetime(2010, 10, 10, 12, 0, 0),
 
59
        "updated_at": datetime.datetime(2010, 11, 11, 11, 0, 0),
62
60
        "admin_pass": "",
63
 
        "user_id": "",
64
 
        "project_id": "",
65
 
        "image_ref": "5",
 
61
        "user_id": "fake",
 
62
        "project_id": "fake",
 
63
        "image_ref": image_ref,
66
64
        "kernel_id": "",
67
65
        "ramdisk_id": "",
68
66
        "launch_index": 0,
69
67
        "key_name": "",
70
68
        "key_data": "",
71
 
        "state": 0,
 
69
        "state": power_state,
72
70
        "state_description": "",
73
71
        "memory_mb": 0,
74
72
        "vcpus": 0,
75
73
        "local_gb": 0,
76
74
        "hostname": "",
77
75
        "host": "",
78
 
        "instance_type": {
79
 
           "flavorid": 1,
80
 
        },
 
76
        "instance_type": dict(inst_type),
81
77
        "user_data": "",
82
78
        "reservation_id": "",
83
79
        "mac_address": "",
85
81
        "launched_at": utils.utcnow(),
86
82
        "terminated_at": utils.utcnow(),
87
83
        "availability_zone": "",
88
 
        "display_name": "test_server",
 
84
        "display_name": name or "server%s" % id,
89
85
        "display_description": "",
90
86
        "locked": False,
91
 
        "metadata": [],
92
 
        #"address": ,
93
 
        #"floating_ips": [{"address":ip} for ip in public_addresses]}
94
 
        "uuid": "deadbeef-feed-edee-beef-d0ea7beefedd"}
 
87
        "metadata": metadata_items,
 
88
        "access_ip_v4": "",
 
89
        "access_ip_v6": "",
 
90
        "uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
 
91
        "virtual_interfaces": [],
 
92
    }
 
93
 
 
94
    instance["fixed_ips"] = {
 
95
        "address": '192.168.0.1',
 
96
        "floating_ips": [],
 
97
    }
95
98
 
96
99
    return instance
97
100
 
98
101
 
 
102
class MockSetAdminPassword(object):
 
103
    def __init__(self):
 
104
        self.instance_id = None
 
105
        self.password = None
 
106
 
 
107
    def __call__(self, context, instance_id, password):
 
108
        self.instance_id = instance_id
 
109
        self.password = password
 
110
 
 
111
 
99
112
class ServerActionsTest(test.TestCase):
100
113
 
101
114
    def setUp(self):
103
116
        super(ServerActionsTest, self).setUp()
104
117
        self.flags(verbose=True)
105
118
        self.stubs = stubout.StubOutForTesting()
106
 
        fakes.FakeAuthManager.reset_fake_data()
107
 
        fakes.FakeAuthDatabase.data = {}
108
119
        fakes.stub_out_auth(self.stubs)
109
120
        self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
110
121
        self.stubs.Set(nova.db.api, 'instance_update', instance_update)
468
479
        self.maxDiff = None
469
480
        super(ServerActionsTestV11, self).setUp()
470
481
        self.stubs = stubout.StubOutForTesting()
471
 
        fakes.FakeAuthManager.reset_fake_data()
472
 
        fakes.FakeAuthDatabase.data = {}
473
482
        fakes.stub_out_auth(self.stubs)
474
483
        self.stubs.Set(nova.db.api, 'instance_get', return_server_by_id)
475
484
        self.stubs.Set(nova.db.api, 'instance_update', instance_update)
489
498
 
490
499
    def test_server_bad_body(self):
491
500
        body = {}
492
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
501
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
493
502
        req.method = 'POST'
494
503
        req.content_type = 'application/json'
495
504
        req.body = json.dumps(body)
498
507
 
499
508
    def test_server_unknown_action(self):
500
509
        body = {'sockTheFox': {'fakekey': '1234'}}
501
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
510
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
502
511
        req.method = 'POST'
503
512
        req.content_type = 'application/json'
504
513
        req.body = json.dumps(body)
509
518
        mock_method = MockSetAdminPassword()
510
519
        self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
511
520
        body = {'changePassword': {'adminPass': '1234pass'}}
512
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
521
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
513
522
        req.method = 'POST'
514
523
        req.content_type = 'application/json'
515
524
        req.body = json.dumps(body)
521
530
    def test_server_change_password_xml(self):
522
531
        mock_method = MockSetAdminPassword()
523
532
        self.stubs.Set(nova.compute.api.API, 'set_admin_password', mock_method)
524
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
533
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
525
534
        req.method = 'POST'
526
535
        req.content_type = "application/xml"
527
536
        req.body = """<?xml version="1.0" encoding="UTF-8"?>
535
544
 
536
545
    def test_server_change_password_not_a_string(self):
537
546
        body = {'changePassword': {'adminPass': 1234}}
538
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
547
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
539
548
        req.method = 'POST'
540
549
        req.content_type = 'application/json'
541
550
        req.body = json.dumps(body)
544
553
 
545
554
    def test_server_change_password_bad_request(self):
546
555
        body = {'changePassword': {'pass': '12345'}}
547
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
556
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
548
557
        req.method = 'POST'
549
558
        req.content_type = 'application/json'
550
559
        req.body = json.dumps(body)
553
562
 
554
563
    def test_server_change_password_empty_string(self):
555
564
        body = {'changePassword': {'adminPass': ''}}
556
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
565
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
557
566
        req.method = 'POST'
558
567
        req.content_type = 'application/json'
559
568
        req.body = json.dumps(body)
562
571
 
563
572
    def test_server_change_password_none(self):
564
573
        body = {'changePassword': {'adminPass': None}}
565
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
574
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
566
575
        req.method = 'POST'
567
576
        req.content_type = 'application/json'
568
577
        req.body = json.dumps(body)
571
580
 
572
581
    def test_server_reboot_hard(self):
573
582
        body = dict(reboot=dict(type="HARD"))
574
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
583
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
575
584
        req.method = 'POST'
576
585
        req.content_type = 'application/json'
577
586
        req.body = json.dumps(body)
580
589
 
581
590
    def test_server_reboot_soft(self):
582
591
        body = dict(reboot=dict(type="SOFT"))
583
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
592
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
584
593
        req.method = 'POST'
585
594
        req.content_type = 'application/json'
586
595
        req.body = json.dumps(body)
589
598
 
590
599
    def test_server_reboot_incorrect_type(self):
591
600
        body = dict(reboot=dict(type="NOT_A_TYPE"))
592
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
601
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
593
602
        req.method = 'POST'
594
603
        req.content_type = 'application/json'
595
604
        req.body = json.dumps(body)
598
607
 
599
608
    def test_server_reboot_missing_type(self):
600
609
        body = dict(reboot=dict())
601
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
610
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
602
611
        req.method = 'POST'
603
612
        req.content_type = 'application/json'
604
613
        req.body = json.dumps(body)
606
615
        self.assertEqual(res.status_int, 400)
607
616
 
608
617
    def test_server_rebuild_accepted_minimum(self):
 
618
        new_return_server = return_server_with_attributes(image_ref='2')
 
619
        self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
 
620
 
609
621
        body = {
610
622
            "rebuild": {
611
623
                "imageRef": "http://localhost/images/2",
612
624
            },
613
625
        }
614
626
 
615
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
627
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
616
628
        req.method = 'POST'
617
629
        req.content_type = 'application/json'
618
630
        req.body = json.dumps(body)
619
631
 
620
632
        res = req.get_response(fakes.wsgi_app())
621
633
        self.assertEqual(res.status_int, 202)
 
634
        body = json.loads(res.body)
 
635
        self.assertEqual(body['server']['image']['id'], '2')
 
636
        self.assertEqual(len(body['server']['adminPass']), 16)
622
637
 
623
638
    def test_server_rebuild_rejected_when_building(self):
624
639
        body = {
633
648
        self.stubs.Set(nova.db, 'instance_get_by_uuid',
634
649
                       return_server_with_uuid_and_power_state(state))
635
650
 
636
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
651
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
637
652
        req.method = 'POST'
638
653
        req.content_type = 'application/json'
639
654
        req.body = json.dumps(body)
642
657
        self.assertEqual(res.status_int, 409)
643
658
 
644
659
    def test_server_rebuild_accepted_with_metadata(self):
 
660
        metadata = {'new': 'metadata'}
 
661
 
 
662
        new_return_server = return_server_with_attributes(metadata=metadata)
 
663
        self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
 
664
 
645
665
        body = {
646
666
            "rebuild": {
647
667
                "imageRef": "http://localhost/images/2",
648
 
                "metadata": {
649
 
                    "new": "metadata",
650
 
                },
 
668
                "metadata": metadata,
651
669
            },
652
670
        }
653
671
 
654
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
672
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
655
673
        req.method = 'POST'
656
674
        req.content_type = 'application/json'
657
675
        req.body = json.dumps(body)
658
676
 
659
677
        res = req.get_response(fakes.wsgi_app())
660
678
        self.assertEqual(res.status_int, 202)
 
679
        body = json.loads(res.body)
 
680
        self.assertEqual(body['server']['metadata'], metadata)
661
681
 
662
682
    def test_server_rebuild_accepted_with_bad_metadata(self):
663
683
        body = {
667
687
            },
668
688
        }
669
689
 
670
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
690
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
671
691
        req.method = 'POST'
672
692
        req.content_type = 'application/json'
673
693
        req.body = json.dumps(body)
682
702
            },
683
703
        }
684
704
 
685
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
705
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
686
706
        req.method = 'POST'
687
707
        req.content_type = 'application/json'
688
708
        req.body = json.dumps(body)
701
721
            },
702
722
        }
703
723
 
704
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
724
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
705
725
        req.method = 'POST'
706
726
        req.content_type = 'application/json'
707
727
        req.body = json.dumps(body)
720
740
            },
721
741
        }
722
742
 
723
 
        req = webob.Request.blank('/v1.1/servers/1/action')
724
 
        req.method = 'POST'
725
 
        req.content_type = 'application/json'
726
 
        req.body = json.dumps(body)
727
 
 
728
 
        res = req.get_response(fakes.wsgi_app())
729
 
        self.assertEqual(res.status_int, 202)
 
743
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
 
744
        req.method = 'POST'
 
745
        req.content_type = 'application/json'
 
746
        req.body = json.dumps(body)
 
747
 
 
748
        res = req.get_response(fakes.wsgi_app())
 
749
        self.assertEqual(res.status_int, 202)
 
750
        body = json.loads(res.body)
 
751
        self.assertTrue('personality' not in body['server'])
 
752
 
 
753
    def test_server_rebuild_admin_pass(self):
 
754
        new_return_server = return_server_with_attributes(image_ref='2')
 
755
        self.stubs.Set(nova.db.api, 'instance_get', new_return_server)
 
756
 
 
757
        body = {
 
758
            "rebuild": {
 
759
                "imageRef": "http://localhost/images/2",
 
760
                "adminPass": "asdf",
 
761
            },
 
762
        }
 
763
 
 
764
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
 
765
        req.method = 'POST'
 
766
        req.content_type = 'application/json'
 
767
        req.body = json.dumps(body)
 
768
 
 
769
        res = req.get_response(fakes.wsgi_app())
 
770
        self.assertEqual(res.status_int, 202)
 
771
        body = json.loads(res.body)
 
772
        self.assertEqual(body['server']['image']['id'], '2')
 
773
        self.assertEqual(body['server']['adminPass'], 'asdf')
 
774
 
 
775
    def test_server_rebuild_server_not_found(self):
 
776
        def server_not_found(self, instance_id):
 
777
            raise exception.InstanceNotFound(instance_id=instance_id)
 
778
        self.stubs.Set(nova.db.api, 'instance_get', server_not_found)
 
779
 
 
780
        body = {
 
781
            "rebuild": {
 
782
                "imageRef": "http://localhost/images/2",
 
783
            },
 
784
        }
 
785
 
 
786
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
 
787
        req.method = 'POST'
 
788
        req.content_type = 'application/json'
 
789
        req.body = json.dumps(body)
 
790
 
 
791
        res = req.get_response(fakes.wsgi_app())
 
792
        self.assertEqual(res.status_int, 404)
730
793
 
731
794
    def test_resize_server(self):
732
795
 
733
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
796
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
734
797
        req.content_type = 'application/json'
735
798
        req.method = 'POST'
736
799
        body_dict = dict(resize=dict(flavorRef="http://localhost/3"))
748
811
        self.assertEqual(self.resize_called, True)
749
812
 
750
813
    def test_resize_server_no_flavor(self):
751
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
814
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
752
815
        req.content_type = 'application/json'
753
816
        req.method = 'POST'
754
817
        body_dict = dict(resize=dict())
758
821
        self.assertEqual(res.status_int, 400)
759
822
 
760
823
    def test_resize_server_no_flavor_ref(self):
761
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
824
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
762
825
        req.content_type = 'application/json'
763
826
        req.method = 'POST'
764
827
        body_dict = dict(resize=dict(flavorRef=None))
768
831
        self.assertEqual(res.status_int, 400)
769
832
 
770
833
    def test_confirm_resize_server(self):
771
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
834
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
772
835
        req.content_type = 'application/json'
773
836
        req.method = 'POST'
774
837
        body_dict = dict(confirmResize=None)
786
849
        self.assertEqual(self.confirm_resize_called, True)
787
850
 
788
851
    def test_revert_resize_server(self):
789
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
852
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
790
853
        req.content_type = 'application/json'
791
854
        req.method = 'POST'
792
855
        body_dict = dict(revertResize=None)
809
872
                'name': 'Snapshot 1',
810
873
            },
811
874
        }
812
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
875
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
813
876
        req.method = 'POST'
814
877
        req.body = json.dumps(body)
815
878
        req.headers["content-type"] = "application/json"
828
891
                'name': 'Snapshot 1',
829
892
            },
830
893
        }
831
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
894
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
832
895
        req.method = 'POST'
833
896
        req.body = json.dumps(body)
834
897
        req.headers["content-type"] = "application/json"
842
905
                'metadata': {'key': 'asdf'},
843
906
            },
844
907
        }
845
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
908
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
846
909
        req.method = 'POST'
847
910
        req.body = json.dumps(body)
848
911
        req.headers["content-type"] = "application/json"
860
923
        }
861
924
        for num in range(FLAGS.quota_metadata_items + 1):
862
925
            body['createImage']['metadata']['foo%i' % num] = "bar"
863
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
926
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
864
927
        req.method = 'POST'
865
928
        req.body = json.dumps(body)
866
929
        req.headers["content-type"] = "application/json"
871
934
        body = {
872
935
            'createImage': {},
873
936
        }
874
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
937
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
875
938
        req.method = 'POST'
876
939
        req.body = json.dumps(body)
877
940
        req.headers["content-type"] = "application/json"
885
948
                'metadata': 'henry',
886
949
            },
887
950
        }
888
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
951
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
889
952
        req.method = 'POST'
890
953
        req.body = json.dumps(body)
891
954
        req.headers["content-type"] = "application/json"
904
967
            },
905
968
        }
906
969
 
907
 
        req = webob.Request.blank('/v1.1/servers/1/action')
 
970
        req = webob.Request.blank('/v1.1/fake/servers/1/action')
908
971
        req.method = 'POST'
909
972
        req.body = json.dumps(body)
910
973
        req.headers["content-type"] = "application/json"