Differences
This shows you the differences between two versions of the page.
Next revision | Previous revision | ||
redhat:openshift-redhat:dailybusiness-openshift [2019/02/11 16:41] – created michael | redhat:openshift-redhat:dailybusiness-openshift [2020/12/10 14:07] (current) – michael | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== Daily Business mit OpenShift ====== | ====== Daily Business mit OpenShift ====== | ||
+ | |||
===== Cluster User Administration ===== | ===== Cluster User Administration ===== | ||
- | Cluster-Admins | + | <WRAP center box 100%> |
+ | ==== Cluster-Admins | ||
Um einem Benutzer cluster-admin Rechte auf der Plattform zu vergeben, müssen folgende Schritte beachtet werden: | Um einem Benutzer cluster-admin Rechte auf der Plattform zu vergeben, müssen folgende Schritte beachtet werden: | ||
- | + | - Einloggen mit einem Benutzer, welcher bereits cluster-admin Rechte besitzt | |
- | 1. Einloggen mit einem Benutzer, welcher bereits cluster-admin Rechte besitzt | + | |
- | + | ||
- | 2. Auflisten der berechtigten Benutzer der Rolle cluster-admin | + | |
- | + | ||
- | [root@vip3cd ~]# oc get clusterrolebinding | grep cluster-admin | + | |
... | ... | ||
cluster-admin | cluster-admin | ||
... | ... | ||
+ | </ | ||
+ | - Benutzer berechtigen < | ||
+ | * Benutzer wieder entfernen < | ||
+ | </ | ||
- | 3 Benutzer berechtigen | ||
- | [root@vip3cd ~]# oc adm policy add-cluster-role-to-group cluster-admin [group] | + | <WRAP center box 100%> |
+ | ==== Benutzer zu einem Projekt hinzufügen ==== | ||
- | |||
- | Benutzer wieder entfernen | ||
- | |||
- | [root@vip3cd ~]# oc adm policy remove-cluster-role-to-group cluster-admin [group] | ||
- | |||
- | |||
- | Benutzer zu Projekt hinzufügen | ||
Es gibt zwei verschiedene Arten, um einen Benutzer an einem Projekt zu berechtigen. | Es gibt zwei verschiedene Arten, um einen Benutzer an einem Projekt zu berechtigen. | ||
Die drei meist verwendeten Berechtigungsvarianten sind folgende: admin, edit, view | Die drei meist verwendeten Berechtigungsvarianten sind folgende: admin, edit, view | ||
- | |||
Die erste Art wäre um GUI beim entsprechenden Projekt auf "View Membership" | Die erste Art wäre um GUI beim entsprechenden Projekt auf "View Membership" | ||
- | |||
Die zweite Art wäre via Command Line den Benutzer auf ein Projekt zu berechtigen: | Die zweite Art wäre via Command Line den Benutzer auf ein Projekt zu berechtigen: | ||
- | [root@vip3cd ~]# oc policy -n [Projekt] add-role-to-user [Rolle] [Benutzer] | + | < |
+ | ---- | ||
- | Projektberechtigungen anzeigen | + | **Projekt |
- | Die Berechtigungen | + | |
- | [root@vosm01 ~]$ oc get rolebindings -n integration-service | + | Die Berechtigungen können entweder über das GUI unter "View Membership" |
+ | < | ||
+ | Link zur Dokumentation: | ||
+ | </ | ||
- | Link zur Dokumentation: | + | ===== Cluster Project Administration ===== |
+ | <WRAP center box 100%> | ||
+ | ==== Set Timeout on OpenShift route ==== | ||
+ | Jenkins has some pages, like the system configuration or the plugin overview, that take up to a minute for displaying. With the default settings on the OpenShift reverse proxy the request will be canceled after several seconds. You may set a new timeout on the route for your Jenkins instance to wait for the page to load: | ||
- | Gluster PV Administration (obsolete, neu mit heketi) | + | < |
+ | If a minute is not enough to load the page feel free to set the value higher. | ||
+ | </ | ||
- | Gluster PVs erstellen (obsolete) | ||
- | Um ein neues PV zu erstellen, muss als erstes berücksichtig werden, ob genügen Platz zur Verfügung steht. | ||
- | Folgender Ansible Befehl kann hierfür verwendet werden: | + | ===== Cluster Administration ===== |
- | ansible gluster -m shell -a "vgs | grep vg_gluster" | ||
- | Wenn genügend Platz zur Verfügung steht, muss das Hostfile der jeweiligen Plattform angepasst werden: | ||
- | [root@vosm01 ~]# cd / | + | ===== Cluster Debugging ===== |
- | [root@vosm01 openshift-hostfiles]# | + | |
- | Anschliessend im Hostfile das neue PV am Ende des Abschnittes " | + | <WRAP center box 100%> |
+ | ==== Kube Config wiederherstellen ==== | ||
- | ... | + | Funktioniert der '' |
- | gluster_pvs: | + | |
- | - name: gluster-pv1 | + | |
- | options: | + | |
- | performance.write-behind-window-size: | + | |
- | size: 100 | + | |
- | - name: gluster-pv2 | + | |
- | options: | + | |
- | cluster.consistent-metadata: 'on' | + | |
- | cluster.post-op-delay-secs: | + | |
- | size: 50 | + | |
- | ... | + | |
- | - name: gluster-pv42 | + | |
- | size: 40 | + | |
- | - name: gluster-pv43 | + | |
- | size: 10 | + | |
- | - name: NEW GLUSTER PW | + | |
- | size: NEW PV SIZE | + | |
- | ... | + | |
+ | < | ||
+ | </ | ||
- | Nun kann das Playbook main.yml im Verzeichnis / | ||
- | [root@vosm01 ~]# cd / | + | <WRAP center box 100%> |
- | [root@vosm01 ~]# ansible-playbook --check main.yml | + | ==== Kube Config wiederherstellen ==== |
+ | Funktioniert der '' | ||
- | Nachdem der Check durchgelaufen ist (mit Fehler, da die Änderungen nicht gemacht wurden und so das PV so nicht gefunden wurde) kann das Playbook ohne das --check ausgeführt werden: | + | < |
+ | </ | ||
- | [root@vosm01 ~]# cd / | ||
- | [root@vosm01 ~]# ansible-playbook main.yml | ||
- | Zum Schluss muss noch überprüft werden, ob das PV tatsächlich angelegt wurde: | ||
- | [root@vosm01 ~]# oc get pv | grep CREATED GLUSTER-PV | + | ===== Firmenspezifische Doku's ===== |
+ | <WRAP center box 100%> | ||
+ | ==== Ressourcen von einem Projekt wiederherstellen ==== | ||
- | Gluster PVs vergrössern (obsolete) | ||
- | An OpenShift GlusterFS PV can be online resized, increased in size. This needs to be done on the OpenShift master node. | ||
- | These are the steps: | + | Bei der Post läuft täglich um 24:00 ein cronjob, der alle wichtigen Projekt-Ressourcen täglich exportiert: |
- | Edit the Ansible Inventory file and set the new size of the pv. Push the changes also to gitit.pnet.ch | + | <hidden openshift-project-backup.sh>< |
+ | # | ||
+ | BACKUP_DIR="/ | ||
+ | BACKUP_DIR_WITH_DATE=${BACKUP_DIR}/ | ||
- | [root@vosm01 openshift-hostfiles]# cd / | + | ### Remove folders older than 30days |
- | [root@vosm01 openshift-hostfiles]# vim hosts_osit2.yaml | + | find ${BACKUP_DIR} |
- | ... | + | |
- | - name: gluster-pv118 | + | |
- | size: 5 | + | |
- | ... | + | |
- | + | ||
- | + | ||
- | [root@vosm01 openshift-hostfiles]# git status | + | |
- | # On branch master | + | |
- | # Changes not staged for commit: | + | |
- | # (use "git add < | + | |
- | # (use "git checkout | + | |
- | # | + | |
- | # | + | |
- | # | + | |
- | no changes added to commit (use "git add" and/or "git commit -a") | + | |
- | [root@vosm01 openshift-hostfiles]# | + | |
- | [root@vosm01 openshift-hostfiles]# | + | |
- | [root@vosm01 openshift-hostfiles]# | + | |
- | Run / | + | |
- | + | ||
- | cd / | + | |
- | ansible-playbook --check main.yml | + | |
- | After successful check run / | + | |
- | + | ||
- | cd / | + | |
- | ansible-playbook main.yml | + | |
- | Check the size of the gluster-pv on the local node. Should now show 1/3rd of the size in mounted position, because GlustrFS is replicated on the node instances. | + | |
- | + | ||
- | df -h | grep gluster-pv118 | + | |
- | Run ov edit pv < | + | |
- | + | ||
- | oc edit pv gluster-pv118 | + | |
- | ... | + | |
- | capacity: | + | |
- | storage: 5Gi | + | |
- | claimRef: | + | |
- | ... | + | |
- | oc get pv | grep pv118 | + | |
- | + | ||
- | + | ||
- | CAUTION: Do not continue if there are errors to see in a step. If there are errors in the Task “[Configure Gluster management firewall rules]“, when running ansible-playbook --check main.yml, note that during container restart, there is a firewall reconfiguration ongoing, which may disturb running ansible-playbook. Try this check again some moments later. | + | |
- | + | ||
- | + | ||
- | + | ||
- | Gluster PV's löschen (obsolete) | + | |
- | + | ||
- | + | ||
- | Auf dem ersten Master das PV unmounten: | + | |
- | + | ||
- | [root@vosm01 cron.hourly]# | + | |
- | [root@vosm01 cron.hourly]# | + | |
- | [root@vosm01 cron.hourly]# | + | |
- | + | ||
- | + | ||
- | Das PV im OpenShift entfernen: | + | |
- | + | ||
- | [root@vosm01 gluster-pvs]# | + | |
- | persistentvolume " | + | |
- | [root@vosn01 ~]# | + | |
- | + | ||
- | + | ||
- | Das gelöschte PV anschliessend auf einem Gluster Node Stopen und löschen: | + | |
- | + | ||
- | [root@vosn01 ~]# gluster volume stop gluster-pvXX | + | |
- | Stopping volume will make its data inaccessible. Do you want to continue? (y/n) y | + | |
- | volume stop: gluster-pv11: | + | |
- | [root@vosn01 ~]# | + | |
- | + | ||
- | + | ||
- | [root@vosn01 ~]# gluster volume delete gluster-pvXX | + | |
- | Deleting volume will erase all information about the volume. Do you want to continue? (y/n) y | + | |
- | volume delete: gluster-pv11: | + | |
- | [root@vosn01 ~]# | + | |
- | + | ||
- | + | ||
- | Zum schluss folgende Ansible Befehle auf dem Master ausführen: | + | |
- | + | ||
- | [root@vosm01 ~]# ansible gluster | + | |
- | [root@vosm01 ~]# ansible gluster -a " | + | ### Setup |
+ | mkdir -p $BACKUP_DIR_WITH_DATE | ||
- | [root@vosm01 ~]# ansible gluster | + | ### Project Backup |
+ | # Check if executed as OSE system: | ||
+ | if [[ "$(oc whoami)" | ||
+ | echo -n "Trying to log in as system: | ||
+ | oc login -u system: | ||
+ | fi | ||
- | [root@vosm01 ~]# ansible gluster | + | # Backup all resources of every project |
- | Ressourcen von einem Projekt wiederherstellen | + | for project in $(oc get projects --no-headers | awk ' |
- | Es läuft täglich 24:00 ein cronjob, der die wichtigsten Projekt Ressourcen täglich exportiert: | + | do |
+ | echo -n "Backing up project $project... " | ||
+ | mkdir -p ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc export all -o yaml -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get rolebindings -o yaml -n ${project} > ${BACKUP_DIR_WITH_DATE}/projects/ | ||
+ | oc get serviceaccount | ||
+ | oc get configmap -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get daemonset -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get secret -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get pvc -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get statefulset -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get buildconfigs -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get builds -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get imagestreams -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get jobs -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get route -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | oc get services -o yaml --export=true -n ${project} > ${BACKUP_DIR_WITH_DATE}/ | ||
+ | echo " | ||
+ | done</ | ||
- | https:// | ||
Dieser legt die Files in folgender Struktur auf dem ersten Master ab: | Dieser legt die Files in folgender Struktur auf dem ersten Master ab: | ||
+ | <sxh bash; gutter: | ||
/ | / | ||
├── backup_201806190000 | ├── backup_201806190000 | ||
Line 241: | Line 170: | ||
│ | │ | ||
..... | ..... | ||
+ | </ | ||
Restore erfolg durch ein simples erstellen der Ressourcen. Zum Beispiel: | Restore erfolg durch ein simples erstellen der Ressourcen. Zum Beispiel: | ||
- | $ oc create -f " | + | < |
- | Problem OpenShift GlusterFS (nicht mehr im HP OVO) | + | </WRAP> |
- | Das Überwachungsskript(/root/ | + | |
- | Dieselbe Fehlermeldung wird auch im HP-OVO Monitoring angezeigt. | + | |
- | Development Platform > DailyBusiness > 1.png | ||
+ | <WRAP center box 100%> | ||
+ | ==== OpenShift Gluster Volume extend - over heketi ==== | ||
- | + | Eine zusätzliche Terabyte Disk auf dem Gluster Cluster via Heketi einbinden: (siehe auch : [[https:// | |
- | Auf dem Glusternode vekq7k wurde wegen eines anderen Fehler ein Neustart des Servers gemacht. Anschliessend konnte GlusterFS nicht vollständig gestartet werden. | + | |
- | Somit muss das GlusterFS auf auf dem gluster-pv101 forciert neu gestartet werden: | + | |
- | + | ||
- | [root@vekq7k ~]# gluster volume status gluster-pv101 | + | |
- | Status of volume: gluster-pv101 | + | |
- | Gluster process | + | |
- | ------------------------------------------------------------------------------ | + | |
- | Brick vhmsgj.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vkyg7l.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vsytjw.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vu32g5.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vpva0p.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vekq7k.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vlf5eh.pnet.ch:/ | + | |
- | ick | + | |
- | Brick vw7w5k.pnet.ch:/ | + | |
- | ick | + | |
- | Brick v2o8fv.pnet.ch:/ | + | |
- | ick | + | |
- | Self-heal Daemon on localhost | + | |
- | Self-heal Daemon on v2o8fv.pnet.ch | + | |
- | Self-heal Daemon on vs3tvs.pnet.ch | + | |
- | Self-heal Daemon on vw7w5k.pnet.ch | + | |
- | Self-heal Daemon on vsytjw.pnet.ch | + | |
- | Self-heal Daemon on vhmsgj.pnet.ch | + | |
- | Self-heal Daemon on vlf5eh.pnet.ch | + | |
- | Self-heal Daemon on vkyg7l.pnet.ch | + | |
- | Self-heal Daemon on vpva0p.pnet.ch | + | |
- | Self-heal Daemon on vu32g5.pnet.ch | + | |
- | Self-heal Daemon on vthbcn.pnet.ch | + | |
- | + | ||
- | Task Status of Volume gluster-pv101 | + | |
- | ------------------------------------------------------------------------------ | + | |
- | There are no active volume tasks | + | |
- | + | ||
- | [root@vekq7k ~]# gluster volume start gluster-pv101 | + | |
- | Kube Config wiederherstellen | + | |
- | Funktioniert oc get " | + | |
- | + | ||
- | [root@vosm01 ~]# cp / | + | |
- | + | ||
- | + | ||
- | + | ||
- | Ansible Einrichtung auf OS Master Node | + | |
- | Damit mittels " | + | |
- | + | ||
- | Aktuelles Hosts Inventory File / | + | |
- | SSH Private Key unter / | + | |
- | Ansible SSH Prublic Key unter / | + | |
- | [root@vosm01 ~]# ls -lsa / | + | |
- | total 16 | + | |
- | 0 drwx------. | + | |
- | 4 dr-xr-x---. 36 root root 4096 Aug 20 16:23 .. | + | |
- | 4 -r--------. | + | |
- | 8 -rw-r--r--. | + | |
- | [root@vosm01 ~]# ls -lsa / | + | |
- | 0 lrwxrwxrwx. 1 root root 42 Mar 6 17:10 / | + | |
- | [root@vosm01 ~]# | + | |
- | [root@vosm01 ~]# ls -lsa / | + | |
- | total 16 | + | |
- | 0 drwx------. | + | |
- | 4 dr-xr-x---. 36 root root 4096 Aug 20 16:23 .. | + | |
- | 4 -r--------. | + | |
- | 8 -rw-r--r--. | + | |
- | [root@vosm01 ~]# | + | |
- | [root@vosm01 ~]# ls -lsa / | + | |
- | 4 -r--------. 1 ansible ansible 389 Jan 27 2017 / | + | |
- | [root@vosm01 ~]# | + | |
- | + | ||
- | + | ||
- | OpenShift Gluster Volume extend - over heketi | + | |
- | Eine zusätzliche Terabyte Disk auf dem Gluster Cluster via Heketi einbinden: (siehe auch : https:// | + | |
Login auf dem OpenShift GUI, Project " | Login auf dem OpenShift GUI, Project " | ||
Line 342: | Line 193: | ||
Auf der Heketi-Pod Konsole node und Cluster ID auslesen. | Auf der Heketi-Pod Konsole node und Cluster ID auslesen. | ||
+ | <sxh plain; highlight: [1]; gutter: false;> | ||
sh-4.2# heketi-cli node list --user admin --secret p/ | sh-4.2# heketi-cli node list --user admin --secret p/ | ||
Id: | Id: | ||
Id: | Id: | ||
Id: | Id: | ||
+ | </ | ||
+ | Jetzt kann das neue Device nach dem Schema "'' | ||
- | Jetzt kann das neue Device nach dem Schema " | + | <sxh plain; highlight: [1,4,7]; gutter: false;> |
- | + | ||
- | + | ||
sh-4.2# heketi-cli device add --name /dev/sdc --node 0680dabe91ee5a7f36da8cb6fe49cdd4 --user admin --secret p/ | sh-4.2# heketi-cli device add --name /dev/sdc --node 0680dabe91ee5a7f36da8cb6fe49cdd4 --user admin --secret p/ | ||
Device added successfully | Device added successfully | ||
Line 360: | Line 211: | ||
sh-4.2# heketi-cli device add --name /dev/sdc --node b016e52ee7378debc04427385f81cd82 --user admin --secret p/ | sh-4.2# heketi-cli device add --name /dev/sdc --node b016e52ee7378debc04427385f81cd82 --user admin --secret p/ | ||
Device added successfully | Device added successfully | ||
+ | </ | ||
Als Resultat der Erweiterung, | Als Resultat der Erweiterung, | ||
+ | <sxh plain; highlight: [1]; gutter: false;> | ||
[root@vosge1 ~]# pvscan | [root@vosge1 ~]# pvscan | ||
PV / | PV / | ||
Line 369: | Line 221: | ||
PV / | PV / | ||
Total: 3 [2.03 TiB] / in use: 3 [2.03 TiB] / in no VG: 0 [0 ] | Total: 3 [2.03 TiB] / in use: 3 [2.03 TiB] / in no VG: 0 [0 ] | ||
+ | </ | ||
+ | </ | ||
- | |||
- | |||
- | Neue Host zum existierenden Cluster hinzufügen | ||
- | Red Hat Anleitung: https:// | ||
- | |||
- | Die neuen Hosts müssen in eine der folgenden beiden Firewall Gruppen, damit sie die nötigen Firewalls geschaltet bekommen (Je nach Plattform unterschiedliche FW-Rules): | ||
- | WICHTIG: Wenn die Änderungen vorgenommen wurden, muss die Gruppe implementiert werden! | ||
- | |||
- | Nonprod: IT-OShift-SharedNodeTest-M02A4-X | ||
- | Prod: IT-OShift-SharedNodeProd-M02A4-X | ||
- | |||
- | Mit folgendem Ansible Befehl kann überprüft werden, ob die FW Rules geschaltet wurden: | ||
- | |||
- | [rebermi@vosbh1]# | ||
- | |||
- | |||
- | Bevor der neue Host dem Cluster hinzugefügt werden kann, muss dieser die nötigen OpenShift Pakete erhalten. | ||
- | Jedoch wird dieses nur bis zur Version 3.9 gepflegt. Deshalb müssen zuerst unter / | ||
- | |||
- | [root@new_host]# | ||
- | [rhel-7-server-ose310-rpms] | ||
- | baseurl = http:// | ||
- | enabled = 1 | ||
- | gpgcheck = 1 | ||
- | gpgkey = file:/// | ||
- | name = Red Hat OpenShift Container Platform 3.10 (RPMs) | ||
- | |||
- | [rhel-7-server-ose39-rpms] | ||
- | baseurl = http:// | ||
- | enabled = 1 | ||
- | gpgcheck = 1 | ||
- | gpgkey = file:/// | ||
- | name = Red Hat OpenShift Container Platform 3.9 (RPMs) | ||
- | |||
- | |||
- | [root@new_host]# | ||
- | [root@new_host]# | ||
- | |||
- | |||
- | Der Host ist nun bereit. Jetzt muss das Hostfile angepasst werden (siehe <---): | ||
- | |||
- | [rebermi@vosbh1]# | ||
- | --- | ||
- | all: | ||
- | children: | ||
- | OSEv3: | ||
- | children: | ||
- | bastion: {} | ||
- | glusterfs: {} | ||
- | glusterfs_registry: | ||
- | etcd: {} | ||
- | masters: {} | ||
- | nodes: | ||
- | children: | ||
- | masters: {} | ||
- | infra_nodes: | ||
- | user_nodes: {} | ||
- | new_nodes: {} <--- | ||
- | ... | ||
- | user_nodes: | ||
- | hosts: | ||
- | EXISTING_HOSTS.pnet.ch: | ||
- | openshift_hostname: | ||
- | openshift_ip: | ||
- | openshift_node_group_name: | ||
- | openshift_node_local_quota_per_fsgroup: | ||
- | new_nodes: <--- | ||
- | hosts: | ||
- | NEW_HOST.pnet.ch: | ||
- | openshift_hostname: | ||
- | openshift_ip: | ||
- | openshift_node_group_name: | ||
- | openshift_node_local_quota_per_fsgroup: | ||
- | |||
- | |||
- | Zum Schluss muss nun das Scaleup Playbook von Red Hat ausgeführt: | ||
- | |||
- | ansible-playbook [-i / | ||
- | |||
- | |||
- | Damit auch Pods auf den neuen Cluster-Nodes erstellt werden können, muss man die LABELS der Nodes anpassen: | ||
- | |||
- | [user@vosbh1 ~]$ oc login https:// | ||
- | [user@vosbh1 ~]$ oc get nodes --show-labels | ||
- | |||
- | # Man kann jetzt die Labels eines funktionierenden Nodes kopieren und folgendermassen diesen labeln: | ||
- | |||
- | [user@vosbh1 ~]$ oc label node NEWNODE compute=true | ||
- | [user@vosbh1 ~]$ oc label node NEWNODE region=primary | ||
- | [user@vosbh1 ~]$ oc label node NEWNODE stage=test | ||
- | [user@vosbh1 ~]$ oc label node NEWNODE zone=defaul | ||
- | |||
- | |||
- | Die Labels sollten je nach Node angepasst werden (EH/ZF , stage=test / stage=prod , usw.) |