|
13 | 13 | # limitations under the License. |
14 | 14 | """Contains classes related to managed container services.""" |
15 | 15 |
|
16 | | -import collections |
17 | | -import itertools |
18 | 16 | import os |
19 | 17 | import time |
20 | | -from typing import Any, Callable, Iterable |
| 18 | +from typing import Any |
21 | 19 |
|
22 | 20 | from absl import flags |
23 | 21 | from perfkitbenchmarker import context |
24 | 22 | from perfkitbenchmarker import data |
25 | | -from perfkitbenchmarker import os_types |
26 | | -from perfkitbenchmarker import provider_info |
27 | 23 | from perfkitbenchmarker import resource |
28 | 24 | from perfkitbenchmarker import sample |
29 | 25 | from perfkitbenchmarker import virtual_machine |
@@ -311,258 +307,3 @@ def __init__(self, vm_config: virtual_machine.BaseVirtualMachine, name: str): |
311 | 307 | self.min_cpu_platform: str |
312 | 308 | self.cpus: int |
313 | 309 | self.memory_mib: int |
314 | | - |
315 | | - |
316 | | -class BaseContainerCluster(resource.BaseResource): |
317 | | - """A cluster that can be used to schedule containers.""" |
318 | | - |
319 | | - RESOURCE_TYPE = 'BaseContainerCluster' |
320 | | - REQUIRED_ATTRS = ['CLOUD', 'CLUSTER_TYPE'] |
321 | | - CLOUD: str |
322 | | - CLUSTER_TYPE: str |
323 | | - |
324 | | - def __init__(self, cluster_spec: container_spec_lib.ContainerClusterSpec): |
325 | | - super().__init__(user_managed=bool(cluster_spec.static_cluster)) |
326 | | - self.name: str = cluster_spec.static_cluster or 'pkb-' + FLAGS.run_uri |
327 | | - # Go get a BaseVM, to use strictly for config values. |
328 | | - default_vm_class = virtual_machine.GetVmClass( |
329 | | - self.CLOUD, os_types.DEFAULT, provider_info.DEFAULT_VM_PLATFORM |
330 | | - ) |
331 | | - default_vm_config: virtual_machine.BaseVirtualMachine = default_vm_class( |
332 | | - cluster_spec.vm_spec |
333 | | - ) # pytype: disable=not-instantiable |
334 | | - self.default_nodepool = self._InitializeDefaultNodePool( |
335 | | - cluster_spec, default_vm_config |
336 | | - ) |
337 | | - self.nodepools: dict[str, BaseNodePoolConfig] = {} |
338 | | - for name, nodepool_spec in cluster_spec.nodepools.copy().items(): |
339 | | - vm_config: virtual_machine.BaseVirtualMachine = default_vm_class( |
340 | | - nodepool_spec.vm_spec |
341 | | - ) # pytype: disable=not-instantiable |
342 | | - nodepool = self._InitializeNodePool(name, nodepool_spec, vm_config) |
343 | | - self.nodepools[nodepool.name] = nodepool |
344 | | - self.min_nodes: int = ( |
345 | | - cluster_spec.min_vm_count or self.default_nodepool.num_nodes |
346 | | - ) |
347 | | - self.max_nodes: int = ( |
348 | | - cluster_spec.max_vm_count or self.default_nodepool.num_nodes |
349 | | - ) |
350 | | - self.containers: dict[str, list[BaseContainer]] = collections.defaultdict( |
351 | | - list |
352 | | - ) |
353 | | - self.services: dict[str, BaseContainerService] = {} |
354 | | - self._extra_samples: list[sample.Sample] = [] |
355 | | - self.container_registry: BaseContainerRegistry | None = None |
356 | | - self.enable_vpa: bool = cluster_spec.enable_vpa |
357 | | - |
358 | | - @property |
359 | | - def num_nodes(self) -> int: |
360 | | - return self.default_nodepool.num_nodes |
361 | | - |
362 | | - @property |
363 | | - def zone(self) -> str: |
364 | | - return self.default_nodepool.zone |
365 | | - |
366 | | - def SetContainerRegistry(self, container_registry): |
367 | | - """Sets the container registry for the cluster.""" |
368 | | - self.container_registry = container_registry |
369 | | - |
370 | | - def _InitializeDefaultNodePool( |
371 | | - self, |
372 | | - cluster_spec: container_spec_lib.ContainerClusterSpec, |
373 | | - vm_config: virtual_machine.BaseVirtualMachine, |
374 | | - ) -> BaseNodePoolConfig: |
375 | | - nodepool_config = BaseNodePoolConfig( |
376 | | - vm_config, |
377 | | - DEFAULT_NODEPOOL, |
378 | | - ) |
379 | | - nodepool_config.num_nodes = cluster_spec.vm_count |
380 | | - self.InitializeNodePoolForCloud(vm_config, nodepool_config) |
381 | | - return nodepool_config |
382 | | - |
383 | | - def _InitializeNodePool( |
384 | | - self, |
385 | | - name: str, |
386 | | - nodepool_spec: container_spec_lib.NodepoolSpec, |
387 | | - vm_config: virtual_machine.BaseVirtualMachine, |
388 | | - ) -> BaseNodePoolConfig: |
389 | | - zone = ( |
390 | | - nodepool_spec.vm_spec.zone |
391 | | - if nodepool_spec.vm_spec |
392 | | - else self.default_nodepool.zone |
393 | | - ) |
394 | | - nodepool_config = BaseNodePoolConfig( |
395 | | - vm_config, |
396 | | - name, |
397 | | - ) |
398 | | - nodepool_config.sandbox_config = nodepool_spec.sandbox_config |
399 | | - nodepool_config.zone = zone |
400 | | - nodepool_config.num_nodes = nodepool_spec.vm_count |
401 | | - self.InitializeNodePoolForCloud(vm_config, nodepool_config) |
402 | | - return nodepool_config |
403 | | - |
404 | | - def InitializeNodePoolForCloud( |
405 | | - self, |
406 | | - vm_config: virtual_machine.BaseVirtualMachine, |
407 | | - nodepool_config: BaseNodePoolConfig, |
408 | | - ): |
409 | | - """Override to initialize cloud specific configs.""" |
410 | | - pass |
411 | | - |
412 | | - def GetNodePoolFromNodeName( |
413 | | - self, node_name: str |
414 | | - ) -> BaseNodePoolConfig | None: |
415 | | - """Get the nodepool from the node name. |
416 | | -
|
417 | | - This method assumes that the nodepool name is embedded in the node name. |
418 | | - Better would be a lookup from the cloud provider. |
419 | | -
|
420 | | - Args: |
421 | | - node_name: The name of the node. |
422 | | -
|
423 | | - Returns: |
424 | | - The associated nodepool, or None if not found. |
425 | | - """ |
426 | | - nodepool_names = self.nodepools.keys() |
427 | | - found_pools = [] |
428 | | - if '-default-' in node_name: |
429 | | - found_pools.append(self.default_nodepool) |
430 | | - for pool_name in nodepool_names: |
431 | | - if f'-{pool_name}-' in node_name: |
432 | | - found_pools.append(self.nodepools[pool_name]) |
433 | | - if len(found_pools) == 1: |
434 | | - return found_pools[0] |
435 | | - if len(found_pools) > 1: |
436 | | - raise ValueError( |
437 | | - f'Multiple nodepools found for node with name {node_name}:' |
438 | | - f' {found_pools}. Please change the name of the nodepools used to' |
439 | | - ' avoid this.' |
440 | | - ) |
441 | | - return None |
442 | | - |
443 | | - def GetMachineTypeFromNodeName(self, node_name: str) -> str | None: |
444 | | - """Get the machine type from the node name.""" |
445 | | - nodepool = self.GetNodePoolFromNodeName(node_name) |
446 | | - if nodepool is None: |
447 | | - return None |
448 | | - return nodepool.machine_type |
449 | | - |
450 | | - def DeleteContainers(self): |
451 | | - """Delete containers belonging to the cluster.""" |
452 | | - for container in itertools.chain(*list(self.containers.values())): |
453 | | - container.Delete() |
454 | | - |
455 | | - def DeleteServices(self): |
456 | | - """Delete services belonging to the cluster.""" |
457 | | - for service in self.services.values(): |
458 | | - service.Delete() |
459 | | - |
460 | | - def GetResourceMetadata(self): |
461 | | - """Returns a dictionary of cluster metadata.""" |
462 | | - nodepools_metadata = {} |
463 | | - for name, nodepool in self.nodepools.items(): |
464 | | - nodepool_metadata = { |
465 | | - 'size': nodepool.num_nodes, |
466 | | - 'machine_type': nodepool.machine_type, |
467 | | - 'name': name, |
468 | | - } |
469 | | - if nodepool.sandbox_config is not None: |
470 | | - nodepool_metadata['sandbox_config'] = { |
471 | | - 'type': nodepool.sandbox_config.type, |
472 | | - } |
473 | | - nodepools_metadata[name] = nodepool_metadata |
474 | | - |
475 | | - metadata = { |
476 | | - 'cloud': self.CLOUD, |
477 | | - 'cluster_type': self.CLUSTER_TYPE, |
478 | | - 'zone': self.default_nodepool.zone, |
479 | | - 'size': self.default_nodepool.num_nodes, |
480 | | - 'machine_type': self.default_nodepool.machine_type, |
481 | | - 'nodepools': nodepools_metadata, |
482 | | - } |
483 | | - |
484 | | - if ( |
485 | | - self.min_nodes != self.default_nodepool.num_nodes |
486 | | - or self.max_nodes != self.default_nodepool.num_nodes |
487 | | - ): |
488 | | - metadata.update({ |
489 | | - 'max_size': self.max_nodes, |
490 | | - 'min_size': self.min_nodes, |
491 | | - }) |
492 | | - |
493 | | - return metadata |
494 | | - |
495 | | - def DeployContainer(self, name, container_spec): |
496 | | - """Deploys Containers according to the ContainerSpec.""" |
497 | | - raise NotImplementedError() |
498 | | - |
499 | | - def DeployContainerService(self, name, container_spec): |
500 | | - """Deploys a ContainerSerivice according to the ContainerSpec.""" |
501 | | - raise NotImplementedError() |
502 | | - |
503 | | - def AddSamples(self, samples: Iterable[sample.Sample]): |
504 | | - self._extra_samples += samples |
505 | | - |
506 | | - def GetSamples(self): |
507 | | - """Return samples with information about deployment times.""" |
508 | | - samples = super().GetSamples() |
509 | | - for container in itertools.chain(*list(self.containers.values())): |
510 | | - metadata = {'image': container.image.split('/')[-1]} |
511 | | - if container.resource_ready_time and container.create_start_time: |
512 | | - samples.append( |
513 | | - sample.Sample( |
514 | | - 'Container Deployment Time', |
515 | | - container.resource_ready_time - container.create_start_time, |
516 | | - 'seconds', |
517 | | - metadata, |
518 | | - ) |
519 | | - ) |
520 | | - if container.delete_end_time and container.delete_start_time: |
521 | | - samples.append( |
522 | | - sample.Sample( |
523 | | - 'Container Delete Time', |
524 | | - container.delete_end_time - container.delete_start_time, |
525 | | - 'seconds', |
526 | | - metadata, |
527 | | - ) |
528 | | - ) |
529 | | - for service in self.services.values(): |
530 | | - metadata = {'image': service.image.split('/')[-1]} |
531 | | - if service.resource_ready_time and service.create_start_time: |
532 | | - samples.append( |
533 | | - sample.Sample( |
534 | | - 'Service Deployment Time', |
535 | | - service.resource_ready_time - service.create_start_time, |
536 | | - 'seconds', |
537 | | - metadata, |
538 | | - ) |
539 | | - ) |
540 | | - if service.delete_end_time and service.delete_start_time: |
541 | | - samples.append( |
542 | | - sample.Sample( |
543 | | - 'Service Delete Time', |
544 | | - service.delete_end_time - service.delete_start_time, |
545 | | - 'seconds', |
546 | | - metadata, |
547 | | - ) |
548 | | - ) |
549 | | - |
550 | | - samples += self._extra_samples |
551 | | - |
552 | | - return samples |
553 | | - |
554 | | - def ResizeNodePool(self, new_size: int, node_pool: str = DEFAULT_NODEPOOL): |
555 | | - """Change the number of nodes in the node pool.""" |
556 | | - raise NotImplementedError |
557 | | - |
558 | | - def GetNodePoolNames(self) -> list[str]: |
559 | | - """Get node pool names for the cluster.""" |
560 | | - raise NotImplementedError |
561 | | - |
562 | | - |
563 | | -def GetContainerClusterClass( |
564 | | - cloud: str, cluster_type: str |
565 | | -) -> Callable[[container_spec_lib.ContainerClusterSpec], BaseContainerCluster]: |
566 | | - return resource.GetResourceClass( |
567 | | - BaseContainerCluster, CLOUD=cloud, CLUSTER_TYPE=cluster_type |
568 | | - ) |
0 commit comments