~heckj/nova/lp798876

« back to all changes in this revision

Viewing changes to nova/compute/manager.py

  • Committer: Joe Heck
  • Date: 2011-07-19 18:30:40 UTC
  • mfrom: (1250.1.33 nova)
  • Revision ID: heckj@mac.com-20110719183040-8uf09a0bqkebthyh
merging in changes from trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
54
54
from nova import utils
55
55
from nova import volume
56
56
from nova.compute import power_state
57
 
from nova.notifier import api as notifier_api
 
57
from nova.notifier import api as notifier
58
58
from nova.compute.utils import terminate_volumes
59
59
from nova.virt import driver
60
60
 
85
85
LOG = logging.getLogger('nova.compute.manager')
86
86
 
87
87
 
 
88
def publisher_id(host=None):
 
89
    return notifier.publisher_id("compute", host)
 
90
 
 
91
 
88
92
def checks_instance_lock(function):
89
93
    """Decorator to prevent action against locked instances for non-admins."""
90
94
    @functools.wraps(function)
183
187
    def get_console_pool_info(self, context, console_type):
184
188
        return self.driver.get_console_pool_info(console_type)
185
189
 
186
 
    @exception.wrap_exception
 
190
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
187
191
    def refresh_security_group_rules(self, context, security_group_id,
188
192
                                     **kwargs):
189
193
        """Tell the virtualization driver to refresh security group rules.
193
197
        """
194
198
        return self.driver.refresh_security_group_rules(security_group_id)
195
199
 
196
 
    @exception.wrap_exception
 
200
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
197
201
    def refresh_security_group_members(self, context,
198
202
                                       security_group_id, **kwargs):
199
203
        """Tell the virtualization driver to refresh security group members.
203
207
        """
204
208
        return self.driver.refresh_security_group_members(security_group_id)
205
209
 
206
 
    @exception.wrap_exception
 
210
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
207
211
    def refresh_provider_fw_rules(self, context, **_kwargs):
208
212
        """This call passes straight through to the virtualization driver."""
209
213
        return self.driver.refresh_provider_fw_rules()
220
224
        for bdm in self.db.block_device_mapping_get_all_by_instance(
221
225
            context, instance_id):
222
226
            LOG.debug(_("setting up bdm %s"), bdm)
 
227
 
 
228
            if bdm['no_device']:
 
229
                continue
 
230
            if bdm['virtual_name']:
 
231
                # TODO(yamahata):
 
232
                # block devices for swap and ephemeralN will be
 
233
                # created by virt driver locally in compute node.
 
234
                assert (bdm['virtual_name'] == 'swap' or
 
235
                        bdm['virtual_name'].startswith('ephemeral'))
 
236
                continue
 
237
 
223
238
            if ((bdm['snapshot_id'] is not None) and
224
239
                (bdm['volume_id'] is None)):
225
240
                # TODO(yamahata): default name and description
252
267
                block_device_mapping.append({'device_path': dev_path,
253
268
                                             'mount_device':
254
269
                                             bdm['device_name']})
255
 
            elif bdm['virtual_name'] is not None:
256
 
                # TODO(yamahata): ephemeral/swap device support
257
 
                LOG.debug(_('block_device_mapping: '
258
 
                            'ephemeral device is not supported yet'))
259
 
            else:
260
 
                # TODO(yamahata): NoDevice support
261
 
                assert bdm['no_device']
262
 
                LOG.debug(_('block_device_mapping: '
263
 
                            'no device is not supported yet'))
264
270
 
265
271
        return block_device_mapping
266
272
 
318
324
            self._update_launched_at(context, instance_id)
319
325
            self._update_state(context, instance_id)
320
326
            usage_info = utils.usage_from_instance(instance)
321
 
            notifier_api.notify('compute.%s' % self.host,
322
 
                                'compute.instance.create',
323
 
                                notifier_api.INFO,
324
 
                                usage_info)
 
327
            notifier.notify('compute.%s' % self.host,
 
328
                            'compute.instance.create',
 
329
                            notifier.INFO, usage_info)
325
330
        except exception.InstanceNotFound:
326
331
            # FIXME(wwolf): We are just ignoring InstanceNotFound
327
332
            # exceptions here in case the instance was immediately
329
334
            # be fixed once we have no-db-messaging
330
335
            pass
331
336
 
332
 
    @exception.wrap_exception
 
337
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
333
338
    def run_instance(self, context, instance_id, **kwargs):
334
339
        self._run_instance(context, instance_id, **kwargs)
335
340
 
336
 
    @exception.wrap_exception
 
341
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
337
342
    @checks_instance_lock
338
343
    def start_instance(self, context, instance_id):
339
344
        """Starting an instance on this host."""
366
371
        if action_str == 'Terminating':
367
372
            terminate_volumes(self.db, context, instance_id)
368
373
 
369
 
    @exception.wrap_exception
 
374
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
370
375
    @checks_instance_lock
371
376
    def terminate_instance(self, context, instance_id):
372
377
        """Terminate an instance on this host."""
376
381
        # TODO(ja): should we keep it in a terminated state for a bit?
377
382
        self.db.instance_destroy(context, instance_id)
378
383
        usage_info = utils.usage_from_instance(instance)
379
 
        notifier_api.notify('compute.%s' % self.host,
380
 
                            'compute.instance.delete',
381
 
                            notifier_api.INFO,
382
 
                            usage_info)
 
384
        notifier.notify('compute.%s' % self.host,
 
385
                        'compute.instance.delete',
 
386
                        notifier.INFO, usage_info)
383
387
 
384
 
    @exception.wrap_exception
 
388
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
385
389
    @checks_instance_lock
386
390
    def stop_instance(self, context, instance_id):
387
391
        """Stopping an instance on this host."""
388
392
        self._shutdown_instance(context, instance_id, 'Stopping')
389
393
        # instance state will be updated to stopped by _poll_instance_states()
390
394
 
391
 
    @exception.wrap_exception
 
395
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
392
396
    @checks_instance_lock
393
397
    def rebuild_instance(self, context, instance_id, **kwargs):
394
398
        """Destroy and re-make this instance.
418
422
        self._update_state(context, instance_id)
419
423
        usage_info = utils.usage_from_instance(instance_ref,
420
424
                                               image_ref=image_ref)
421
 
        notifier_api.notify('compute.%s' % self.host,
 
425
        notifier.notify('compute.%s' % self.host,
422
426
                            'compute.instance.rebuild',
423
 
                            notifier_api.INFO,
 
427
                            notifier.INFO,
424
428
                            usage_info)
425
429
 
426
 
    @exception.wrap_exception
 
430
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
427
431
    @checks_instance_lock
428
432
    def reboot_instance(self, context, instance_id):
429
433
        """Reboot an instance on this host."""
448
452
        self.driver.reboot(instance_ref)
449
453
        self._update_state(context, instance_id)
450
454
 
451
 
    @exception.wrap_exception
 
455
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
452
456
    def snapshot_instance(self, context, instance_id, image_id,
453
457
                          image_type='snapshot', backup_type=None,
454
458
                          rotation=None):
540
544
                LOG.debug(_("Deleting image %d" % image_id))
541
545
                image_service.delete(context, image_id)
542
546
 
543
 
    @exception.wrap_exception
 
547
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
544
548
    @checks_instance_lock
545
549
    def set_admin_password(self, context, instance_id, new_pass=None):
546
550
        """Set the root/admin password for an instance on this host.
588
592
                    time.sleep(1)
589
593
                    continue
590
594
 
591
 
    @exception.wrap_exception
 
595
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
592
596
    @checks_instance_lock
593
597
    def inject_file(self, context, instance_id, path, file_contents):
594
598
        """Write a file to the specified path in an instance on this host."""
606
610
        LOG.audit(msg)
607
611
        self.driver.inject_file(instance_ref, path, file_contents)
608
612
 
609
 
    @exception.wrap_exception
 
613
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
610
614
    @checks_instance_lock
611
615
    def agent_update(self, context, instance_id, url, md5hash):
612
616
        """Update agent running on an instance on this host."""
624
628
        LOG.audit(msg)
625
629
        self.driver.agent_update(instance_ref, url, md5hash)
626
630
 
627
 
    @exception.wrap_exception
 
631
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
628
632
    @checks_instance_lock
629
633
    def rescue_instance(self, context, instance_id):
630
634
        """Rescue an instance on this host."""
641
645
        self.driver.rescue(instance_ref, _update_state)
642
646
        self._update_state(context, instance_id)
643
647
 
644
 
    @exception.wrap_exception
 
648
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
645
649
    @checks_instance_lock
646
650
    def unrescue_instance(self, context, instance_id):
647
651
        """Rescue an instance on this host."""
662
666
        """Update instance state when async task completes."""
663
667
        self._update_state(context, instance_id)
664
668
 
665
 
    @exception.wrap_exception
 
669
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
666
670
    @checks_instance_lock
667
671
    def confirm_resize(self, context, instance_id, migration_id):
668
672
        """Destroys the source instance."""
670
674
        instance_ref = self.db.instance_get(context, instance_id)
671
675
        self.driver.destroy(instance_ref)
672
676
        usage_info = utils.usage_from_instance(instance_ref)
673
 
        notifier_api.notify('compute.%s' % self.host,
 
677
        notifier.notify('compute.%s' % self.host,
674
678
                            'compute.instance.resize.confirm',
675
 
                            notifier_api.INFO,
 
679
                            notifier.INFO,
676
680
                            usage_info)
677
681
 
678
 
    @exception.wrap_exception
 
682
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
679
683
    @checks_instance_lock
680
684
    def revert_resize(self, context, instance_id, migration_id):
681
685
        """Destroys the new instance on the destination machine.
697
701
                       'instance_id': instance_id, },
698
702
                })
699
703
 
700
 
    @exception.wrap_exception
 
704
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
701
705
    @checks_instance_lock
702
706
    def finish_revert_resize(self, context, instance_id, migration_id):
703
707
        """Finishes the second half of reverting a resize.
722
726
        self.db.migration_update(context, migration_id,
723
727
                {'status': 'reverted'})
724
728
        usage_info = utils.usage_from_instance(instance_ref)
725
 
        notifier_api.notify('compute.%s' % self.host,
 
729
        notifier.notify('compute.%s' % self.host,
726
730
                            'compute.instance.resize.revert',
727
 
                            notifier_api.INFO,
 
731
                            notifier.INFO,
728
732
                            usage_info)
729
733
 
730
 
    @exception.wrap_exception
 
734
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
731
735
    @checks_instance_lock
732
736
    def prep_resize(self, context, instance_id, flavor_id):
733
737
        """Initiates the process of moving a running instance to another host.
765
769
        usage_info = utils.usage_from_instance(instance_ref,
766
770
                              new_instance_type=instance_type['name'],
767
771
                              new_instance_type_id=instance_type['id'])
768
 
        notifier_api.notify('compute.%s' % self.host,
 
772
        notifier.notify('compute.%s' % self.host,
769
773
                            'compute.instance.resize.prep',
770
 
                            notifier_api.INFO,
 
774
                            notifier.INFO,
771
775
                            usage_info)
772
776
 
773
 
    @exception.wrap_exception
 
777
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
774
778
    @checks_instance_lock
775
779
    def resize_instance(self, context, instance_id, migration_id):
776
780
        """Starts the migration of a running instance to another host."""
796
800
                                           'instance_id': instance_id,
797
801
                                           'disk_info': disk_info}})
798
802
 
799
 
    @exception.wrap_exception
 
803
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
800
804
    @checks_instance_lock
801
805
    def finish_resize(self, context, instance_id, migration_id, disk_info):
802
806
        """Completes the migration process.
828
832
        self.db.migration_update(context, migration_id,
829
833
                {'status': 'finished', })
830
834
 
831
 
    @exception.wrap_exception
 
835
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
832
836
    @checks_instance_lock
833
837
    def add_fixed_ip_to_instance(self, context, instance_id, network_id):
834
838
        """Calls network_api to add new fixed_ip to instance
840
844
        self.inject_network_info(context, instance_id)
841
845
        self.reset_network(context, instance_id)
842
846
 
843
 
    @exception.wrap_exception
 
847
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
 
848
    @checks_instance_lock
 
849
    def remove_fixed_ip_from_instance(self, context, instance_id, address):
 
850
        """Calls network_api to remove existing fixed_ip from instance
 
851
        by injecting the altered network info and resetting
 
852
        instance networking.
 
853
        """
 
854
        self.network_api.remove_fixed_ip_from_instance(context, instance_id,
 
855
                                                       address)
 
856
        self.inject_network_info(context, instance_id)
 
857
        self.reset_network(context, instance_id)
 
858
 
 
859
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
844
860
    @checks_instance_lock
845
861
    def pause_instance(self, context, instance_id):
846
862
        """Pause an instance on this host."""
857
873
                                                       instance_id,
858
874
                                                       result))
859
875
 
860
 
    @exception.wrap_exception
 
876
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
861
877
    @checks_instance_lock
862
878
    def unpause_instance(self, context, instance_id):
863
879
        """Unpause a paused instance on this host."""
874
890
                                                       instance_id,
875
891
                                                       result))
876
892
 
877
 
    @exception.wrap_exception
 
893
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
878
894
    def set_host_enabled(self, context, instance_id=None, host=None,
879
895
            enabled=None):
880
896
        """Sets the specified host's ability to accept new instances."""
881
897
        return self.driver.set_host_enabled(host, enabled)
882
898
 
883
 
    @exception.wrap_exception
 
899
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
884
900
    def get_diagnostics(self, context, instance_id):
885
901
        """Retrieve diagnostics for an instance on this host."""
886
902
        instance_ref = self.db.instance_get(context, instance_id)
889
905
                      context=context)
890
906
            return self.driver.get_diagnostics(instance_ref)
891
907
 
892
 
    @exception.wrap_exception
 
908
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
893
909
    @checks_instance_lock
894
910
    def suspend_instance(self, context, instance_id):
895
911
        """Suspend the given instance."""
905
921
                                                       instance_id,
906
922
                                                       result))
907
923
 
908
 
    @exception.wrap_exception
 
924
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
909
925
    @checks_instance_lock
910
926
    def resume_instance(self, context, instance_id):
911
927
        """Resume the given suspended instance."""
921
937
                                                       instance_id,
922
938
                                                       result))
923
939
 
924
 
    @exception.wrap_exception
 
940
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
925
941
    def lock_instance(self, context, instance_id):
926
942
        """Lock the given instance."""
927
943
        context = context.elevated()
929
945
        LOG.debug(_('instance %s: locking'), instance_id, context=context)
930
946
        self.db.instance_update(context, instance_id, {'locked': True})
931
947
 
932
 
    @exception.wrap_exception
 
948
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
933
949
    def unlock_instance(self, context, instance_id):
934
950
        """Unlock the given instance."""
935
951
        context = context.elevated()
937
953
        LOG.debug(_('instance %s: unlocking'), instance_id, context=context)
938
954
        self.db.instance_update(context, instance_id, {'locked': False})
939
955
 
940
 
    @exception.wrap_exception
 
956
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
941
957
    def get_lock(self, context, instance_id):
942
958
        """Return the boolean state of the given instance's lock."""
943
959
        context = context.elevated()
966
982
 
967
983
        self.driver.inject_network_info(instance, network_info)
968
984
 
969
 
    @exception.wrap_exception
 
985
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
970
986
    def get_console_output(self, context, instance_id):
971
987
        """Send the console output for the given instance."""
972
988
        context = context.elevated()
976
992
        output = self.driver.get_console_output(instance_ref)
977
993
        return output.decode('utf-8', 'replace').encode('ascii', 'replace')
978
994
 
979
 
    @exception.wrap_exception
 
995
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
980
996
    def get_ajax_console(self, context, instance_id):
981
997
        """Return connection information for an ajax console."""
982
998
        context = context.elevated()
984
1000
        instance_ref = self.db.instance_get(context, instance_id)
985
1001
        return self.driver.get_ajax_console(instance_ref)
986
1002
 
987
 
    @exception.wrap_exception
 
1003
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
988
1004
    def get_vnc_console(self, context, instance_id):
989
1005
        """Return connection information for a vnc console."""
990
1006
        context = context.elevated()
1047
1063
 
1048
1064
        return True
1049
1065
 
1050
 
    @exception.wrap_exception
 
1066
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1051
1067
    @checks_instance_lock
1052
1068
    def _detach_volume(self, context, instance_id, volume_id, destroy_bdm):
1053
1069
        """Detach a volume from an instance."""
1082
1098
        """
1083
1099
        self.volume_manager.remove_compute_volume(context, volume_id)
1084
1100
 
1085
 
    @exception.wrap_exception
 
1101
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1086
1102
    def compare_cpu(self, context, cpu_info):
1087
1103
        """Checks that the host cpu is compatible with a cpu given by xml.
1088
1104
 
1093
1109
        """
1094
1110
        return self.driver.compare_cpu(cpu_info)
1095
1111
 
1096
 
    @exception.wrap_exception
 
1112
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1097
1113
    def create_shared_storage_test_file(self, context):
1098
1114
        """Makes tmpfile under FLAGS.instance_path.
1099
1115
 
1113
1129
        os.close(fd)
1114
1130
        return os.path.basename(tmp_file)
1115
1131
 
1116
 
    @exception.wrap_exception
 
1132
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1117
1133
    def check_shared_storage_test_file(self, context, filename):
1118
1134
        """Confirms existence of the tmpfile under FLAGS.instances_path.
1119
1135
 
1125
1141
        if not os.path.exists(tmp_file):
1126
1142
            raise exception.FileNotFound(file_path=tmp_file)
1127
1143
 
1128
 
    @exception.wrap_exception
 
1144
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1129
1145
    def cleanup_shared_storage_test_file(self, context, filename):
1130
1146
        """Removes existence of the tmpfile under FLAGS.instances_path.
1131
1147
 
1136
1152
        tmp_file = os.path.join(FLAGS.instances_path, filename)
1137
1153
        os.remove(tmp_file)
1138
1154
 
1139
 
    @exception.wrap_exception
 
1155
    @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id())
1140
1156
    def update_available_resource(self, context):
1141
1157
        """See comments update_resource_info.
1142
1158