Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright 2016 The LUCI Authors. All rights reserved. | 1 # Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 """Utilities for operating on instance group managers.""" | 5 """Utilities for operating on instance group managers.""" |
| 6 | 6 |
| 7 import logging | 7 import logging |
| 8 | 8 |
| 9 from google.appengine.ext import ndb | 9 from google.appengine.ext import ndb |
| 10 | 10 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 'InstanceTemplateRevision project unspecified: %s', key.parent()) | 127 'InstanceTemplateRevision project unspecified: %s', key.parent()) |
| 128 return | 128 return |
| 129 | 129 |
| 130 if not parent.url: | 130 if not parent.url: |
| 131 logging.warning( | 131 logging.warning( |
| 132 'InstanceTemplateRevision URL unspecified: %s', key.parent()) | 132 'InstanceTemplateRevision URL unspecified: %s', key.parent()) |
| 133 return | 133 return |
| 134 | 134 |
| 135 api = gce.Project(parent.project) | 135 api = gce.Project(parent.project) |
| 136 try: | 136 try: |
| 137 # Create the instance group manager with 0 instances. The resize cron job | |
| 138 # will adjust this later. | |
| 137 result = api.create_instance_group_manager( | 139 result = api.create_instance_group_manager( |
| 138 get_name(entity), | 140 get_name(entity), |
| 139 parent.url, | 141 parent.url, |
| 140 entity.minimum_size, | 142 0, |
| 141 entity.key.id(), | 143 entity.key.id(), |
| 142 base_name=get_base_name(entity), | 144 base_name=get_base_name(entity), |
| 143 ) | 145 ) |
| 144 except net.Error as e: | 146 except net.Error as e: |
| 145 if e.status_code == 409: | 147 if e.status_code == 409: |
| 146 # If the instance template already exists, just record the URL. | 148 # If the instance template already exists, just record the URL. |
| 147 result = api.get_instance_group_manager(get_name(entity), entity.key.id()) | 149 result = api.get_instance_group_manager(get_name(entity), entity.key.id()) |
| 148 update_url(entity.key, result['selfLink']) | 150 update_url(entity.key, result['selfLink']) |
| 149 return | 151 return |
| 150 else: | 152 else: |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 logging.warning( | 276 logging.warning( |
| 275 'Failed to enqueue task for InstanceGroupManager: %s', key) | 277 'Failed to enqueue task for InstanceGroupManager: %s', key) |
| 276 | 278 |
| 277 | 279 |
| 278 def resize(key): | 280 def resize(key): |
| 279 """Resizes the given instance group manager. | 281 """Resizes the given instance group manager. |
| 280 | 282 |
| 281 Args: | 283 Args: |
| 282 key: ndb.Key for a models.InstanceGroupManager entity. | 284 key: ndb.Key for a models.InstanceGroupManager entity. |
| 283 """ | 285 """ |
| 286 # To avoid a massive resize, impose a limit on how much larger we can | |
| 287 # resize the instance group. Repeated calls will eventually allow the | |
| 288 # instance group to reach its target size. Cron timing together with | |
| 289 # this limit controls the rate at which instances are created. | |
| 290 RESIZE_LIMIT = 100 | |
| 291 | |
| 284 entity = key.get() | 292 entity = key.get() |
| 285 if not entity: | 293 if not entity: |
| 286 logging.warning('InstanceGroupManager does not exist: %s', key) | 294 logging.warning('InstanceGroupManager does not exist: %s', key) |
| 287 return | 295 return |
| 288 | 296 |
| 289 if not entity.url: | 297 if not entity.url: |
| 290 logging.warning('InstanceGroupManager URL unspecified: %s', key) | 298 logging.warning('InstanceGroupManager URL unspecified: %s', key) |
| 291 | 299 |
| 292 parent = key.parent().get() | 300 parent = key.parent().get() |
| 293 if not parent: | 301 if not parent: |
| 294 logging.warning('InstanceTemplateRevision does not exist: %s', key) | 302 logging.warning('InstanceTemplateRevision does not exist: %s', key) |
| 295 return | 303 return |
| 296 | 304 |
| 297 if not parent.project: | 305 if not parent.project: |
| 298 logging.warning('InstanceTemplateRevision project unspecified: %s', key) | 306 logging.warning('InstanceTemplateRevision project unspecified: %s', key) |
| 299 return | 307 return |
| 300 | 308 |
| 301 # For now, just ensure a minimum size. | 309 api = gce.Project(parent.project) |
| 302 if entity.current_size >= entity.minimum_size: | 310 response = api.get_instance_group_manager(get_name(entity), key.id()) |
| 311 | |
| 312 # Try to reach the target size, but avoid increasing the number of | |
| 313 # instances by more than the resize limit. For now, the target size | |
| 314 # is just the minimum size. | |
| 315 target_size = min(entity.minimum_size, response['targetSize'] + RESIZE_LIMIT) | |
| 316 if response['targetSize'] >= target_size: | |
|
Vadim Sh.
2016/06/29 23:17:48
how is it going to scale down then if we change mi
smut
2016/06/29 23:24:38
We never scale down, we just wait for excess VMs t
| |
| 303 return | 317 return |
| 304 | 318 |
| 305 api = gce.Project(parent.project) | 319 api.resize_managed_instance_group(response['name'], key.id(), target_size) |
| 306 api.resize_managed_instance_group( | |
| 307 get_name(entity), key.id(), entity.minimum_size) | |
| 308 | 320 |
| 309 | 321 |
| 310 def schedule_resize(): | 322 def schedule_resize(): |
| 311 """Enqueues tasks to resize instance group managers.""" | 323 """Enqueues tasks to resize instance group managers.""" |
| 312 for instance_template in models.InstanceTemplate.query(): | 324 for instance_template in models.InstanceTemplate.query(): |
| 313 if instance_template.active: | 325 if instance_template.active: |
| 314 instance_template_revision = instance_template.active.get() | 326 instance_template_revision = instance_template.active.get() |
| 315 if instance_template_revision: | 327 if instance_template_revision: |
| 316 for instance_group_manager_key in instance_template_revision.active: | 328 for instance_group_manager_key in instance_template_revision.active: |
| 317 if not utils.enqueue_task( | 329 if not utils.enqueue_task( |
| 318 '/internal/queues/resize-instance-group', | 330 '/internal/queues/resize-instance-group', |
| 319 'resize-instance-group', | 331 'resize-instance-group', |
| 320 params={ | 332 params={ |
| 321 'key': instance_group_manager_key.urlsafe(), | 333 'key': instance_group_manager_key.urlsafe(), |
| 322 }, | 334 }, |
| 323 ): | 335 ): |
| 324 logging.warning( | 336 logging.warning( |
| 325 'Failed to enqueue task for InstanceGroupManager: %s', | 337 'Failed to enqueue task for InstanceGroupManager: %s', |
| 326 instance_group_manager_key, | 338 instance_group_manager_key, |
| 327 ) | 339 ) |
| OLD | NEW |