3 from datetime
import datetime
6 from .client
import client
8 log
= logging
.getLogger(__name__
)
11 class Unit(model
.ModelEntity
):
13 def agent_status(self
):
14 """Returns the current agent status string.
17 return self
.data
['agent-status']['current']
20 def agent_status_since(self
):
21 """Get the time when the `agent_status` was last updated.
24 since
= self
.data
['agent-status']['since']
25 # Juju gives us nanoseconds, but Python only supports microseconds
27 return datetime
.strptime(since
, "%Y-%m-%dT%H:%M:%S.%f")
30 def agent_status_message(self
):
31 """Get the agent status message.
34 return self
.data
['agent-status']['message']
37 def workload_status(self
):
38 """Returns the current workload status string.
41 return self
.data
['workload-status']['current']
44 def workload_status_since(self
):
45 """Get the time when the `workload_status` was last updated.
48 since
= self
.data
['workload-status']['since']
49 # Juju gives us nanoseconds, but Python only supports microseconds
51 return datetime
.strptime(since
, "%Y-%m-%dT%H:%M:%S.%f")
54 def workload_status_message(self
):
55 """Get the workload status message.
58 return self
.data
['workload-status']['message']
60 def add_storage(self
, name
, constraints
=None):
61 """Add unit storage dynamically.
63 :param str name: Storage name, as specified by the charm
64 :param str constraints: Comma-separated list of constraints in the
65 form 'POOL,COUNT,SIZE'
70 def collect_metrics(self
):
71 """Collect metrics on this unit.
76 async def destroy(self
):
80 app_facade
= client
.ApplicationFacade()
81 app_facade
.connect(self
.connection
)
84 'Destroying %s', self
.name
)
86 return await app_facade
.DestroyUnits([self
.name
])
89 def get_resources(self
, details
=False):
90 """Return resources for this unit.
92 :param bool details: Include detailed info about resources used by each
98 def resolved(self
, retry
=False):
99 """Mark unit errors resolved.
101 :param bool retry: Re-execute failed hooks
106 async def run(self
, command
, timeout
=None):
107 """Run command on this unit.
109 :param str command: The command to run
110 :param int timeout: Time to wait before command is considered failed
112 Returns a tuple containing the stdout, stderr, and return code
116 action
= client
.ActionFacade()
117 action
.connect(self
.connection
)
120 'Running `%s` on %s', command
, self
.name
)
122 res
= await action
.Run(
129 return await self
.model
.wait_for_action(res
.results
[0].action
.tag
)
131 def run_action(self
, action_name
, **params
):
132 """Run action on this unit.
134 :param str action_name: Name of action to run
135 :param \*\*params: Action parameters
141 self
, source_path
, user
=None, destination_path
=None, proxy
=False,
143 """Transfer files to this unit.
145 :param str source_path: Path of file(s) to transfer
146 :param str user: Remote username
147 :param str destination_path: Destination of transferred files on
149 :param bool proxy: Proxy through the Juju API server
150 :param str scp_opts: Additional options to the `scp` command
155 def set_meter_status(self
):
156 """Set the meter status on this unit.
162 self
, command
, user
=None, proxy
=False, ssh_opts
=None):
163 """Execute a command over SSH on this unit.
165 :param str command: Command to execute
166 :param str user: Remote username
167 :param bool proxy: Proxy through the Juju API server
168 :param str ssh_opts: Additional options to the `ssh` command
173 def status_history(self
, num
=20, utc
=False):
174 """Get status history for this unit.
176 :param int num: Size of history backlog
177 :param bool utc: Display time as UTC in RFC3339 format
182 async def is_leader_from_status(self
):
184 Check to see if this unit is the leader. Returns True if so, and
185 False if it is not, or if leadership does not make sense
186 (e.g., there is no leader in this application.)
188 This method is a kluge that calls FullStatus in the
189 ClientFacade to get its information. Once
190 https://bugs.launchpad.net/juju/+bug/1643691 is resolved, we
191 should add a simple .is_leader property, and deprecate this
195 app
= self
.name
.split("/")[0]
197 c
= client
.ClientFacade()
198 c
.connect(self
.model
.connection
)
200 status
= await c
.FullStatus(None)
202 return status
.applications
[app
]['units'][self
.name
].get(