コード例 #1
0
  def test_drain_hosts_timed_out_wait(self, _, mock_drain_hosts, mock_maintenance_status, mock_log):
    fake_maintenance_status_response = Response(
        responseCode=ResponseCode.OK,
        result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
          HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.SCHEDULED),
          HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.SCHEDULED),
          HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.SCHEDULED)
        ]))))

    mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
    mock_maintenance_status.return_value = fake_maintenance_status_response
    test_hosts = Hosts(set(TEST_HOSTNAMES))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
    maintenance.MAX_STATUS_WAIT = Amount(1, Time.MILLISECONDS)

    not_drained_hostnames = maintenance._drain_hosts(test_hosts)
    assert TEST_HOSTNAMES == sorted(not_drained_hostnames)
    assert mock_maintenance_status.call_count == 1
    mock_drain_hosts.assert_called_once_with(test_hosts)
    mock_maintenance_status.assert_called_once_with((Hosts(set(TEST_HOSTNAMES))))
    assert mock_log.mock_calls == [mock.call(textwrap.dedent("""\
        Failed to move all hosts into DRAINED within 1 ms:
        \tHost:us-west-001.example.com\tStatus:SCHEDULED
        \tHost:us-west-002.example.com\tStatus:SCHEDULED
        \tHost:us-west-003.example.com\tStatus:SCHEDULED"""))]
コード例 #2
0
    def test_check_status(self, mock_maintenance_status):
        mock_maintenance_status.return_value = Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(
                set([
                    HostStatus(host=TEST_HOSTNAMES[0],
                               mode=MaintenanceMode.DRAINING),
                    HostStatus(host=TEST_HOSTNAMES[1],
                               mode=MaintenanceMode.DRAINED),
                    HostStatus(host=TEST_HOSTNAMES[2],
                               mode=MaintenanceMode.NONE)
                ]))))
        maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
        result = maintenance.check_status(TEST_HOSTNAMES)
        mock_maintenance_status.assert_called_once_with(
            Hosts(set(TEST_HOSTNAMES)))

        assert len(result) == 3
        assert (TEST_HOSTNAMES[0],
                MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.DRAINING]
                ) in result
        assert (TEST_HOSTNAMES[1],
                MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.DRAINED]
                ) in result
        assert (
            TEST_HOSTNAMES[2],
            MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.NONE]) in result
コード例 #3
0
    def test_drain_hosts_timed_out_wait(self, _, mock_drain_hosts,
                                        mock_maintenance_status):
        fake_maintenance_status_response = Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(
                set([
                    HostStatus(host=TEST_HOSTNAMES[0],
                               mode=MaintenanceMode.SCHEDULED),
                    HostStatus(host=TEST_HOSTNAMES[1],
                               mode=MaintenanceMode.SCHEDULED),
                    HostStatus(host=TEST_HOSTNAMES[2],
                               mode=MaintenanceMode.SCHEDULED)
                ]))))

        mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
        mock_maintenance_status.return_value = fake_maintenance_status_response
        test_hosts = Hosts(set(TEST_HOSTNAMES))
        maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
        maintenance.MAX_STATUS_WAIT = Amount(1, Time.MILLISECONDS)

        not_drained_hostnames = maintenance._drain_hosts(test_hosts)
        assert TEST_HOSTNAMES == sorted(not_drained_hostnames)
        assert mock_maintenance_status.call_count == 1
        mock_drain_hosts.assert_called_once_with(test_hosts)
        mock_maintenance_status.assert_called_once_with(
            (Hosts(set(TEST_HOSTNAMES))))
コード例 #4
0
  def test_perform_maintenance_partial_sla_failure(self, mock_check_sla, mock_start_maintenance,
                               mock_drain_hosts, mock_operate_on_hosts, mock_complete_maintenance):
    mock_callback = mock.Mock()
    failed_host = 'us-west-001.example.com'
    mock_check_sla.return_value = set([failed_host])
    drained_hosts = set(TEST_HOSTNAMES) - set([failed_host])
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')

    with temporary_file() as fp:
      with group_by_rack():
        maintenance.perform_maintenance(
            TEST_HOSTNAMES,
            callback=mock_callback,
            grouping_function='by_rack',
            output_file=fp.name)

        with open(fp.name, 'r') as fpr:
          content = fpr.read()
          assert failed_host in content

        mock_start_maintenance.assert_called_once_with(TEST_HOSTNAMES)
        assert mock_check_sla.call_count == 1
        assert mock_drain_hosts.call_count == 1
        assert mock_drain_hosts.call_args_list == [mock.call(Hosts(drained_hosts))]
        assert mock_operate_on_hosts.call_count == 1
        assert mock_operate_on_hosts.call_args_list == [
            mock.call(Hosts(drained_hosts), mock_callback)]
        assert mock_complete_maintenance.call_count == 2
        assert mock_complete_maintenance.call_args_list == [
            mock.call(Hosts(set([failed_host]))), mock.call(Hosts(drained_hosts))]
コード例 #5
0
def test_rack_grouping():
    old_grouping_functions = HostMaintenance.GROUPING_FUNCTIONS.copy()
    HostMaintenance.GROUPING_FUNCTIONS["by_rack"] = rack_grouping

    example_host_list = [
        "west-aaa-001.example.com",
        "west-aaa-002.example.com",
        "west-xyz-002.example.com",
        "east-xyz-003.example.com",
        "east-xyz-004.example.com",
    ]

    try:
        batches = list(HostMaintenance.iter_batches(example_host_list, 1, "by_rack"))
        assert batches[0] == Hosts(set(["west-aaa-001.example.com", "west-aaa-002.example.com"]))
        assert batches[1] == Hosts(
            set(["west-xyz-002.example.com", "east-xyz-003.example.com", "east-xyz-004.example.com"])
        )

        batches = list(HostMaintenance.iter_batches(example_host_list, 2, "by_rack"))
        assert batches[0] == Hosts(set(example_host_list))

        batches = list(HostMaintenance.iter_batches(example_host_list, 3, "by_rack"))
        assert batches[0] == Hosts(set(example_host_list))

        with pytest.raises(ValueError):
            list(HostMaintenance.iter_batches(example_host_list, 0))

    finally:
        HostMaintenance.GROUPING_FUNCTIONS = old_grouping_functions
コード例 #6
0
  def test_perform_maintenance_partial_sla_failure(self, mock_check_sla, mock_start_maintenance,
                               mock_drain_hosts):
    failed_host = 'us-west-001.example.com'
    mock_check_sla.return_value = set([failed_host])
    mock_start_maintenance.return_value = TEST_HOSTNAMES
    drained_hosts = set(TEST_HOSTNAMES) - set([failed_host])
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')

    with temporary_file() as fp:
      with group_by_rack():
        drained = maintenance.perform_maintenance(
            TEST_HOSTNAMES,
            grouping_function='by_rack',
            output_file=fp.name)

        with open(fp.name, 'r') as fpr:
          content = fpr.read()
          assert failed_host in content

        mock_start_maintenance.assert_called_once_with(TEST_HOSTNAMES)
        assert len(drained) == 2
        assert failed_host not in drained
        assert mock_check_sla.call_count == 1
        assert mock_drain_hosts.call_count == 1
        assert mock_drain_hosts.call_args_list == [mock.call(Hosts(drained_hosts))]
コード例 #7
0
 def test_start_maintenance(self, mock_api):
     mock_api.return_value = Response(
         responseCode=ResponseCode.OK,
         result=Result(startMaintenanceResult=StartMaintenanceResult(
             statuses=set([HostStatus()]))))
     maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
     maintenance.start_maintenance(TEST_HOSTNAMES)
     mock_api.assert_called_once_with(Hosts(set(TEST_HOSTNAMES)))
コード例 #8
0
 def test_perform_maintenance(self, mock_check_sla, mock_start_maintenance, mock_drain_hosts):
   mock_check_sla.return_value = set()
   mock_start_maintenance.return_value = TEST_HOSTNAMES
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.perform_maintenance(TEST_HOSTNAMES)
   mock_start_maintenance.assert_called_once_with(TEST_HOSTNAMES)
   assert mock_check_sla.call_count == 3
   assert mock_drain_hosts.call_count == 3
   assert mock_drain_hosts.call_args_list == [
       mock.call(Hosts(set([hostname]))) for hostname in TEST_HOSTNAMES]
コード例 #9
0
 def test_perform_maintenance(self, mock_check_sla, mock_start_maintenance, mock_drain_hosts):
   mock_check_sla.return_value = set()
   mock_start_maintenance.return_value = TEST_HOSTNAMES
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.perform_maintenance(TEST_HOSTNAMES)
   mock_start_maintenance.assert_called_once_with(TEST_HOSTNAMES)
   assert mock_check_sla.call_count == 3
   assert mock_drain_hosts.call_count == 3
   assert mock_drain_hosts.call_args_list == [
       mock.call(Hosts(set([hostname]))) for hostname in TEST_HOSTNAMES]
コード例 #10
0
def test_default_grouping():
    example_host_list = ["xyz321.example.com", "bar337.example.com", "foo001.example.com"]

    batches = list(HostMaintenance.iter_batches(example_host_list, 1))
    assert batches[0] == Hosts(set(["bar337.example.com"]))
    assert batches[1] == Hosts(set(["foo001.example.com"]))
    assert batches[2] == Hosts(set(["xyz321.example.com"]))

    batches = list(HostMaintenance.iter_batches(example_host_list, 2))
    assert batches[0] == Hosts(set(["bar337.example.com", "foo001.example.com"]))
    assert batches[1] == Hosts(set(["xyz321.example.com"]))
コード例 #11
0
  def test_drain_hosts(self, mock_event_wait, mock_drain_hosts, mock_maintenance_status):
    fake_maintenance_status_response = [
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.SCHEDULED),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.SCHEDULED),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.SCHEDULED)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINING)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINED),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINED),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINED),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
            ]))))]

    fake_maintenance_status_call_args = []
    def fake_maintenance_status_side_effect(hosts):
      fake_maintenance_status_call_args.append(copy.deepcopy(hosts))
      return fake_maintenance_status_response.pop(0)

    mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
    mock_maintenance_status.side_effect = fake_maintenance_status_side_effect
    test_hosts = Hosts(set(TEST_HOSTNAMES))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')

    not_drained_hostnames = maintenance._drain_hosts(test_hosts)
    assert len(not_drained_hostnames) == 0
    mock_drain_hosts.assert_called_once_with(test_hosts)
    assert mock_maintenance_status.call_count == 4
    assert mock_event_wait.call_count == 4
    assert fake_maintenance_status_call_args == [
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES)))]
コード例 #12
0
  def test_drain_hosts(self, mock_event_wait, mock_drain_hosts, mock_maintenance_status):
    fake_maintenance_status_response = [
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.SCHEDULED),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.SCHEDULED),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.SCHEDULED)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINING)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
                HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINED),
                HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
            ])))),
        Response(
            responseCode=ResponseCode.OK,
            result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
                HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINED)
            ]))))]

    fake_maintenance_status_call_args = []
    def fake_maintenance_status_side_effect(hosts):
      fake_maintenance_status_call_args.append(copy.deepcopy(hosts))
      return fake_maintenance_status_response.pop(0)

    mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
    mock_maintenance_status.side_effect = fake_maintenance_status_side_effect
    test_hosts = Hosts(set(TEST_HOSTNAMES))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')

    not_drained_hostnames = maintenance._drain_hosts(test_hosts)
    assert len(not_drained_hostnames) == 0
    mock_drain_hosts.assert_called_once_with(test_hosts)
    assert mock_maintenance_status.call_count == 4
    assert mock_event_wait.call_count == 4
    assert fake_maintenance_status_call_args == [
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set([TEST_HOSTNAMES[0]])))]
コード例 #13
0
 def test_complete_maintenance(self, mock_end_maintenance, mock_maintenance_status, mock_warning):
   mock_maintenance_status.return_value = Response(result=Result(
       maintenanceStatusResult=MaintenanceStatusResult(set([
           HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.NONE),
           HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.NONE),
           HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
       ]))
   ))
   mock_end_maintenance.return_value = Response(responseCode=ResponseCode.OK)
   test_hosts = Hosts(set(TEST_HOSTNAMES))
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance._complete_maintenance(test_hosts)
   mock_end_maintenance.assert_called_once_with(test_hosts)
   mock_maintenance_status.assert_called_once_with(test_hosts)
   mock_warning.assert_called_once_with('%s is DRAINING or in DRAINED' % TEST_HOSTNAMES[2])
コード例 #14
0
 def test_complete_maintenance(self, mock_end_maintenance, mock_maintenance_status, mock_warning):
   mock_maintenance_status.return_value = Response(result=Result(
       maintenanceStatusResult=MaintenanceStatusResult(set([
           HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.NONE),
           HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.NONE),
           HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
       ]))
   ))
   mock_end_maintenance.return_value = Response(responseCode=ResponseCode.OK)
   test_hosts = Hosts(set(TEST_HOSTNAMES))
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance._complete_maintenance(test_hosts)
   mock_end_maintenance.assert_called_once_with(test_hosts)
   mock_maintenance_status.assert_called_once_with(test_hosts)
   mock_warning.assert_called_once_with('%s is DRAINING or in DRAINED' % TEST_HOSTNAMES[2])
コード例 #15
0
  def test_check_status(self, mock_maintenance_status):
    mock_maintenance_status.return_value = Response(responseCode=ResponseCode.OK, result=Result(
        maintenanceStatusResult=MaintenanceStatusResult(set([
            HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
            HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINED),
            HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.NONE)
        ]))
    ))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
    result = maintenance.check_status(TEST_HOSTNAMES)
    mock_maintenance_status.assert_called_once_with(Hosts(set(TEST_HOSTNAMES)))

    assert len(result) == 3
    assert (TEST_HOSTNAMES[0], MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.DRAINING]) in result
    assert (TEST_HOSTNAMES[1], MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.DRAINED]) in result
    assert (TEST_HOSTNAMES[2], MaintenanceMode._VALUES_TO_NAMES[MaintenanceMode.NONE]) in result
コード例 #16
0
def test_none_grouping():
  example_host_list = [
    'xyz321.example.com',
    'bar337.example.com',
    'foo001.example.com',
  ]

  batches = list(HostMaintenance.iter_batches(example_host_list, 'none'))
  assert batches[0] == Hosts(set(example_host_list))
  assert len(batches) == 1
コード例 #17
0
  def test_drain_hosts(self, mock_drain_hosts, mock_maintenance_status):
    fake_maintenance_status_response = [
        Response(result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
            HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.SCHEDULED),
            HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.SCHEDULED),
            HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.SCHEDULED)
        ])))),
        Response(result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
            HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
            HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINING),
            HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINING)
        ])))),
        Response(result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
            HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINING),
            HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.DRAINED),
            HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.DRAINED)
        ])))),
        Response(result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
            HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.DRAINED)
        ]))))
    ]
    fake_maintenance_status_call_args = []
    def fake_maintenance_status_side_effect(hosts):
      fake_maintenance_status_call_args.append(copy.deepcopy(hosts))
      return fake_maintenance_status_response.pop(0)

    clock = mock.Mock(time)
    mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
    mock_maintenance_status.side_effect = fake_maintenance_status_side_effect
    test_hosts = Hosts(set(TEST_HOSTNAMES))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
    maintenance._drain_hosts(test_hosts, clock)
    mock_drain_hosts.assert_called_once_with(test_hosts)
    assert clock.sleep.call_count == 4
    assert clock.sleep.call_args == mock.call(
        HostMaintenance.START_MAINTENANCE_DELAY.as_(Time.SECONDS))
    assert mock_maintenance_status.call_count == 4
    assert fake_maintenance_status_call_args == [
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set(TEST_HOSTNAMES))),
        (Hosts(set([TEST_HOSTNAMES[0]])))]
コード例 #18
0
def test_default_grouping():
  example_host_list = [
    'xyz321.example.com',
    'bar337.example.com',
    'foo001.example.com',
  ]

  batches = list(HostMaintenance.iter_batches(example_host_list))
  assert batches[0] == Hosts(set(['bar337.example.com']))
  assert batches[1] == Hosts(set(['foo001.example.com']))
  assert batches[2] == Hosts(set(['xyz321.example.com']))
コード例 #19
0
  def test_drain_hosts_timed_out_wait(self, _, mock_drain_hosts, mock_maintenance_status):
    fake_maintenance_status_response = Response(
        responseCode=ResponseCode.OK,
        result=Result(maintenanceStatusResult=MaintenanceStatusResult(set([
          HostStatus(host=TEST_HOSTNAMES[0], mode=MaintenanceMode.SCHEDULED),
          HostStatus(host=TEST_HOSTNAMES[1], mode=MaintenanceMode.SCHEDULED),
          HostStatus(host=TEST_HOSTNAMES[2], mode=MaintenanceMode.SCHEDULED)
        ]))))

    mock_drain_hosts.return_value = Response(responseCode=ResponseCode.OK)
    mock_maintenance_status.return_value = fake_maintenance_status_response
    test_hosts = Hosts(set(TEST_HOSTNAMES))
    maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
    maintenance.MAX_STATUS_WAIT = Amount(1, Time.MILLISECONDS)

    not_drained_hostnames = maintenance._drain_hosts(test_hosts)
    assert TEST_HOSTNAMES == sorted(not_drained_hostnames)
    assert mock_maintenance_status.call_count == 1
    mock_drain_hosts.assert_called_once_with(test_hosts)
    mock_maintenance_status.assert_called_once_with((Hosts(set(TEST_HOSTNAMES))))
コード例 #20
0
def test_default_grouping():
  example_host_list = [
    'xyz321.example.com',
    'bar337.example.com',
    'foo001.example.com',
  ]

  batches = list(HostMaintenance.iter_batches(example_host_list))
  assert batches[0] == Hosts(set(['bar337.example.com']))
  assert batches[1] == Hosts(set(['foo001.example.com']))
  assert batches[2] == Hosts(set(['xyz321.example.com']))
コード例 #21
0
 def test_perform_maintenance(self, mock_operate_on_hosts, mock_check_sla, mock_start_maintenance,
                              mock_drain_hosts):
   mock_callback = mock.Mock()
   mock_check_sla.return_value = set()
   mock_start_maintenance.return_value = TEST_HOSTNAMES
   drain_hosts_results = [set() for _ in TEST_HOSTNAMES]
   drain_hosts_results[0] = set([TEST_HOSTNAMES[0]])
   def drain_hosts_result(*args):
     return drain_hosts_results.pop(0)
   mock_drain_hosts.side_effect = drain_hosts_result
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.perform_maintenance(TEST_HOSTNAMES, callback=mock_callback)
   mock_start_maintenance.assert_called_once_with(TEST_HOSTNAMES)
   assert mock_check_sla.call_count == 3
   assert mock_drain_hosts.call_count == 3
   assert mock_drain_hosts.call_args_list == [
       mock.call(Hosts(set([hostname]))) for hostname in TEST_HOSTNAMES]
   assert mock_operate_on_hosts.call_count == 3
   assert mock_operate_on_hosts.call_args_list == [mock.call(set(), mock_callback)] + [
       mock.call(set([hostname]), mock_callback) for hostname in TEST_HOSTNAMES[1:]]
コード例 #22
0
def host_status(cluster):
    """usage: host_status {--filename=filename | --hosts=hosts}
                        cluster

  Print the drain status of each supplied host.
  """
    options = app.get_options()
    checkable_hosts = parse_hostnames(options.filename, options.hosts)
    statuses = HostMaintenance(CLUSTERS[cluster],
                               options.verbosity).check_status(checkable_hosts)
    for pair in statuses:
        log.info("%s is in state: %s" % pair)
コード例 #23
0
def host_activate(cluster):
    """usage: host_activate {--filename=filename | --hosts=hosts}
                          cluster

  Removes maintenance mode from hosts.

  The list of hosts is marked as not in a drained state anymore. This will
  allow normal scheduling to resume on the given list of hosts.
  """
    options = app.get_options()
    HostMaintenance(CLUSTERS[cluster], options.verbosity).end_maintenance(
        parse_hostnames(options.filename, options.hosts))
コード例 #24
0
def host_deactivate(cluster):
    """usage: host_deactivate {--filename=filename | --hosts=hosts}
                            cluster

  Puts hosts into maintenance mode.

  The list of hosts is marked for maintenance, and will be de-prioritized
  from consideration for scheduling.  Note, they are not removed from
  consideration, and may still schedule tasks if resources are very scarce.
  Usually you would mark a larger set of machines for drain, and then do
  them in batches within the larger set, to help drained tasks not land on
  future hosts that will be drained shortly in subsequent batches.
  """
    options = app.get_options()
    HostMaintenance(CLUSTERS[cluster], options.verbosity).start_maintenance(
        parse_hostnames(options.filename, options.hosts))
コード例 #25
0
def test_rack_grouping():
  example_host_list = [
    'west-aaa-001.example.com',
    'west-aaa-002.example.com',
    'west-xyz-002.example.com',
    'east-xyz-003.example.com',
    'east-xyz-004.example.com',
  ]

  with group_by_rack():
    batches = list(HostMaintenance.iter_batches(example_host_list, 'by_rack'))
    assert batches[0] == Hosts(set([
        'west-aaa-001.example.com',
        'west-aaa-002.example.com'
    ]))
    assert batches[1] == Hosts(set([
        'west-xyz-002.example.com',
        'east-xyz-003.example.com',
        'east-xyz-004.example.com',
    ]))
コード例 #26
0
def test_rack_grouping():
  example_host_list = [
    'west-aaa-001.example.com',
    'west-aaa-002.example.com',
    'west-xyz-002.example.com',
    'east-xyz-003.example.com',
    'east-xyz-004.example.com',
  ]

  with group_by_rack():
    batches = list(HostMaintenance.iter_batches(example_host_list, 'by_rack'))
    assert batches[0] == Hosts(set([
        'west-aaa-001.example.com',
        'west-aaa-002.example.com'
    ]))
    assert batches[1] == Hosts(set([
        'west-xyz-002.example.com',
        'east-xyz-003.example.com',
        'east-xyz-004.example.com',
    ]))
コード例 #27
0
def host_drain(cluster):
    """usage: host_drain {--filename=filename | --hosts=hosts}
                       [--post_drain_script=path]
                       [--grouping=function]
                       [--override_percentage=percentage]
                       [--override_duration=duration]
                       [--override_reason=reason]
                       [--unsafe_hosts_file=unsafe_hosts_filename]
                       cluster

  Asks the scheduler to start maintenance on the list of provided hosts (see host_deactivate
  for more details) and drains any active tasks on them.

  The list of hosts is drained and marked in a drained state.  This will kill
  off any tasks currently running on these hosts, as well as prevent future
  tasks from scheduling on these hosts while they are drained.

  The hosts are left in maintenance mode upon completion. Use host_activate to
  return hosts back to service and allow scheduling tasks on them.
  """
    options = app.get_options()
    drainable_hosts = parse_hostnames(options.filename, options.hosts)
    get_grouping_or_die(options.grouping)

    override_percentage, override_duration = parse_and_validate_sla_overrides(
        options, drainable_hosts)

    post_drain_callback = parse_script(options.post_drain_script)

    drained_hostnames = HostMaintenance(
        CLUSTERS[cluster], options.verbosity).perform_maintenance(
            drainable_hosts,
            grouping_function=options.grouping,
            percentage=override_percentage,
            duration=override_duration,
            output_file=options.unsafe_hosts_filename)

    if post_drain_callback:
        for hostname in drained_hostnames:
            post_drain_callback(hostname)
コード例 #28
0
 def test_start_maintenance(self, mock_api):
   mock_api.return_value = Response(responseCode=ResponseCode.OK)
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.start_maintenance(TEST_HOSTNAMES)
   mock_api.assert_called_once_with(Hosts(set(TEST_HOSTNAMES)))
コード例 #29
0
 def test_end_maintenance(self, mock_complete_maintenance):
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.end_maintenance(TEST_HOSTNAMES)
   mock_complete_maintenance.assert_called_once_with(Hosts(set(TEST_HOSTNAMES)))
コード例 #30
0
 def test_operate_on_hosts(self):
   mock_callback = mock.Mock()
   test_hosts = Hosts(TEST_HOSTNAMES)
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance._operate_on_hosts(test_hosts, mock_callback)
   assert mock_callback.call_count == 3
コード例 #31
0
 def test_operate_on_hosts(self):
   mock_callback = mock.Mock()
   test_hosts = Hosts(TEST_HOSTNAMES)
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance._operate_on_hosts(test_hosts, mock_callback)
   assert mock_callback.call_count == 3
コード例 #32
0
 def test_start_maintenance(self, mock_api):
     mock_api.return_value = Response(responseCode=ResponseCode.OK)
     maintenance = HostMaintenance(DEFAULT_CLUSTER, "quiet")
     maintenance.start_maintenance(MOCK_TEST_HOSTS)
コード例 #33
0
 def test_end_maintenance(self, mock_complete_maintenance):
   maintenance = HostMaintenance(DEFAULT_CLUSTER, 'quiet')
   maintenance.end_maintenance(TEST_HOSTNAMES)
   mock_complete_maintenance.assert_called_once_with(Hosts(set(TEST_HOSTNAMES)))