|
5 | 5 |
|
6 | 6 | import pyrfc3339 |
7 | 7 |
|
8 | | -from . import model, tag, utils |
| 8 | +from . import model, tag |
9 | 9 | from .annotationhelper import _get_annotations, _set_annotations |
10 | 10 | from .client import client |
11 | 11 | from .errors import JujuError |
|
16 | 16 | class Machine(model.ModelEntity): |
17 | 17 | def __init__(self, *args, **kwargs): |
18 | 18 | super().__init__(*args, **kwargs) |
19 | | - self.model.loop.create_task(self._queue_workarounds()) |
20 | | - |
21 | | - async def _queue_workarounds(self): |
22 | | - model = self.model |
23 | | - if not model.info: |
24 | | - await utils.run_with_interrupt(model.get_info(), |
25 | | - model._watch_stopping, |
26 | | - loop=model.loop) |
27 | | - if model._watch_stopping.is_set(): |
28 | | - return |
29 | | - if model.info.agent_version < client.Number.from_json('2.2.3'): |
30 | | - self.on_change(self._workaround_1695335) |
31 | | - |
32 | | - async def _workaround_1695335(self, delta, old, new, model): |
33 | | - """ |
34 | | - This is a (hacky) temporary work around for a bug in Juju where the |
35 | | - instance status and agent version fields don't get updated properly |
36 | | - by the AllWatcher. |
37 | | -
|
38 | | - Deltas never contain a value for `data['agent-status']['version']`, |
39 | | - and once the `instance-status` reaches `pending`, we no longer get |
40 | | - any updates for it (the deltas come in, but the `instance-status` |
41 | | - data is always the same after that). |
42 | | -
|
43 | | - To work around this, whenever a delta comes in for this machine, we |
44 | | - query FullStatus and use the data from there if and only if it's newer. |
45 | | - Luckily, the timestamps on the `since` field does seem to be accurate. |
46 | | -
|
47 | | - See https://bugs.launchpad.net/juju/+bug/1695335 |
48 | | -
|
49 | | - NOTE: this was fixed in 2.2.3 and 2.3-beta1. |
50 | | - """ |
51 | | - if delta.data.get('synthetic', False): |
52 | | - # prevent infinite loops re-processing already processed deltas |
53 | | - return |
54 | | - |
55 | | - full_status = await utils.run_with_interrupt(model.get_status(), |
56 | | - model._watch_stopping, |
57 | | - loop=model.loop) |
58 | | - if model._watch_stopping.is_set(): |
59 | | - return |
60 | | - |
61 | | - if self.id not in full_status.machines: |
62 | | - return |
63 | | - |
64 | | - if not full_status.machines[self.id]['instance-status']['since']: |
65 | | - return |
66 | | - |
67 | | - machine = full_status.machines[self.id] |
68 | | - |
69 | | - change_log = [] |
70 | | - key_map = { |
71 | | - 'status': 'current', |
72 | | - 'info': 'message', |
73 | | - 'since': 'since', |
74 | | - } |
75 | | - |
76 | | - # handle agent version specially, because it's never set in |
77 | | - # deltas, and we don't want even a newer delta to clear it |
78 | | - agent_version = machine['agent-status']['version'] |
79 | | - if agent_version: |
80 | | - delta.data['agent-status']['version'] = agent_version |
81 | | - change_log.append(('agent-version', '', agent_version)) |
82 | | - |
83 | | - # only update (other) delta fields if status data is newer |
84 | | - status_since = pyrfc3339.parse(machine['instance-status']['since']) |
85 | | - delta_since = pyrfc3339.parse(delta.data['instance-status']['since']) |
86 | | - if status_since > delta_since: |
87 | | - for status_key in ('status', 'info', 'since'): |
88 | | - delta_key = key_map[status_key] |
89 | | - status_value = machine['instance-status'][status_key] |
90 | | - delta_value = delta.data['instance-status'][delta_key] |
91 | | - change_log.append((delta_key, delta_value, status_value)) |
92 | | - delta.data['instance-status'][delta_key] = status_value |
93 | | - |
94 | | - if change_log: |
95 | | - log.debug('Overriding machine delta with FullStatus data') |
96 | | - for log_item in change_log: |
97 | | - log.debug(' {}: {} -> {}'.format(*log_item)) |
98 | | - delta.data['synthetic'] = True |
99 | | - old_obj, new_obj = self.model.state.apply_delta(delta) |
100 | | - await model._notify_observers(delta, old_obj, new_obj) |
101 | 19 |
|
102 | 20 | async def destroy(self, force=False): |
103 | 21 | """Remove this machine from the model. |
|
0 commit comments