Merge lp:~kim0/pyjuju/user-tutorial-and-FAQ into lp:pyjuju
- user-tutorial-and-FAQ
- Merge into trunk
Proposed by
Ahmed Kamal
Status: | Merged |
---|---|
Approved by: | Gustavo Niemeyer |
Approved revision: | 206 |
Merged at revision: | 220 |
Proposed branch: | lp:~kim0/pyjuju/user-tutorial-and-FAQ |
Merge into: | lp:pyjuju |
Diff against target: |
396 lines (+375/-0) 3 files modified
docs/source/faq.rst (+49/-0) docs/source/index.rst (+2/-0) docs/source/user-tutorial.rst (+324/-0) |
To merge this branch: | bzr merge lp:~kim0/pyjuju/user-tutorial-and-FAQ |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Niemeyer | Approve | ||
Review via email: mp+58861@code.launchpad.net |
Commit message
Description of the change
Added user level tutorial
Started a FAQ document
To post a comment you must log in.
- 207. By Ahmed Kamal
-
Applying merge 58861 comments, text cleanups
Revision history for this message
Ahmed Kamal (kim0) wrote : | # |
Thanks! I've applied your comments and pushed
- 208. By Ahmed Kamal
-
Adding project resources and contact info
- 209. By Ahmed Kamal
-
Aligning at two leading spaces
- 210. By Ahmed Kamal
-
Fixing typo, title underline too short
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added file 'docs/source/faq.rst' |
2 | --- docs/source/faq.rst 1970-01-01 00:00:00 +0000 |
3 | +++ docs/source/faq.rst 2011-05-05 13:46:31 +0000 |
4 | @@ -0,0 +1,49 @@ |
5 | +Frequently Asked Questions |
6 | +========================== |
7 | + |
8 | +Where does the name Ensemble come from? |
9 | + |
10 | + The word ensemble could be defined as "an assemblage of parts or details |
11 | + (as in a work of art) considered as forming a whole". Ensemble assembles |
12 | + machines and software components and manages them as a whole, providing |
13 | + service deployment and management, hence the name. |
14 | + |
15 | +Why is Ensemble useful? |
16 | + |
17 | + Ensemble is a next generation service deployment and orchestration |
18 | + framework. It has been likened to APT for the cloud. With Ensemble, |
19 | + different authors are able to create service formulas independently, and |
20 | + make those services coordinate their communication through a simple |
21 | + protocol. Users can then take the product of different authors and very |
22 | + comfortably deploy those services in an environment. The result is |
23 | + multiple machines and components transparently collaborating towards |
24 | + providing the requested service. Read more :doc:`about` |
25 | + |
26 | +When will it be ready for production? |
27 | + |
28 | + As of Ubuntu Natty 11.04, Ensemble is a technology preview. It is not yet |
29 | + ready to be used in production. However, adventurous users are encouraged to |
30 | + evaluate it, study it, start writing formulas for it or start hacking on |
31 | + Ensemble internals. The rough roadmap is to have Ensemble packaged for |
32 | + Universe by 11.10 release and perhaps in main by 12.04 |
33 | + |
34 | +What language is Ensemble developed in? |
35 | + |
36 | + Ensemble itself is developed using python. However, writing formulas for |
37 | + Ensemble can be done in any language. All Ensemble cares about is finding a |
38 | + set of executable files, which it will trigger appropriately. |
39 | + |
40 | +How can I contact the Ensemble team? |
41 | + |
42 | + User and formula author oriented resources |
43 | + * Mailing list: https://lists.ubuntu.com/mailman/listinfo/Ubuntu-cloud |
44 | + * IRC #ubuntu-cloud |
45 | + Ensemble development |
46 | + * Mailing list: https://lists.ubuntu.com/mailman/listinfo/Ensemble |
47 | + * IRC #ubuntu-ensemble |
48 | + |
49 | +Where can I find out more about Ensemble? |
50 | + |
51 | + * Project Site: https://launchpad.net/ensemble |
52 | + * Ensemble Documentation: http://j.mp/ensemble-docs |
53 | + * Work Items: http://people.canonical.com/~niemeyer/budapest.html |
54 | |
55 | === modified file 'docs/source/index.rst' |
56 | --- docs/source/index.rst 2011-05-05 09:41:11 +0000 |
57 | +++ docs/source/index.rst 2011-05-05 13:46:31 +0000 |
58 | @@ -10,7 +10,9 @@ |
59 | :maxdepth: 2 |
60 | |
61 | about |
62 | + faq |
63 | getting-started |
64 | + user-tutorial |
65 | formula |
66 | hook-debugging |
67 | upgrades |
68 | |
69 | === added file 'docs/source/user-tutorial.rst' |
70 | --- docs/source/user-tutorial.rst 1970-01-01 00:00:00 +0000 |
71 | +++ docs/source/user-tutorial.rst 2011-05-05 13:46:31 +0000 |
72 | @@ -0,0 +1,324 @@ |
73 | +.. _user-tutorial: |
74 | + |
75 | +User tutorial |
76 | +============= |
77 | + |
78 | +Introduction |
79 | +------------ |
80 | + |
81 | +This tutorial demonstrates basic features of Ensemble from a user perspective. |
82 | +An Ensemble user would typically be a devops or a sys-admin who is interested in |
83 | +automated deployment and management of servers and services. |
84 | + |
85 | +Bootstrapping |
86 | +------------- |
87 | + |
88 | +The first step for deploying an Ensemble system is to perform bootstrapping. |
89 | +Bootstrapping launches a utility instance that is used in all subsequent |
90 | +operations to launch and orchestrate other instances:: |
91 | + |
92 | + $ bin/ensemble bootstrap |
93 | + |
94 | +Note that while the command should display a message indicating it has finished |
95 | +successfully, that does not mean the bootstrapping instance is immediately |
96 | +ready for usage. Bootstrapping an instance can require a couple of minutes. To |
97 | +check on the status of the Ensemble deployment, we can use the status command:: |
98 | + |
99 | + $ bin/ensemble status |
100 | + |
101 | +If the bootstrapping node has not yet completed bootstrapping, the status |
102 | +command may either mention the environment is not yet ready, or may display a |
103 | +connection timeout such as:: |
104 | + |
105 | + INFO Connecting to environment. |
106 | + ERROR Connection refused |
107 | + ProviderError: Interaction with machine provider failed: |
108 | + ConnectionTimeoutException('could not connect before timeout after 2 |
109 | + retries',) |
110 | + ERROR ProviderError: Interaction with machine |
111 | + provider failed: ConnectionTimeoutException('could not connect before timeout |
112 | + after 2 retries',) |
113 | + |
114 | +This is simply an indication the environment needs more time to complete |
115 | +initialization. It is recommended you retry every minute. Once the environment |
116 | +has properly initialized, the status command should display:: |
117 | + |
118 | + machines: |
119 | + 0: {dns-name: ec2-50-16-61-111.compute-1.amazonaws.com, instance-id: i-2a702745} |
120 | + services: {} |
121 | + |
122 | +Note the following, machine "0" has been started. This is the bootstrapping |
123 | +node and the first node to be started. The dns-name for the node is printed. |
124 | +Also the EC2 instance-id is printed. Since no services are yet deployed to the |
125 | +Ensemble system yet, the list of deployed services is empty |
126 | + |
127 | +Starting debug-log |
128 | +------------------ |
129 | + |
130 | +While not a requirement, it is beneficial for the understanding of Ensemble to |
131 | +start a debug-log session. Ensemble's debug-log provides great insight into the |
132 | +execution of various hooks as they are triggered by various events. It is |
133 | +important to understand that debug-log shows events from a distributed |
134 | +environment (multiple-instances). This means that log lines will alternate |
135 | +between output from different instances. To start a debug-log session, from a |
136 | +secondary terminal issue:: |
137 | + |
138 | + $ bin/ensemble debug-log |
139 | + INFO Connecting to environment. |
140 | + INFO Enabling distributed debug log. |
141 | + INFO Tailing logs - Ctrl-C to stop. |
142 | + |
143 | +This will connect to the environment, and start tailing logs. |
144 | + |
145 | +Deploying service units |
146 | +----------------------- |
147 | + |
148 | +Now that we have bootstrapped the Ensemble environment, and started the |
149 | +debug-log viewer, let's proceed by deploying a mysql service:: |
150 | + |
151 | + $ bin/ensemble deploy --repository=examples mysql |
152 | + INFO Connecting to environment. |
153 | + INFO Formula deployed as service: 'mysql' |
154 | + INFO 'deploy' command finished successfully |
155 | + |
156 | +Checking the debug-log window, we can see the mysql service unit being |
157 | +downloaded and started:: |
158 | + |
159 | + Machine:1: ensemble.agents.machine DEBUG: Downloading formula |
160 | + local:mysql-11... |
161 | + Machine:1: ensemble.agents.machine INFO: Started service unit mysql/0 |
162 | + |
163 | +It is important to note the different debug levels. DEBUG is used for very |
164 | +detailed logging messages, usually you should not care about reading such |
165 | +messages unless you are trying to debug (hence the name) a specific problem. |
166 | +INFO debugging level is used for slightly more important informational |
167 | +messages. In this case, these messages are generated as the mysql formula's |
168 | +hooks are being executed. Let's check the current status:: |
169 | + |
170 | + $ bin/ensemble status |
171 | + machines: |
172 | + 0: {dns-name: ec2-50-16-61-111.compute-1.amazonaws.com, instance-id: i-2a702745} |
173 | + 1: {dns-name: ec2-50-16-117-185.compute-1.amazonaws.com, instance-id: i-227e294d} |
174 | + services: |
175 | + mysql: |
176 | + formula: local:mysql-11 |
177 | + relations: {} |
178 | + units: |
179 | + mysql/0: |
180 | + machine: 1 |
181 | + relations: {} |
182 | + state: null |
183 | + |
184 | +We can see a new EC2 instance has now been spun up for mysql. Information for |
185 | +this instance is displayed as machine number 1 and mysql is now listed under |
186 | +services. It is apparent the mysql service unit has no relations, since it has |
187 | +not been connected to wordpress yet. Since this is the first mysql service |
188 | +unit, it is being referred to as mysql/0, subsequent service units would be |
189 | +named mysql/1 and so on. |
190 | + |
191 | +.. note:: |
192 | + An important distinction to make is the difference between a service |
193 | + and a service unit. A service is a high level concept relating to an |
194 | + end-user visible service such as mysql. The mysql service would be |
195 | + composed of several mysql service units referred to as mysql/0, mysql/1 |
196 | + and so on. |
197 | + |
198 | +The mysql service state is listed as null since it's not ready yet. |
199 | +Downloading, installing, configuring and starting mysql can take some time. |
200 | +However we don't have to wait for it to configure, let's proceed deploying |
201 | +wordpress:: |
202 | + |
203 | + $ bin/ensemble deploy --repository=examples wordpress |
204 | + |
205 | +Let's wait for a minute for all services to complete their configuration cycle and |
206 | +get properly started, then issue a status command:: |
207 | + |
208 | + $ bin/ensemble status |
209 | + machines: |
210 | + 0: {dns-name: ec2-50-16-61-111.compute-1.amazonaws.com, instance-id: i-2a702745} |
211 | + 1: {dns-name: ec2-50-16-117-185.compute-1.amazonaws.com, instance-id: i-227e294d} |
212 | + 2: {dns-name: ec2-184-72-156-54.compute-1.amazonaws.com, instance-id: i-9c7e29f3} |
213 | + services: |
214 | + mysql: |
215 | + formula: local:mysql-11 |
216 | + relations: {} |
217 | + units: |
218 | + mysql/0: |
219 | + machine: 1 |
220 | + relations: {} |
221 | + state: started |
222 | + wordpress: |
223 | + formula: local:wordpress-29 |
224 | + relations: {} |
225 | + units: |
226 | + wordpress/0: |
227 | + machine: 2 |
228 | + relations: {} |
229 | + state: started |
230 | + |
231 | +mysql/0 as well as wordpress/0 are both now in the started state. Checking the |
232 | +debug-log would reveal wordpress has been started as well |
233 | + |
234 | +Adding a relation |
235 | +----------------- |
236 | + |
237 | +While mysql and wordpress service units have been started, they are still |
238 | +isolated from each other. An important concept for Ensemble is connecting |
239 | +various service units together to create a bigger ensemble! Adding a relation |
240 | +between service units causes hooks to trigger, in effect causing all service |
241 | +units to collaborate and work together to reach the desired end state. Adding a |
242 | +relation is extremely simple:: |
243 | + |
244 | + $ bin/ensemble add-relation wordpress mysql |
245 | + INFO Connecting to environment. |
246 | + INFO Added mysql relation to all service units. |
247 | + INFO 'add_relation' command finished successfully |
248 | + |
249 | +Checking the Ensemble status we see that the db relation now exists with state |
250 | +up:: |
251 | + |
252 | + $ bin/ensemble status |
253 | + machines: |
254 | + 0: {dns-name: ec2-50-16-61-111.compute-1.amazonaws.com, instance-id: i-2a702745} |
255 | + 1: {dns-name: ec2-50-16-117-185.compute-1.amazonaws.com, instance-id: i-227e294d} |
256 | + 2: {dns-name: ec2-184-72-156-54.compute-1.amazonaws.com, instance-id: i-9c7e29f3} |
257 | + services: |
258 | + mysql: |
259 | + formula: local:mysql-11 |
260 | + relations: {db: wordpress} |
261 | + units: |
262 | + mysql/0: |
263 | + machine: 1 |
264 | + relations: |
265 | + db: {state: up} |
266 | + state: started |
267 | + wordpress: |
268 | + formula: local:wordpress-29 |
269 | + relations: {db: mysql} |
270 | + units: |
271 | + wordpress/0: |
272 | + machine: 2 |
273 | + relations: |
274 | + db: {state: up} |
275 | + state: started |
276 | + |
277 | +You can now point your browser at the public dns-name for instance 2 (running |
278 | +wordpress) to view the wordpress blog |
279 | + |
280 | +Tracing hook execution |
281 | +---------------------- |
282 | + |
283 | +An Ensemble user should never have to trace the execution order of hooks, |
284 | +however if you are the kind of person who enjoys looking under the hood, this |
285 | +section is for you. Understanding hook order execution, the parallel nature of |
286 | +hook execution across instances, and how relation-set in a hook can trigger the |
287 | +execution of another hook is quite interesting and provides insight into |
288 | +Ensemble internals |
289 | + |
290 | +Here are a few important messages from the debug-log of this Ensemble run. The |
291 | +date field has been deliberately left in this log, in order to understand the |
292 | +parallel nature of hook execution. |
293 | + |
294 | +Things to consider while reading the log include: |
295 | + * The time the log message was generated |
296 | + * Which service unit is causing the log message (for example mysql/0) |
297 | + * The message logging level. In this run DEBUG messages are generated by the |
298 | + Ensemble core engine, while WARNING messages are generated by calling |
299 | + ensemble-log from inside formulas (which you can read in the examples |
300 | + folder) |
301 | + |
302 | +Let's view select debug-log messages which can help understand the execution |
303 | +order:: |
304 | + |
305 | + 14:29:43,625 unit:mysql/0: hook.scheduler DEBUG: executing hook for wordpress/0:joined |
306 | + 14:29:43,626 unit:mysql/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-joined |
307 | + 14:29:43,660 unit:wordpress/0: hook.scheduler DEBUG: executing hook for mysql/0:joined |
308 | + 14:29:43,660 unit:wordpress/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-joined |
309 | + 14:29:43,661 unit:wordpress/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-changed |
310 | + 14:29:43,789 unit:mysql/0: unit.hook.api WARNING: Creating new database and corresponding security settings |
311 | + 14:29:43,813 unit:wordpress/0: unit.hook.api WARNING: Retrieved hostname: ec2-184-72-156-54.compute-1.amazonaws.com |
312 | + 14:29:43,976 unit:mysql/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-changed |
313 | + 14:29:43,997 unit:wordpress/0: hook.scheduler DEBUG: executing hook for mysql/0:modified |
314 | + 14:29:43,997 unit:wordpress/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-changed |
315 | + 14:29:44,143 unit:wordpress/0: unit.hook.api WARNING: Retrieved hostname: ec2-184-72-156-54.compute-1.amazonaws.com |
316 | + 14:29:44,849 unit:wordpress/0: unit.hook.api WARNING: Creating appropriate upload paths and directories |
317 | + 14:29:44,992 unit:wordpress/0: unit.hook.api WARNING: Writing wordpress config file /etc/wordpress/config-ec2-184-72-156-54.compute-1.amazonaws.com.php |
318 | + 14:29:45,130 unit:wordpress/0: unit.hook.api WARNING: Writing apache config file /etc/apache2/sites-available/ec2-184-72-156-54.compute-1.amazonaws.com |
319 | + 14:29:45,301 unit:wordpress/0: unit.hook.api WARNING: Enabling apache modules: rewrite, vhost_alias |
320 | + 14:29:45,512 unit:wordpress/0: unit.hook.api WARNING: Enabling apache site: ec2-184-72-156-54.compute-1.amazonaws.com |
321 | + 14:29:45,688 unit:wordpress/0: unit.hook.api WARNING: Restarting apache2 service |
322 | + |
323 | + |
324 | +Scaling the ensemble |
325 | +-------------------- |
326 | + |
327 | +Assuming your blog got really popular, is having high load and you decided to |
328 | +scale it up (it's a cloud deployment after all). Ensemble makes this magically |
329 | +easy. All what is needed is:: |
330 | + |
331 | + $ bin/ensemble add-unit wordpress |
332 | + INFO Connecting to environment. |
333 | + INFO Unit 'wordpress/1' added to service 'wordpress' |
334 | + INFO 'add_unit' command finished successfully |
335 | + $ bin/ensemble status |
336 | + machines: |
337 | + 0: {dns-name: ec2-50-16-61-111.compute-1.amazonaws.com, instance-id: i-2a702745} |
338 | + 1: {dns-name: ec2-50-16-117-185.compute-1.amazonaws.com, instance-id: i-227e294d} |
339 | + 2: {dns-name: ec2-184-72-156-54.compute-1.amazonaws.com, instance-id: i-9c7e29f3} |
340 | + 3: {dns-name: ec2-50-16-156-106.compute-1.amazonaws.com, instance-id: i-ba6532d5} |
341 | + services: |
342 | + mysql: |
343 | + formula: local:mysql-11 |
344 | + relations: {db: wordpress} |
345 | + units: |
346 | + mysql/0: |
347 | + machine: 1 |
348 | + relations: |
349 | + db: {state: up} |
350 | + state: started |
351 | + wordpress: |
352 | + formula: local:wordpress-29 |
353 | + relations: {db: mysql} |
354 | + units: |
355 | + wordpress/0: |
356 | + machine: 2 |
357 | + relations: |
358 | + db: {state: up} |
359 | + state: started |
360 | + wordpress/1: |
361 | + machine: 3 |
362 | + relations: |
363 | + db: {state: up} |
364 | + state: started |
365 | + |
366 | + |
367 | +The add-unit command starts a new wordpress instance (wordpress/1), which then |
368 | +joins the relation with the already existing mysql/0 instance. mysql/0 notices |
369 | +the database required has already been created and thus decides all needed |
370 | +configuration has already been done. On the other hand wordpress/1 reads |
371 | +service settings from mysql/0 and starts configuring itself and joining the |
372 | +ensemble. Let's review a short version of debug-log for adding wordpress/1:: |
373 | + |
374 | + 14:36:19,755 unit:mysql/0: hook.scheduler DEBUG: executing hook for wordpress/1:joined |
375 | + 14:36:19,755 unit:mysql/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-joined |
376 | + 14:36:19,810 unit:wordpress/1: hook.scheduler DEBUG: executing hook for mysql/0:joined |
377 | + 14:36:19,811 unit:wordpress/1: unit.relation.lifecycle DEBUG: Executing hook db-relation-joined |
378 | + 14:36:19,811 unit:wordpress/1: unit.relation.lifecycle DEBUG: Executing hook db-relation-changed |
379 | + 14:36:19,918 unit:mysql/0: unit.hook.api WARNING: Database already exists, exiting |
380 | + 14:36:19,938 unit:mysql/0: unit.relation.lifecycle DEBUG: Executing hook db-relation-changed |
381 | + 14:36:19,990 unit:wordpress/1: unit.hook.api WARNING: Retrieved hostname: ec2-50-16-156-106.compute-1.amazonaws.com |
382 | + 14:36:20,757 unit:wordpress/1: unit.hook.api WARNING: Creating appropriate upload paths and directories |
383 | + 14:36:20,916 unit:wordpress/1: unit.hook.api WARNING: Writing wordpress config file /etc/wordpress/config-ec2-50-16-156-106.compute-1.amazonaws.com.php |
384 | + 14:36:21,088 unit:wordpress/1: unit.hook.api WARNING: Writing apache config file /etc/apache2/sites-available/ec2-50-16-156-106.compute-1.amazonaws.com |
385 | + 14:36:21,236 unit:wordpress/1: unit.hook.api WARNING: Enabling apache modules: rewrite, vhost_alias |
386 | + 14:36:21,476 unit:wordpress/1: unit.hook.api WARNING: Enabling apache site: ec2-50-16-156-106.compute-1.amazonaws.com |
387 | + 14:36:21,682 unit:wordpress/1: unit.hook.api WARNING: Restarting apache2 service |
388 | + |
389 | +Destroying the environment |
390 | +-------------------------- |
391 | + |
392 | +Once you are done with an Ensemble deployment, you need to terminate all |
393 | +running instances in order to stop paying for them. The shutdown command helps |
394 | +terminate all running instances:: |
395 | + |
396 | + $ bin/ensemble shutdown |
Wow, this is *awesome* Ahmed. Thanks a lot!
I have several minor nits only due to the doc size, but it's indeed very
good overall.
Would you mind to check these out and let me know what you think?
[1]
+User Tutorial
Can you please lowercase the "Tutorial"? We had casing mixed up, and since the last doc
polishing I'm trying to have all documents standardizing around "Title case", so that
we have some consistency there.
[2]
10 + The name Ensemble is rooted in group communication systems and paxos, where
The Ensemble term actually comes from the meaning of the "ensemble" word itself:
"an assemblage of parts or details (as in a work of art) considered as forming a whole"
[3]
+ servers. Another way to look at it, is that Ensemble helps you manage an
s/,//
[4]
+ make those services communicate through a simple protocol. Users can then
s/communicate/ coordinate their communication/
[5]
+ ready to be used in production. However adventerous users are encouraged to
s/However /However, /
s/adventerous/ adventurous/
[6]
+ Ensemble itself is developed using python. However writing formulas for
s/However /However, /
[7]
37 + Ensemble can be done in any language. All Ensemble cares about is finding a
38 + set of executable files, which it will trigger appropriately. Hooks can be
39 + written in a variety of languages such as bash, python, perl, c++ and
40 + others
Might be better to end the paragraph in "appropriately.". It already said it
can be written in *any* language, so there's no need to give examples.
[8]
109 +Note the following, machine "0" has been started. This is usually the
110 +bootstrapping node and the first node to be started. The dns-name for the node
s/usually//, both affirmations are necessarily true.
[9]
+is printed. Also the ec2 instance-id is printed. Since no services are yet
s/ec2/EC2/
[10]
+This will connect to the environment, and start tailing logs
s/logs/logs./
[11]
+Deploying Service Units
s/S/s/ and s/U/u/, same as [1].
[12]
+We can see a new ec2 instance has now been spun up for mysql. Information for
s/ec2/EC2/
[13]
171 +We can see a new ec2 instance has now been spun up for mysql. Information for
172 +this instance is displayed as machine number 1. Mysql is now listed under
173 +services, it is apparent the mysql service unit has no relations, since it
Minor sentence refactoring:
We can see a new ec2 instance has now been spun up for mysql. Information for
this instance is displayed as machine number 1 and mysql is now listed under
services. It is apparent that the mysql service unit has no relations, since it
[14]
174 +has not been connected to wordpress yet. Since this is the first mysql service
175 +unit, it is being referred to as mysql/0, subsequent service units would be
It would be nice to mention here, even if very briefly, the distinction between a
service and a service unit.
[15]
183 +Waiting a minute for all services to complete their configuration cycle and
184 +get properly started, then issuing a status command::
s/Waiting a/Let's wait for a/
s/then issuing/then issue/
[16]
+Adding Relation
=> "Adding a relation"
[17]...