-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathyakko
executable file
·9150 lines (7675 loc) · 299 KB
/
yakko
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
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/bin/bash
#set -x; export PS4='Line ${LINENO}: '
YAKKOVERSION=8.1
YAKKODATE=20241221.1459
###########################################################################
# YAKKO - Yet another KVM Konfigurator for OpenShift
# AUTHOR: Daniel Cifuentes
# ------------------------------------------------------------------------
# A COVID Pandemic Confinement project - Circa 09/2020
# ------------------------------------------------------------------------
# Inspirational Documentation for this:
# https://github.com/eitchugo/openshift-libvirt/blob/master/OpenShift_4_libvirt_install_1_master.md
###########################################################################
############ OPENSHIFT 4.16 SIZING ########################################
#
# PLATFORM AGNOSTIC:
# https://docs.openshift.com/container-platform/4.16/installing/installing_platform_agnostic/installing-platform-agnostic.html
#
# SNO:
# https://docs.openshift.com/container-platform/4.16/installing/installing_sno/install-sno-preparing-to-install-sno.html
#
# AGENT BASED INSTALLER:
# https://docs.openshift.com/container-platform/4.16/installing/installing_with_agent_based_installer/preparing-to-install-with-agent-based-installer.html
#
##########################################################################
# TESTED PLATFORMS FOR THIS VERSION OF YAKKO - this will be checked always on install
TESTEDPLATFORMS="rhel 9.4, fedora 40"
#########################################################################
## START: USER CONFIGURABLE PARAMETERS - you can also change through the use of a template
## (do not change this heading!)
#########################################################################
# RAM Sizing
SINGLEMASTERRAMSIZE=32000 # See recommendation links above
THREEMASTERRAMSIZE=16000 # See recommendation links above
DEFAULTWORKERRAMSIZE=8000 # Recommended 8GB
WORKERRAMSIZE=8000 # Recommended 8GB
MINWORKERRAMSIZE=8000 # This boundary has been changing as OCP revs up!
BOOTSTRAPNODERAMSIZE=16000 # See recommendation links above - RAM size of the bootstrap has changed over time...
MAXMEMBALOONSIZE=2000 # We provide a little room for growth. No one wants to swap!
# CPU Sizing
MASTERNODECOUNT=3 # Default clusters by YAKKO are built as 3x0
MASTERVCPUS=4 # Recommended 4, though with SNO/single master it is better to have 8
WORKERVCPUS=2 # Recommended 2
RECOMMENDEDCORECOUNT=8 # This is for the YAKKO host to work well. Less than this? try harder when installing.
BOOTSTRAPNODEVCPUS=4 # See recommendation links above - CPU count of the bootstrap has changed over time...
MAXNODEVCPUS=8 # Max number of allowable CPUs for a worker node
# Disk Sizing
MASTERDISKSIZE=120 # Disk image size for master, GB # OCP 4.15 needs 120GB for Agent Based Install
WORKERDISKSIZE=120 # Disk image size for worker, GB
#Node Sizing
MAXWORKERNODES=5 # Max number of worker nodes allowed at cluster BUILD time, after that, no limit
# Other parameters - these are configured by YAKKO, but here you go
USEYAKKODNSMASQ=Y # Choose to use your own name servers only or have YAKKO also setup a complimentary DNS service
WEBSERVERPORT=8086 # This is the webserver that YAKKO uses for provisioning and for further info
HAPROXYACCESS=0 # We default OPEN access through the proxy, subject to change later
PROXYADDRESS=1 # So that the overall "proxy" to the cluster is BASENETWORK.PROXY e.g. 192.168.140.1
VNCPORT=5920 # We'll leave the firt few ports open for traditional VNC uses
SDNTYPE=OVNKubernetes # Just in case... it can also be: OpenShiftSDN
AGENTBASEDINSTALLER="" # It's a question now. YAKKO 7.0++
SNAPCLUSTERONINSTALL=N # 8.0 - we can snap a cluster, offer the option on fresh install
OCPINSTLOGLEVEL=info # OCP installer log level
REDUCEPROMETHEUS=N # Prometheus pod RAM can be reduced, which makes sense, change to Y if not desired.
COREMACADDRESS=52:54:00:4a # This is the MAC address prefix for all node VM MACs
## The BASEMACADDRESS is missing the last two entries/hexes. The second to last is calculated on
## the last number of the BASEMACNETWORK, in case two clusters run on the same box, to prevent
## virtual network confusion, even if perhaps... it may work without conflict. Original code had
## this number as 52:54:00:4a:66 but now the last hex number will be the 3 network digit i.e. 140 which is "8c"
# File and directory variables used throughout
OCPVMDIR=/var/lib/libvirt/images # This is where node VMs will reside
CLUSTERDOMAIN=localdomain # The default domain name if no other is offered
LOGINCOMMANDFILE=cluster-login # Yakko leaves a login file behind when done!
CLUSTERNOTES=cluster-notes # Where YAKKO keeps your notes about the cluster
CLUSTERPOSTINSTALL=cluster-post-install # The default file to run for post-install tasks
OCPSETUPENV=ocp-setup-env # Default commands to setup your KUEBCONFIG and oc binary
#########################################################################
## END: USER CONFIGURABLE PARAMETERS
## (do not change this heading!)
#########################################################################
#### DO NOT CHANGE FROM HEREON
YAKKONAME=YAKKO # In case we want to change the name?
YAKKOSCRIPTNAME=yakko # In case we want to change the script name??
# HOST DETAILS
YAKKOHOSTOSNAME=$(cat /etc/os-release | grep '^ID=' | cut -f2 -d= | tr -d "\"")
YAKKOHOSTOSRELEASE=$(cat /etc/os-release | grep '^VERSION_ID=' | cut -f2 -d= | tr -d "\"")
YAKKOHOSTPLATFORM="$YAKKOHOSTOSNAME $YAKKOHOSTOSRELEASE"
# WGET setup (one day - curl!)
[ ${YAKKOHOSTOSNAME} == "rhel" ] && WGET="wget"
[ ${YAKKOHOSTOSNAME} == "fedora" ] && WGET="wget2"
# Cluster build progression variables - DO NOT CHANGE
REQUIREDPACKAGES="libvirt virt-install qemu-kvm virt-top haproxy lsof httpd firewalld bind-utils net-tools ${WGET}"
YAKKOSTAGE=0
STAGEPROGRESS=0
YAKKOBUILDTEMPLATETYPE=0 # 0 means "ask questions, don't use a template file"
AUTOSETUP=N # Y is Auto, N is manual
DELETECLUSTERMODE=1 # This goes to 0 when we delete the entire cluster with deletecluster
DELETECLUSTERFORCE=1
YAKKOADMIN=kubeadmin # once deleted this is stored as "" in CLUSTERCONFIGFILE
PAUSEFORCONFIGEDIT=1
SPINNERPID=0
CSRAPPROVALPID=0
ADDNODETIMEOUT=900 # TIMER: If I cannot add a node within timeout (this multiplied by number of nodes)
YAKKOTEXTCOLOUR=brightblue # Look and feel :)
# YAKKO parameter options
YAKKOINFRAOPTIONS=" startcluster / stopcluster / snaptake / snaprestore / addnode / deletenode / nodelogs / sshtonode / changeaccess / updateservices / listresources / listclusters / purgedownloads / resizeram / describehw / nfsshare / installcomplete / deletecluster "
YAKKOCLUSTEROPTIONS=" htpasswd / useradd / userdelete / mastersched / nodelabel / localregistry / nfsregistry / nfsmap / ingresscert / approvecsrs / emergency / yakkotest "
# Temporary files
HTPASSWDFILE=/tmp/ocp-htpasswd.$$
DHCPXMLTMPFILE=/tmp/yakkodhcpxmlline.$$.tmp
OCPWGETTMP=/tmp/ocpsetupwget.$$.tmp
YAKKOTALLY=/.yakkobuildtally
# Default Download links
# Get the OCP installer specifically for x86_64. One day this may be useful for IBM ... Power ;)
OCPPLATFORM=x86_64
OCPROOT=https://mirror.openshift.com/pub/openshift-v4/$OCPPLATFORM
# Decorations
SEPARATIONLINE="__________________________________________________________________________"
# Some useful constants
NUMBERRE='^[0-9]+$' # Number - regular expression
################ A FEW INITIALISATION FUNCTIONS ################################################
print-yakko-nocluster-menu() {
echo " yakko (no params) -------------------------> build new cluster - just answer questions"
echo " yakko rebuildcluster -----------------------> recreate the last cluster built"
echo " yakko buildclusterfromtemplate <file/URL> --> build new cluster from file or URL"
echo " yakko buildclusterfromdefaults <#M> <#W> ---> build with all defaults, specifing only"
echo " # of masters and # of workers"
}
populate-cluster-config-file() {
# CLUSTERCONFIGFILE CREATION
# Populate the config file with some references for future calls
# this is an emergency break, has happened!
[ -z "${CLUSTERNAME}" ] && check-for-error-and-exit 0 "Cluster name is blank - saving cluster config file"
{
echo "CLUSTERNAME=${CLUSTERNAME}"
echo "CLUSTERDOMAIN=${CLUSTERDOMAIN}"
echo "CLUSTERFQDN=${CLUSTERFQDN}"
echo "CLUSTERWEBURL=${CLUSTERWEBURL}"
echo "CLUSTERAPIURL=${CLUSTERAPIURL}"
echo "YAKKOSTAGE=0"
echo "CLUSTERSETUPDIR=${CLUSTERSETUPDIR}"
echo "NETWORKNAME=${NETWORKNAME}"
echo "OCPVERSION=${OCPVERSION}"
echo "OCPDOWNLOADCLIENT=${OCPDOWNLOADCLIENT}"
echo "OCPINSTALLVERSION=${OCPVERSION}"
echo "OCPINSTALLMINORVERSION=${OCPINSTALLMINORVERSION}"
echo "OCPDOWNLOADIMAGES=${OCPDOWNLOADIMAGES}"
echo "OCPVMDISKDIR=${OCPVMDISKDIR}"
echo "OCPINSTALLSOURCE=$OCPINSTALLSOURCE"
echo "NETWORKXML=$CLUSTERSETUPDIR/${NETWORKNAME}.xml"
echo "NETWORKADDRESSSLOT=20"
echo "NODECOUNT=0"
echo "OCPSSHKEY=${OCPSSHKEY}"
echo "BUILTWITHYAKKOVERSION=${YAKKOVERSION}"
echo "NOTICEYAKKOVERSION=${YAKKOVERSION}"
echo "YAKKOHOSTIP=${YAKKOHOSTIP}"
echo "VNCPORT=${VNCPORT}"
echo "HAPROXYACCESS=${HAPROXYACCESS}"
echo "SYSTEMSTUBFILE_DNSMASQ=${SYSTEMSTUBFILE_DNSMASQ}"
echo "SYSTEMSTUBFILE_NETWORKMANAGER=${SYSTEMSTUBFILE_NETWORKMANAGER}"
echo "SYSTEMSTUBFILE_RESOLVED=${SYSTEMSTUBFILE_RESOLVED}"
echo "SYSTEMSTUBFILE_HAPROXY=${SYSTEMSTUBFILE_HAPROXY}"
echo "SYSTEMSTUBFILE_HTTPD=${SYSTEMSTUBFILE_HTTPD}"
echo "STUBFILES=${STUBFILES}"
echo "SELINUXSTATE=${SELINUXSTATE}"
echo "OCPINSTLOGLEVEL=${OCPINSTLOGLEVEL}"
echo "REDUCEPROMETHEUES=${REDUCEPROMETHEUS}"
echo "WEBSERVERPORT=${WEBSERVERPORT}"
echo "LOGINFILEHASPASSWORD=0"
echo "AGENTBASEDINSTALLER=$AGENTBASEDINSTALLER"
# These exist in lastclusterconfig too, but resizing will change it here only
echo "MASTERNODECOUNT=${MASTERNODECOUNT}"
echo "WORKERNODECOUNT=${WORKERNODECOUNT}"
echo "MASTERRAMSIZE=${MASTERRAMSIZE}"
echo "WORKERRAMSIZE=${WORKERRAMSIZE}"
echo "MASTERVCPUS=${MASTERVCPUS}"
echo "WORKERVCPUS=${WORKERVCPUS}"
echo "MASTERDISKSIZE=${MASTERDISKSIZE}"
echo "WORKERDISKSIZE=${WORKERDISKSIZE}"
} > "${CLUSTERCONFIGFILE}"
source "${CLUSTERCONFIGFILE}"
}
populate-user-definitions() {
# Basic directories
CLUSTERSETUPDIR=${YAKKODIRECTORY}/install
STUBFILES=${CLUSTERSETUPDIR}/stubfiles
OCPINSTALLVERSION=$OCPVERSION
OCPINSTALLSOURCE=$IMAGEREPO/$OCPINSTALLVERSION
# Added ${PROXYADDRESS} below so that you can repeat cluster names without interefering with the virtual network
NETWORKNAME=${YAKKOSCRIPTNAME}-net-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}
NETWORKXML=$CLUSTERSETUPDIR/${NETWORKNAME}.xml
CLUSTERFQDN=${CLUSTERNAME}.${CLUSTERDOMAIN}
CLUSTERWEBURL="https://console-openshift-console.apps.${CLUSTERFQDN}"
CLUSTERAPIURL="https://api.${CLUSTERFQDN}:6443"
CLUSTERPROXY="${BASENETWORK}.${PROXYADDRESS}"
OCPSSHKEY=~/.ssh/id_rsa_ocp_${CLUSTERNAME}_${CLUSTERDOMAIN}_${YAKKOID}
#Disk storage for VMs
OCPVMDISKDIR="$OCPVMDIR"/YAKKO-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}
# These are files that will be placed in the right place on cluster boot, SYSTEMSTUBFILE_*
SYSTEMSTUBFILE_DNSMASQ=/etc/NetworkManager/dnsmasq.d/yakko-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}-dnsmasq.conf
SYSTEMSTUBFILE_NETWORKMANAGER=/etc/NetworkManager/conf.d/yakko-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}-NetworkManager.conf
SYSTEMSTUBFILE_HTTPD=/etc/httpd/conf.d/yakko-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}-httpd.conf
SYSTEMSTUBFILE_RESOLVED=/etc/systemd/resolved.conf.d/yakko-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}-resolved.conf
SYSTEMSTUBFILE_HAPROXY=/etc/haproxy/conf.d/yakko-${CLUSTERNAME}-${CLUSTERDOMAIN}-${YAKKOID}-haproxy.cfg
# We calculate the BASEMACADDRESS last digit here...
# This in case there is more than one cluster defined... Maybe...
BASEMACADDRESS="${COREMACADDRESS}:$(echo ${BASENETWORK} | cut -f3 -d. | xargs printf '%x')"
{
# GENERAL CONFIG
echo "CLUSTERNAME=${CLUSTERNAME}"
echo "CLUSTERDOMAIN=${CLUSTERDOMAIN}"
echo "OCPVMDIR=${OCPVMDIR}"
echo "OCPVMDISKDIR=${OCPVMDISKDIR}"
echo "PAUSEFORCONFIGEDIT=${PAUSEFORCONFIGEDIT}"
echo "AGENTBASEDINSTALLER=$AGENTBASEDINSTALLER"
# CLUSTER NODE CONFGURATION
echo "MASTERNODECOUNT=${MASTERNODECOUNT}"
echo "WORKERNODECOUNT=${WORKERNODECOUNT}"
echo "MASTERRAMSIZE=${MASTERRAMSIZE}"
echo "WORKERRAMSIZE=${WORKERRAMSIZE}"
echo "MASTERVCPUS=${MASTERVCPUS}"
echo "WORKERVCPUS=${WORKERVCPUS}"
echo "MASTERDISKSIZE=${MASTERDISKSIZE}"
echo "WORKERDISKSIZE=${WORKERDISKSIZE}"
# NETWORK CONFIGURATION
echo "BASEMACADDRESS=${BASEMACADDRESS}"
echo "BASENETWORK=${BASENETWORK}"
echo "YAKKOHOSTIP=${YAKKOHOSTIP}"
echo "HAPROXYACCESS=${HAPROXYACCESS}"
echo "USEYAKKODNSMASQ=${USEYAKKODNSMASQ}"
echo "WEBSERVERPORT=${WEBSERVERPORT}"
echo "CLUSTERPROXY=${CLUSTERPROXY}"
# This will be used for creating nodes later on so that any new nodes start at $NETWORKADDRESSSLOT
# Note that bootstrap and masters have fixed numbers for IP and MAC
# 52:54:00 is KVM/QEMU default 4A:66:00 is a transliteration of YAKKO ;)
# All worker nodes will begin with MAC and IP $NETWORKADDRESSSLOT
echo "NETWORKADDRESSSLOT=20"
echo "BOOTSTRAPMAC=${BASEMACADDRESS}:09"
echo "MASTER0MAC=${BASEMACADDRESS}:10"
echo "MASTER1MAC=${BASEMACADDRESS}:11"
echo "MASTER2MAC=${BASEMACADDRESS}:12"
echo "BOOTSTRAPIP=${BASENETWORK}.9"
echo "MASTER0IP=${BASENETWORK}.10"
echo "MASTER1IP=${BASENETWORK}.11"
echo "MASTER2IP=${BASENETWORK}.12"
echo "MIRRORSERVER=${MIRRORSERVER}"
echo "CLUSTERPOSTINSTALL=${CLUSTERPOSTINSTALL}"
} > "${CLUSTERBUILDDEFAULTS}"
source "${CLUSTERBUILDDEFAULTS}"
}
print-yakko-defaults() {
awk '/START: USER CONFIGURABLE PARAMETERS/,/END: USER CONFIGURABLE PARAMETERS/' < yakko | grep -v "START: USER CONFIGURABLE" | grep -v "^##"
}
generate-login-command-file() {
# Need two parameters,username and password
LOGINUSERNAME=$1
LOGINPASSWORD=$2
if [ "${LOGINUSERNAME}" == "kubeadmin" ]
then
echo "oc login -u ${LOGINUSERNAME} -p $(cat ${CLUSTERSETUPDIR}/auth/kubeadmin-password) --insecure-skip-tls-verify=true --server=https://api.${CLUSTERFQDN}:6443" > ${YAKKODIRECTORY}/$LOGINCOMMANDFILE
else
sed -i "s/oc login -u kubeadmin/#oc login -u kubeadmin/" ${YAKKODIRECTORY}/$LOGINCOMMANDFILE &>/dev/null
if [ "${LOGINFILEHASPASSWORD}" -eq 0 ] # O means it's allowed to put the password in the file
then
echo "oc login -u ${LOGINUSERNAME} -p ${LOGINPASSWORD} --insecure-skip-tls-verify=true --server=https://api.${CLUSTERFQDN}:6443" >> ${YAKKODIRECTORY}/$LOGINCOMMANDFILE
else
echo "oc login -u ${LOGINUSERNAME} --insecure-skip-tls-verify=true --server=https://api.${CLUSTERFQDN}:6443" >> ${YAKKODIRECTORY}/$LOGINCOMMANDFILE
fi
fi
chmod 700 ${YAKKODIRECTORY}/$LOGINCOMMANDFILE
}
change-console-logo() {
rm /tmp/yakko-custom-logo.png &>/dev/null
${WGET} -O /tmp/yakko-custom-logo.png https://raw.githubusercontent.com/ozchamo/YAKKO/master/openshift-yakko-logo.png &>/dev/null
if [ $? -eq 0 ]
then
echo "Updating OpenShift Console logo!"
${OCCOMMAND} delete configmap yakko-custom-logo -n openshift-config
${OCCOMMAND} create configmap yakko-custom-logo --from-file /tmp/yakko-custom-logo.png -n openshift-config
${OCCOMMAND} patch consoles.operator.openshift.io/cluster --type=merge -p '{"spec":{"customization":{"customLogoFile":{"name":"yakko-custom-logo"}}}}'
${OCCOMMAND} patch consoles.operator.openshift.io/cluster --type=merge -p '{"spec":{"customization":{"customLogoFile":{"key":"yakko-custom-logo.png"}}}}'
rm /tmp/yakko-custom-logo.png &>/dev/null
else
echo "Could not update OpenShift Console logo - failed to download from github."
fi
}
mark-cluster-complete() {
OCPINSTALLCODE=$1
CLUSTERCOMPLETE="\"exitcode ${OCPINSTALLCODE} date $(date +"%d-%b-%Y@%T") hostdir ${YAKKODIRECTORY} \""
echo "CLUSTERCOMPLETE=$CLUSTERCOMPLETE" >> ${CLUSTERCONFIGFILE}
if [ ${OCPINSTALLCODE} == MANUAL ]
then
CLUSTERCERTSEXPIRY=Unknown
else
CLUSTERCERTSEXPIRY=\"$(get-cluster-certificate-expiry)\"
fi
echo "CLUSTERCERTSEXPIRY=${CLUSTERCERTSEXPIRY}" >> ${CLUSTERCONFIGFILE}
# We copy the cluster config file for retrieval via the web server
cp ${KUBECONFIG} ${IMAGEREPO}/kubeconfig
chmod +r ${IMAGEREPO}/kubeconfig
chcon -R -t httpd_sys_content_t ${IMAGEREPO}/kubeconfig
compose-html-cluster-report
# and dump the login token ;)
check-oc-credentials
if [ $? -eq 0 ]
then
generate-login-command-file kubeadmin
fi
}
check-for-other-yakko-cluster-files() {
# very simple routine, simply exit if there are other yakko files present.
# this is in particular useful when starting a cluster after a crash
# or when building a new cluster after a crash
if [ $(find /etc -name 'yakko*' | wc -l) -gt 0 ]
then
print-in-colour orange "NOTE: There is no active cluster but there are YAKKO files in the system"
echo "This can cause conflicts for services to come up properly."
echo "There is no dependency on the following files to cleanly"
echo "start up the cluster and can therefore be removed safely:"
echo
find /etc -name 'yakko*' | sed -e "s/^/- /"
echo
ask-user "Delete these files and continue" Y noauto
if [ $? -eq 0 ]
then
remove-stubfiles
stop-virtual-network undefine
echo
else
cleanup-and-exit 1 orange "Please check manually and return when ready"
fi
fi
}
################ A FEW REUSABLE FUNCTIONS ################################################
start-spinner() {
# Call this to start the spinner. No need to background anything.
# $1 - Pass some text if you want to explain what's going on.
# SPINNERPID is global
[ "$RUNCOMMANDDEBUG" == "Y" ] && return
SPINNERSTRING=$1
local -a cursor=( '/' '-' '\' '|' );
tput civis # Hide the cursor
while true
do
printf "$SPINNERSTRING %s\r" "${cursor[i++ % ${#cursor[@]}]}";
sleep 0.25
trap "tput cnorm;exit" SIGTERM # Restore the cursor and exit on signal
trap "tput cnorm;exit" SIGINT # Restore the cursor and exit on signal
trap "tput cnorm;exit" SIGQUIT # Restore the cursor and exit on signal
done &
SPINNERPID=$!
}
stop-spinner() {
# Call this to stop the spinner. No params required thanks to global SPINNERPID
[ "$RUNCOMMANDDEBUG" == "Y" ] && return
local ENDSPINNERSTRING=$1
if [ $SPINNERPID -ne 0 ]
then
# If it's not zero, it means it's active, we kill it and set it back to zero
if [ -z "$ENDSPINNERSTRING" ]
then
#printf " \r";
blank-line
else
echo "$ENDSPINNERSTRING"
fi
kill -SIGTERM $SPINNERPID
tput cnorm # Just in case
SPINNERPID=0
SPINNERSTRING=""
sleep 2 # Give a little time for the above
fi
}
wait-for-any-key() {
echo -n "$* "
read -n1 -s _
echo
}
wait-for-stable-operators() {
TIMEOUT=$1
echo
start-spinner "Waiting up to $TIMEOUT minutes for all operators to become stable (start time $(date +%H:%M))"
$OCCOMMAND adm wait-for-stable-cluster --minimum-stable-period=10s --timeout=0h${TIMEOUT}m0s &> /dev/null
RESULT=$?
stop-spinner
return $RESULT
}
cleanup-and-exit() {
# $1 is the return code
# $2-colour and $3-message come together and are optional
if [ $# -eq 2 ]
then
local TEXTCOLOUR=white
local TEXTMESSAGE=$2
else
local TEXTCOLOUR=$2
local TEXTMESSAGE=$3
fi
if [ -n "$TEXTMESSAGE" ]
then
echo
print-in-colour $TEXTCOLOUR "$TEXTMESSAGE. Exiting..."
fi
echo # Make it all look pretty
pkill -P $BASHPID # We kill all children spawned by the big guy # YAKKO 8.0
stop-spinner
# Other basic cleanup
rm $OCPWGETTMP &>/dev/null
if [ $# -eq 0 ]
then
exit 0
else
exit $1
fi
}
do-remove-directory() {
if [ $# -gt 1 ]
then
echo "Requested to remove multiple directories - aborting!"
exit
fi
if [ -z "$1" ]
then
echo "WARNING: A request to remove a directory was made without a directory name!"
fi
if [ "$1" == "/" ]
then
echo "Requested to delete / - aborting!"
exit
fi
SLRE='^/+$'
# and this just in case
if [[ $1 =~ $SLRE ]]
then
echo "Requested to delete / - aborting!"
exit
fi
# We are in a safer place now
rm -rf "$1"
}
print-in-colour() {
# $1 is the color:
case "$1" in
"red") TEXTCOLOR=1;;
"green") TEXTCOLOR=2;;
"yellow") TEXTCOLOR=3;;
"lightblue") TEXTCOLOR=6;;
"white") TEXTCOLOR=7;;
"brightblue") TEXTCOLOR=14;;
"orange") TEXTCOLOR=9;;
esac
shift
# It's $1 again because we shifted above
if [ "$1" == "nonewline" ]
then
ECHOPARAMS="-e -n"
shift
else
ECHOPARAMS="-e"
fi
tput setaf ${TEXTCOLOR};tput bold
echo ${ECHOPARAMS} "$*"
tput sgr0
}
print-in-blink() {
# $1 is the message
MESSAGE=$1
echo -e $(tput blink)${MESSAGE}$(tput sgr0)
echo
}
print-alert() {
# $1 is the message
# This is in red and blinking for drawing lots of attention
MESSAGE=$1
tput setaf 1;tput bold
echo -e $(tput blink)${MESSAGE}$(tput sgr0)
tput sgr0
echo
}
print-time-elapsed() {
TIMEELAPSEDSECS=$(( $SECONDS - $TIMESTART))
TIMEELAPSEDMINS=$(( $TIMEELAPSEDSECS / 60 ))
print-in-colour ${YAKKOTEXTCOLOUR} "Time elapsed: " ${TIMEELAPSEDMINS} mins $(( ${TIMEELAPSEDSECS} - (${TIMEELAPSEDMINS} * 60 ) )) secs
}
print-question-separator() {
echo
tput bold
print-in-colour lightblue "[$((QUESTIONNUM++))/${QUESTIONSTOTAL}] $*:"
tput sgr0
}
print-question-skip() {
echo
tput bold
print-in-colour lightblue "[$((QUESTIONNUM++))/${QUESTIONSTOTAL}] $*"
tput sgr0
}
blank-line() {
# This little trick let's you overwrite a line with the next echo
echo -ne "\r\e[0K"
}
ask-user() {
# $1 is the string to display
# $2 is the default if user presses <ENTER>
# $3 as "noauto" ignores the AUTOSETUP flag
# Returns 0 for YES and 1 for NO
DIALOGUETEXT=$1
DEFAULTRESPONSE=$2
NOAUTO=$3
local AURESPONSE
# We are within a stage, so we need to setup a trap to rollback
[ -n "${CURRENTSTAGE}" ] && trap 'echo; echo "Input interrupted. Aborting."; ${CURRENTSTAGE} rollback; echo; cleanup-and-exit 1' SIGINT
if [ $AUTOSETUP == Y -a -z "$NOAUTO" ]
then
# if in AUTO mode return DEFAULTRESPONSE
if [ "$DEFAULTRESPONSE" == "y" -o "$DEFAULTRESPONSE" == "Y" ]
then
return 0
elif [ "$DEFAULTRESPONSE" == "n" -o "$DEFAULTRESPONSE" == "N" ]
then
return 1 # 1 = false!
fi
fi
# We use AURESPONSE as "Ask User Response" - because RESPONSE is global :(
while true
do
echo -n "$DIALOGUETEXT (Y/N) [$DEFAULTRESPONSE]? "
read AURESPONSE
[ -z "${AURESPONSE}" ] && AURESPONSE=${DEFAULTRESPONSE}
if [ "$AURESPONSE" == "y" -o "$AURESPONSE" == "Y" ]
then
return 0
elif [ "$AURESPONSE" == "n" -o "$AURESPONSE" == "N" ]
then
return 1 # 1 = false!
else
echo "Invalid reponse [$AURESPONSE]."
fi
done
}
check-for-error-and-print() {
# There is no error found
[ "$1" -eq 0 ] && return
# Else... Doom!
echo
print-in-colour red "ERROR: $2"
}
check-for-error-and-exit() {
# Something bad got caught somewhere - write this out and abort
# $1 is the error code passed (0 is good)
# $2 is a string to report
# If we are already in a rollback don't repeat!
if [ "${ROLLBACKACTIVE}" == "Y" ]
then
return
fi
# There is no error found
[ "$1" -eq 0 ] && return
# Else... Doom!
echo
print-in-colour red "ERROR: $2 - exiting..."
if [ -n "${CURRENTSTAGE}" ]
then
#We are within a stage so we rollback
ask-user "Rollback steps of this stage (Y) or leave for debugging (N)" "Y" noauto
[ $? -eq 0 ] && ${CURRENTSTAGE} rollback
fi
#We had to print that there was an earlier error so we cannot now pass ERROR text to cleanup-and-exit
cleanup-and-exit 1
}
print-yakko-header() {
# PRINTFULLYAKKOHEADER - This is to allow for little text output when calling yakko within yakko
if [ "${PRINTFULLYAKKOHEADER}" != "Y" ]
then
# If yakko is called within yakko during the post-install, we don't want too much noise
# and we know where we are because CLUSTERCOMPLETE is not set
echo ${SEPARATIONLINE}
else
# Here comes the colorful YAKKO header!
clear -x
print-in-colour ${YAKKOTEXTCOLOUR} ${SEPARATIONLINE}
echo
print-in-colour ${YAKKOTEXTCOLOUR} " YAKKO: Yet Another KVM Konfigurator for Openshift (Ver. ${YAKKOVERSION})"
print-in-colour ${YAKKOTEXTCOLOUR} ${SEPARATIONLINE}
echo
fi
}
install-package-if-missing() {
# $1 is the package to check for
PACKAGE=$1
dnf list installed | grep $PACKAGE &>/dev/null
if [ $? -ne 0 ]
then
if [ ${CONNECTEDINSTALL} == 1 ]
then
print-in-colour orange "- $PACKAGE is required but not installed."
PACKAGEINSTALLSTATUS=1
else
echo "Installing package [$PACKAGE]"
dnf -y install $PACKAGE
check-for-error-and-exit $? "Failed to install package [$PACKAGE]"
fi
fi
}
install-required-yakko-packages() {
# This procedure only gets called when you are running yakko for the first time
# as an installation. If you are running "addcluster" there would be no need
# to check that all packages are there because it has been done before
PACKAGEINSTALLSTATUS=0
echo
echo "${YAKKONAME} requires a number of packages to be present. For this, it can automatically"
echo "attempt to install these where access to repos for 'dnf' exists. You can however,"
echo "also install these manually using dnf."
echo
ask-user "Do you want ${YAKKONAME} to install required packages automatically?" Y
CONNECTEDINSTALL=$?
echo
if [ ${CONNECTEDINSTALL} == 1 ]
then
print-in-colour orange "${YAKKONAME} will look for the required packages and prompt you to install any that are missing."
else
echo "Installing required packages..."
fi
for PACKAGE in ${REQUIREDPACKAGES}
do
echo "> Checking package [$PACKAGE]..."
install-package-if-missing "${PACKAGE}"
done
if [ "${PACKAGEINSTALLSTATUS}" == "1" ]
then
echo
echo "You will need to install the above highlighted packages and rerun ${YAKKONAME} when ready."
echo
cleanup-and-exit 1
else
print-in-colour green "All required packages are installed."
echo
fi
}
test-libvirt-monolithic-service-status() {
SERVICE=$1 # service name eg libvirtd.socket
echo "Testing status of monolithic daemon $1 ..."
sleep 1
systemctl is-active $SERVICE &>/dev/null
RESULTTSS1=$?
if [ $RESULTTSS1 -eq 0 ]
then
echo "- $SERVICE is ACTIVE"
else
echo "- $SERVICE is NOT ACTIVE"
fi
return $RESULTTSS1
}
install-libvirt-modular-services() {
# Starting with YAKKO 8.0, it's all about libvirt MODULAR daemons
# https://libvirt.org/daemons.html
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/configuring_and_managing_virtualization/optimizing-virtual-machine-performance-in-rhel_configuring-and-managing-virtualization#assembly_optimizing-libvirt-daemons_optimizing-virtual-machine-performance-in-rhel
# #
# MONOLYTHIC DAEMON: libvirtd.service
# MONOLYTHIC SOCKETS: libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd-tcp.socket libvirtd-tls.socket
#
# MODULAR DAEMONS: virtqemud
# MODULAR DAEMONS SECONDARY: virtinterfaced virtnetworkd virtnodedevd virtnwfilterd virtsecretd virtstoraged
#
if [ "$YAKKOHOSTOSNAME" == "fedora" ]
then
if [ "$YAKKOHOSTOSRELEASE" -lt 36 ]
then
echo "As this system is earlier than Fedora 36, you should use an older version of YAKKO."
echo "Going forward YAKKO only uses modular libvirt daemons, which were released post Fedora 35."
echo
cleanup-and-exit 1
fi
fi
if [ "$YAKKOHOSTOSNAME" == "rhel" -a "$(echo $YAKKOHOSTOSRELEASE | tr -d .)" -lt 90 ]
then
echo "As this system is earlier than RHEL 9, it will remain under monolithic daemons."
echo "Going forward YAKKO only uses modular libvirt daemons, which were released post Fedora 35."
echo
cleanup-and-exit 1
fi
test-libvirt-monolithic-service-status libvirtd.socket
RESULTMONOLITHIC=$?
test-libvirt-monolithic-service-status libvirtd.service
RESULTMONOLITHIC=$(($RESULTMONOLITHIC+$?))
if [ $RESULTMONOLITHIC -eq 0 ]
then
#MONOLITHIC DAEMON IS IN USE
echo
echo "Legacy monolithic libvirt daemons are in use. YAKKO requires modular daemons going forward."
echo "For further information, visit https://libvirt.org/daemons.html or search \"optimizing modular libvirt daemons\""
ask-user "Do you want $YAKKONAME to update your system accordingly (Y) or exit (N)" "Y" noauto
if [ $? -ne 0 ]
then
# The update is not wanted. Too bad
echo "YAKKO will now exit. Please refer to the above URL and run $YAKKONAME again when ready."
cleanup-and-exit 1
fi
# KVM MODULAR SERVICES, yakko 8.0...
#Stop the current monolithic daemon and its socket units
echo
echo "Stopping and disabling legacy monolithic libvirt daemons..."
systemctl stop libvirtd.service
systemctl stop libvirtd{,-ro,-admin,-tcp,-tls}.socket
#Disable future start of the monolithic daemon
systemctl disable libvirtd.service
systemctl disable libvirtd{,-ro,-admin,-tcp,-tls}.socket
#For stronger protection it is valid to use mask instead of disable too.
else
#MODULAR DAEMONS ARE IN USE.
echo "Modular libvirt daemons are in use. $YAKKONAME will check and update to meet requirements."
fi
#Enable the new daemons for the particular virtualizationd driver desired, and any of the secondary drivers to accompany it. The following example enables the QEMU driver and all the secondary drivers:
echo
echo "Enabling modular libvirt daemons..."
for drv in qemu interface network nodedev nwfilter secret storage
do
systemctl unmask virt${drv}d.service
systemctl unmask virt${drv}d{,-ro,-admin}.socket
systemctl enable virt${drv}d.service
systemctl enable virt${drv}d{,-ro,-admin}.socket
done
sleep 2
#Start the sockets for the same set of daemons. There is no need to start the services as they will get started when the first socket connection is established
echo "Starting modular libvirt daemons..."
for drv in qemu network nodedev nwfilter secret storage
do
systemctl start virt${drv}d{,-ro,-admin}.socket
done
sleep 3
print-in-colour green "Modular libvirt daemon framework is active."
echo
}
process-system-service-state() {
# eg process-system-service-state restart virtqemud quietfast
# This is a general approach to handling the multiple systemctl restarts used in YAKKO
# in a better way of course ;)
SYSTEMSERVICEACTION=$1 # can be start, restart, force-restart
SYSTEMSERVICENAME=$2
# These are here to make the code more legible
BEQUIET=N
BEFAST=N
EXITONFAIL=N
case "$3" in
"quiet") BEQUIET=Y;;
"fast") BEFAST=Y;;
"quietfast"|"fastquiet") BEQUIET=Y;BEFAST=Y;;
"exitonfail") EXITONFAIL=Y;;
esac
case "$4" in
"quiet") BEQUIET=Y;;
"fast") BEFAST=Y;;
"quietfast"|"fastquiet") BEQUIET=Y;BEFAST=Y;;
"exitonfail") EXITONFAIL=Y;;
esac
#[ "$BEQUIET" == "N" ] && echo -n "Checking service [$SYSTEMSERVICENAME]."
if [ "$BEQUIET" == "N" ]
then
start-spinner "Checking service [$SYSTEMSERVICENAME]"
fi
case $SYSTEMSERVICEACTION in
"start"|"restart") systemctl restart ${SYSTEMSERVICENAME} &>/dev/null;;
"force-restart") systemctl reload-or-restart ${SYSTEMSERVICENAME} &>/dev/null;;
esac
WAITCYCLES=5 # sometimes services take their sweet time, we give 'em a chance
if [ "$BEFAST" == "Y" ]
then
WAITCYCLES=3
else
WAITCYCLES=10
fi
while [ $WAITCYCLES -gt 0 ]
do
systemctl is-active --quiet ${SYSTEMSERVICENAME} &>/dev/null
[ $? -eq 0 ] && break
((WAITCYCLES--))
sleep 1
done
stop-spinner
if [ $WAITCYCLES -eq 0 ]
then
if [ $EXITONFAIL == Y ]
then
check-for-error-and-exit 1 "Service [${SYSTEMSERVICENAME}] could not be ${SYSTEMSERVICEACTION}ed and is required, please review your system"
else
print-in-colour orange "ATTENTION: Failed to restart service [${SYSTEMSERVICENAME}]."
fi
fi
[ "$BEQUIET" == "N" ] && blank-line
}
set-selinux-state() {
selinuxenabled &>/dev/null
if [ $? -eq 0 ]
then
SELINUXSTATE=0
else
print-in-colour orange "SELinux is disabled in this system"
SELINUXSTATE=1
fi
}
check-ip-address-is-valid() {
# returns 0 if $1 is a proper IPV4 address
#
if [[ $1 =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]
then
return 0
else
return 1
fi
}
get-node-vm-name() {
# This is a safety measure...
# This function should be called as
# $(get-node-vm-name <kvm-machine-name>)
# it returns a KVM machine name
VMNAME=$1
echo ${VMNAME} | grep ${CLUSTERFQDN} | grep ${YAKKOID} &>/dev/null
[ $? -ne 0 ] && VMNAME=${VMNAME}.${CLUSTERFQDN}.${YAKKOID}
echo ${VMNAME}
}
get-node-fqdn() {
# This is a safety measure...
# This function should be called as
# $(get-node-fqdn $NODENAME)
# it returns a nodename with the FQDN attached
UNQUALIFIEDNAME=$1
# if the VM name has YAKKOID, we filter that and that's enough!
echo ${UNQUALIFIEDNAME} | grep ${YAKKOID} &>/dev/null
[ $? -eq 0 ] && UNQUALIFIEDNAME=$(echo $UNQUALIFIEDNAME | sed "s/\.$YAKKOID//")