~0x44/nova/bug838466

« back to all changes in this revision

Viewing changes to nova/compute/api.py

  • Committer: Trey Morris
  • Date: 2011-06-30 19:20:59 UTC
  • mfrom: (1236 nova)
  • mto: This revision was merged to the branch mainline in revision 1237.
  • Revision ID: trey.morris@rackspace.com-20110630192059-pi1p516i50t8pc06
trunk merge with migration renumbering

Show diffs side-by-side

added added

removed removed

Lines of Context:
48
48
                     'Timeout after NN seconds when looking for a host.')
49
49
 
50
50
 
51
 
def generate_default_hostname(instance_id):
 
51
def generate_default_hostname(instance):
52
52
    """Default function to generate a hostname given an instance reference."""
53
 
    return str(instance_id)
 
53
    display_name = instance['display_name']
 
54
    if display_name is None:
 
55
        return 'server_%d' % (instance['id'],)
 
56
    table = ''
 
57
    deletions = ''
 
58
    for i in xrange(256):
 
59
        c = chr(i)
 
60
        if ('a' <= c <= 'z') or ('0' <= c <= '9') or (c == '-'):
 
61
            table += c
 
62
        elif c == ' ':
 
63
            table += '_'
 
64
        elif ('A' <= c <= 'Z'):
 
65
            table += c.lower()
 
66
        else:
 
67
            table += '\0'
 
68
            deletions += c
 
69
    if isinstance(display_name, unicode):
 
70
        display_name = display_name.encode('latin-1', 'ignore')
 
71
    return display_name.translate(table, deletions)
54
72
 
55
73
 
56
74
def _is_able_to_shutdown(instance, instance_id):
126
144
 
127
145
    def _check_create_parameters(self, context, instance_type,
128
146
               image_href, kernel_id=None, ramdisk_id=None,
129
 
               min_count=1, max_count=1,
 
147
               min_count=None, max_count=None,
130
148
               display_name='', display_description='',
131
149
               key_name=None, key_data=None, security_group='default',
132
150
               availability_zone=None, user_data=None, metadata={},
137
155
 
138
156
        if not instance_type:
139
157
            instance_type = instance_types.get_default_instance_type()
 
158
        if not min_count:
 
159
            min_count = 1
 
160
        if not max_count:
 
161
            max_count = min_count
140
162
 
141
163
        num_instances = quota.allowed_instances(context, max_count,
142
164
                                                instance_type)
186
208
        if ramdisk_id:
187
209
            image_service.show(context, ramdisk_id)
188
210
 
189
 
        if security_group is None:
190
 
            security_group = ['default']
191
 
        if not type(security_group) is list:
192
 
            security_group = [security_group]
193
 
 
194
 
        security_groups = []
195
211
        self.ensure_default_security_group(context)
196
 
        for security_group_name in security_group:
197
 
            group = db.security_group_get_by_name(context,
198
 
                                                  context.project_id,
199
 
                                                  security_group_name)
200
 
            security_groups.append(group['id'])
201
212
 
202
213
        if key_data is None and key_name:
203
214
            key_pair = db.key_pair_get(context, context.user_id, key_name)
232
243
            'architecture': architecture,
233
244
            'vm_mode': vm_mode}
234
245
 
235
 
        return (num_instances, base_options, security_groups)
 
246
        return (num_instances, base_options)
236
247
 
237
248
    def create_db_entry_for_new_instance(self, context, base_options,
238
 
             security_groups, block_device_mapping, num=1):
 
249
             security_group, block_device_mapping, num=1):
239
250
        """Create an entry in the DB for this new instance,
240
 
        including any related table updates (such as security
241
 
        groups, MAC address, etc). This will called by create()
242
 
        in the majority of situations, but all-at-once style
243
 
        Schedulers may initiate the call."""
244
 
        instance = dict(launch_index=num,
245
 
                        **base_options)
 
251
        including any related table updates (such as security group,
 
252
        etc).
 
253
 
 
254
        This will called by create() in the majority of situations,
 
255
        but create_all_at_once() style Schedulers may initiate the call.
 
256
        If you are changing this method, be sure to update both
 
257
        call paths.
 
258
        """
 
259
        instance = dict(launch_index=num, **base_options)
246
260
        instance = self.db.instance_create(context, instance)
247
261
        instance_id = instance['id']
248
262
 
249
263
        elevated = context.elevated()
250
 
        if not security_groups:
251
 
            security_groups = []
 
264
        if security_group is None:
 
265
            security_group = ['default']
 
266
        if not isinstance(security_group, list):
 
267
            security_group = [security_group]
 
268
 
 
269
        security_groups = []
 
270
        for security_group_name in security_group:
 
271
            group = db.security_group_get_by_name(context,
 
272
                                                  context.project_id,
 
273
                                                  security_group_name)
 
274
            security_groups.append(group['id'])
 
275
 
252
276
        for security_group_id in security_groups:
253
277
            self.db.instance_add_security_group(elevated,
254
278
                                                instance_id,
255
279
                                                security_group_id)
256
280
 
 
281
        block_device_mapping = block_device_mapping or []
257
282
        # NOTE(yamahata)
258
283
        # tell vm driver to attach volume at boot time by updating
259
284
        # BlockDeviceMapping
272
297
            self.db.block_device_mapping_create(elevated, values)
273
298
 
274
299
        # Set sane defaults if not specified
275
 
        updates = dict(hostname=self.hostname_factory(instance_id))
 
300
        updates = {}
276
301
        if (not hasattr(instance, 'display_name') or
277
302
                instance.display_name is None):
278
303
            updates['display_name'] = "Server %s" % instance_id
 
304
            instance['display_name'] = updates['display_name']
 
305
        updates['hostname'] = self.hostname_factory(instance)
279
306
 
280
307
        instance = self.update(context, instance_id, **updates)
281
308
 
320
347
 
321
348
    def create_all_at_once(self, context, instance_type,
322
349
               image_href, kernel_id=None, ramdisk_id=None,
323
 
               min_count=1, max_count=1,
 
350
               min_count=None, max_count=None,
324
351
               display_name='', display_description='',
325
352
               key_name=None, key_data=None, security_group='default',
326
353
               availability_zone=None, user_data=None, metadata={},
327
354
               injected_files=None, admin_password=None, zone_blob=None,
328
 
               reservation_id=None):
 
355
               reservation_id=None, block_device_mapping=None):
329
356
        """Provision the instances by passing the whole request to
330
357
        the Scheduler for execution. Returns a Reservation ID
331
358
        related to the creation of all of these instances."""
332
 
        num_instances, base_options, security_groups = \
333
 
                    self._check_create_parameters(
 
359
        num_instances, base_options = self._check_create_parameters(
334
360
                               context, instance_type,
335
361
                               image_href, kernel_id, ramdisk_id,
336
362
                               min_count, max_count,
350
376
 
351
377
    def create(self, context, instance_type,
352
378
               image_href, kernel_id=None, ramdisk_id=None,
353
 
               min_count=1, max_count=1,
 
379
               min_count=None, max_count=None,
354
380
               display_name='', display_description='',
355
381
               key_name=None, key_data=None, security_group='default',
356
382
               availability_zone=None, user_data=None, metadata={},
362
388
        Scheduler drivers, but may remove the effectiveness of the
363
389
        more complicated drivers.
364
390
 
 
391
        NOTE: If you change this method, be sure to change
 
392
        create_all_at_once() at the same time!
 
393
 
365
394
        Returns a list of instance dicts.
366
395
        """
367
396
 
368
 
        num_instances, base_options, security_groups = \
369
 
                    self._check_create_parameters(
 
397
        num_instances, base_options = self._check_create_parameters(
370
398
                               context, instance_type,
371
399
                               image_href, kernel_id, ramdisk_id,
372
400
                               min_count, max_count,
376
404
                               injected_files, admin_password, zone_blob,
377
405
                               reservation_id)
378
406
 
379
 
        block_device_mapping = block_device_mapping or []
380
407
        instances = []
381
408
        LOG.debug(_("Going to run %s instances..."), num_instances)
382
409
        for num in range(num_instances):
383
410
            instance = self.create_db_entry_for_new_instance(context,
384
 
                                    base_options, security_groups,
 
411
                                    base_options, security_group,
385
412
                                    block_device_mapping, num=num)
386
413
            instances.append(instance)
387
414
            instance_id = instance['id']
595
622
        """
596
623
        return self.get(context, instance_id)
597
624
 
598
 
    def get_all_across_zones(self, context, reservation_id):
599
 
        """Get all instances with this reservation_id, across
600
 
        all available Zones (if any).
 
625
    def get_all(self, context, project_id=None, reservation_id=None,
 
626
                fixed_ip=None, recurse_zones=False):
 
627
        """Get all instances filtered by one of the given parameters.
 
628
 
 
629
        If there is no filter and the context is an admin, it will retreive
 
630
        all instances in the system.
601
631
        """
602
 
        context = context.elevated()
603
 
        instances = self.db.instance_get_all_by_reservation(
 
632
 
 
633
        if reservation_id is not None:
 
634
            recurse_zones = True
 
635
            instances = self.db.instance_get_all_by_reservation(
604
636
                                    context, reservation_id)
605
 
 
606
 
        children = scheduler_api.call_zone_method(context, "list",
607
 
                                novaclient_collection_name="servers",
608
 
                                reservation_id=reservation_id)
 
637
        elif fixed_ip is not None:
 
638
            try:
 
639
                instances = self.db.fixed_ip_get_instance(context, fixed_ip)
 
640
            except exception.FloatingIpNotFound, e:
 
641
                if not recurse_zones:
 
642
                    raise
 
643
                instances = None
 
644
        elif project_id or not context.is_admin:
 
645
            if not context.project:
 
646
                instances = self.db.instance_get_all_by_user(
 
647
                    context, context.user_id)
 
648
            else:
 
649
                if project_id is None:
 
650
                    project_id = context.project_id
 
651
                instances = self.db.instance_get_all_by_project(
 
652
                    context, project_id)
 
653
        else:
 
654
            instances = self.db.instance_get_all(context)
 
655
 
 
656
        if instances is None:
 
657
            instances = []
 
658
        elif not isinstance(instances, list):
 
659
            instances = [instances]
 
660
 
 
661
        if not recurse_zones:
 
662
            return instances
 
663
 
 
664
        admin_context = context.elevated()
 
665
        children = scheduler_api.call_zone_method(admin_context,
 
666
                "list",
 
667
                novaclient_collection_name="servers",
 
668
                reservation_id=reservation_id,
 
669
                project_id=project_id,
 
670
                fixed_ip=fixed_ip,
 
671
                recurse_zones=True)
609
672
 
610
673
        for zone, servers in children:
611
674
            for server in servers:
614
677
                instances.append(server._info)
615
678
        return instances
616
679
 
617
 
    def get_all(self, context, project_id=None, reservation_id=None,
618
 
                fixed_ip=None):
619
 
        """Get all instances filtered by one of the given parameters.
620
 
 
621
 
        If there is no filter and the context is an admin, it will retreive
622
 
        all instances in the system.
623
 
        """
624
 
        if reservation_id is not None:
625
 
            return self.get_all_across_zones(context, reservation_id)
626
 
 
627
 
        if fixed_ip is not None:
628
 
            return self.db.fixed_ip_get_instance(context, fixed_ip)
629
 
 
630
 
        if project_id or not context.is_admin:
631
 
            if not context.project:
632
 
                return self.db.instance_get_all_by_user(
633
 
                    context, context.user_id)
634
 
 
635
 
            if project_id is None:
636
 
                project_id = context.project_id
637
 
 
638
 
            return self.db.instance_get_all_by_project(
639
 
                context, project_id)
640
 
 
641
 
        return self.db.instance_get_all(context)
642
 
 
643
680
    def _cast_compute_message(self, method, context, instance_id, host=None,
644
681
                              params=None):
645
682
        """Generic handler for RPC casts to compute.