huangcm
2025-02-24 69ed55dec4b2116a19e4cca4393cbc014fce5fb2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
UP_SQL = """
CREATE UNIQUE INDEX host_queue_entries_job_id_and_host_id
ON host_queue_entries (job_id, host_id);
 
DROP INDEX host_queue_entries_job_id ON host_queue_entries;
"""
 
 
DOWN_SQL = """
CREATE INDEX host_queue_entries_job_id ON host_queue_entries (job_id);
 
DROP INDEX host_queue_entries_job_id_and_host_id ON host_queue_entries;
"""
 
 
def null_out_duplicate_hqes(manager, hqe_ids):
    if not hqe_ids:
        return
    ids_to_null_string = ','.join(str(hqe_id) for hqe_id in hqe_ids)
 
    # check if any of the HQEs we're going to null out are active. if so, it's
    # too dangerous to proceed.
    rows = manager.execute('SELECT id FROM host_queue_entries '
                           'WHERE active AND id IN (%s)' % ids_to_null_string)
    if rows:
        raise Exception('Active duplicate HQEs exist, cannot proceed.  Please '
                        'manually abort these HQE IDs: %s' % ids_to_null_string)
 
    # go ahead and null them out
    print 'Nulling out duplicate HQE IDs: %s' % ids_to_null_string
    manager.execute('UPDATE host_queue_entries '
                    'SET host_id = NULL, active = FALSE, complete = TRUE, '
                    'aborted = TRUE, status = "Aborted" '
                    'WHERE id IN (%s)' % ids_to_null_string)
 
 
def migrate_up(manager):
    # cleanup duplicate host_queue_entries. rather than deleting them (and
    # dealing with foreign key references), we'll just null out their host_ids
    # and set them to aborted.
    rows = manager.execute('SELECT GROUP_CONCAT(id), COUNT(1) AS count '
                           'FROM host_queue_entries '
                           'WHERE host_id IS NOT NULL '
                           'GROUP BY job_id, host_id HAVING count > 1')
    # gather all the HQE IDs we want to null out
    ids_to_null = []
    for ids_string, _ in rows:
        id_list = ids_string.split(',')
        # null out all but the first one.  this isn't terribly important, but
        # the first one is the most likely to have actually executed, so might
        # as well keep that one.
        ids_to_null.extend(id_list[1:])
 
    null_out_duplicate_hqes(manager, ids_to_null)
 
    manager.execute_script(UP_SQL)