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
|
# Far-Edge Automation Stack Deployment Guide
The Far-Edge automation stack consists of nine Ubuntu 18.04 hosts:
- Two load balancers
- Two middleware application hosts
- Two ansible hosts
- Three database hosts
The provisioning of these hosts in openstack is outside the scope of
this document. There will be a separate document to address this.
There is an additional host in the production stack to handle LDAP
dual-stack proxying to reach USWIN. This host does not live in the
automation stack tenant space. It is a standalone VM managed by VCPe.
## OpenStack tenant space
In both production and MTCE the far-edge automation stack runs in an
OpenStack tenant space. (Production runs in VCPe.) Creating the
OpenStack objects (neutron networks, cinder volumes, instances) is
beyond the scope of this document and will be documented separately.
Secgroup rules must be created to allow network traffic. Use a script
like the following to create the secgroup rules:
#!/bin/bash
private_network_cidr="2001:4888:a21:3102:245:29::/112"
public_network_cidrs="2001:4888::/32"
for name in default-grp; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for protocol in tcp udp; do
if [ "openstack security group show ${name} -f shell -c rules | grep -F 'ingress' | grep -F \"port_range_min='1'\" | grep -F \"port_range_max='65535'\" | grep -F \"${protocol}\" | grep -F 'IPv6'" == "" ]; then
openstack security group rule create --egress --protocol ${protocol} --src-ip ::/0 --dst-port 1:65535 --ethertype IPv6 ${name}
fi
done
for cidr in ${private_network_cidr} ${public_network_cidrs}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"icmp\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol icmp --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
for port in 22; do
for cidr in ${private_network_cidr} ${public_network_cidrs}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
for name in icinga; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for port in 5665; do
for cidr in ${private_network_cidr}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
for name in ldap; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for port in 636; do
for cidr in ${private_network_cidr}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
for name in web; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for port in 443 3000; do
for cidr in ${private_network_cidr} ${public_network_cidrs}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
for port in 80 3000 3080 3128:3130 8000; do
for cidr in ${private_network_cidr}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
for name in galera; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for port in 3306 4444 4567 9200 13306; do
for cidr in ${private_network_cidr}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
for name in zmq; do
openstack security group show ${name} || openstack security group create --description "${name}" ${name}
for port in 5555:5559; do
for cidr in ${private_network_cidr}; do
if [ "$(openstack security group show ${name} -f shell -c rules | grep -F \"port_range_min='${port}'\" | grep -F \"remote_ip_prefix='${cidr}'\")" == "" ]; then
openstack security group rule create --ingress --protocol tcp --dst-port ${port} --src-ip ${cidr} --ethertype IPv6 ${name}
fi
done
done
done
exit 0
## Database
```far_edge_ops_api``` and icinga2 require a database backend. We
currently use postgresql. The goal is to migrate to
galera/mariadb. For now we are using only one database host, but when
we switch to galera we will use all three. The galera solution is
dockerized. It is a mature and well-tested product of the VCP Metering
project.
### Installation
Install postgresql on the first database host per the typical
procedure that can be found on the internet. TODO: provide a link to
an internet HOWTO that best fits our needs.
#### postgresql.conf:
data_directory = '/var/lib/postgresql/12/data'
listen_addresses = '*'
port = 5432
max_connections = 2000
password_encryption = md5
ssl = off
shared_buffers = 2000MB
work_mem = 4MB
maintenance_work_mem = 256MB
dynamic_shared_memory_type = posix
wal_buffers = 2MB
checkpoint_timeout = 15min
max_wal_size = 1GB
min_wal_size = 80MB
checkpoint_completion_target = 0.9
logging_collector = on
log_directory = '/var/lib/postgresql/12_log/'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_size = 50MB
log_min_duration_statement = 5
log_checkpoints = on
log_connections = on
log_disconnections = on
log_duration = on
log_error_verbosity = default
log_line_prefix = '%m, %d, %a. %r, %s, %x, %p '
log_timezone = 'GMT'
autovacuum = on
idle_in_transaction_session_timeout = 43200000
datestyle = 'iso, dmy'
timezone = 'GMT'
lc_messages = 'en_US.utf8'
lc_monetary = 'en_US.utf8'
lc_numeric = 'en_US.utf8'
lc_time = 'en_US.utf8'
default_text_search_config = 'pg_catalog.simple'
plperl.on_init = 'use utf8; use re; package utf8; require "utf8_heavy.pl";'
#### pg_hba.conf:
local icinga icinga md5
local all all password
local replication postgres trust
host icinga icinga 127.0.0.1/32 md5
host icinga icinga ::1/128 md5
host all all 127.0.0.1/32 password
host all all ::1/128 password
host icinga icinga 2001:4888:a21:3102::/32 md5
host all all 2001:4888:a21:3102::/32 password
#### sysctl.conf:
Configure ```kernel.shmmax``` and ```kernel.shmall``` to be 25\% of
available RAM. For example on a 16GB host:
kernel.shmmax=4199411712
kernel.shmall=4199411712
### User and database creation
As the postgres user:
# createuser -l -P -e faredge
# createdb -e -O faredge faredge
We do not need to populate the database with a schema. Django will do
this automatically.
## Load Balancers
The services which run on the loadbalancer hosts are as follows:
- apache
- haproxy
- icinga2
### Apache
#### SSL Certificates:
A prerequisite for configuring apache is an SSL x509 certificate that
answers to the following names:
middleware.<fqdn>
icinga.<fqdn>
dns-admin.<fqdn>
Place the certificate in ```/etc/ssl/certs/``` and the key in
```/etc/ssl/private```.
#### Modules:
Apache needs the following modules enabled:
- access_compat.load
- alias.conf
- alias.load
- auth_basic.load
- authn_core.load
- authn_file.load
- authz_host.load
- authz_user.load
- authz_core.load
- autoindex.conf
- autoindex.load
- deflate.conf
- deflate.load
- dir.conf
- dir.load
- env.load
- filter.load
- http2.load
- mime.conf
- mime.load
- mpm_prefork.conf
- mpm_prefork.load
- negotiation.conf
- negotiation.load
- php7.2.conf
- php7.2.load
- proxy.conf
- proxy.load
- proxy_http.load
- proxy_http2.load
- proxy_wstunnel.load
- reqtimeout.conf
- reqtimeout.load
- rewrite.load
- setenvif.conf
- setenvif.load
- socache_shmcb.load
- ssl.conf
- ssl.load
- status.conf
- status.load
#### VirtualHosts:
Apache needs the following sites enabled:
- dns-admin.conf
- far_edge_ops_api.conf
- icinga.conf
- webdav.conf
```webdav.conf``` is only needed when an external HTTP share is not
available.
##### dns-admin.conf:
<VirtualHost [2607:f160:b:10f1::e]:443>
ServerName dns-admin.faredge.vzwops.com
ServerAdmin carlos.konstanski@verizonwireless.com
Protocols http/1.1
SSLEngine on
SSLProxyEngine on
SSLCertificateFile /etc/ssl/certs/vcpfe-lb-vip.faredge.vzwops.com.pem
SSLCertificateKeyFile /etc/ssl/private/vcpfe-lb-vip.faredge.vzwops.com.key
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder on
SSLCompression off
SSLOptions +StrictRequire
ProxyPass "/" "http://[::1]:13000/"
ProxyPassReverse "/" "http://[::1]:13000/"
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
ErrorLog "/var/log/apache2/dnsadmin_error_log"
CustomLog "/var/log/apache2/dnsadmin_access_log" common
</VirtualHost>
##### far\_edge\_ops\_api.conf:
<VirtualHost [2607:f160:b:10f1::e]:443>
ServerName middleware.faredge.vzwops.com
ServerAdmin carlos.konstanski@verizonwireless.com
Protocols http/1.1
SSLEngine on
SSLProxyEngine on
SSLCertificateFile /etc/ssl/certs/vcpfe-lb-vip.faredge.vzwops.com.pem
SSLCertificateKeyFile /etc/ssl/private/vcpfe-lb-vip.faredge.vzwops.com.key
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder on
SSLCompression off
SSLOptions +StrictRequire
ProxyPass "/" "http://[::1]:13080/"
ProxyPassReverse "/" "http://[::1]:13080/"
ErrorLog "/var/log/apache2/middleware_error_log"
CustomLog "/var/log/apache2/middleware_access_log" common
</VirtualHost>
##### icinga.conf:
<VirtualHost [2607:f160:b:10f1::e]:443>
ServerName icinga.faredge.vzwops.com
ServerAdmin carlos.konstanski@verizonwireless.com
DocumentRoot "/usr/share/icingaweb2/public"
SSLEngine on
SSLProxyEngine on
SSLCertificateFile /etc/ssl/certs/vcpfe-lb-vip.faredge.vzwops.com.pem
SSLCertificateKeyFile /etc/ssl/private/vcpfe-lb-vip.faredge.vzwops.com.key
SSLProtocol all -SSLv2 -SSLv3
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
SSLHonorCipherOrder on
SSLCompression off
SSLOptions +StrictRequire
<Directory "/usr/share/icingaweb2/public">
Options SymLinksIfOwnerMatch
AllowOverride None
<IfModule mod_authz_core.c>
<RequireAll>
Require all granted
</RequireAll>
</IfModule>
SetEnv ICINGAWEB_CONFIGDIR "/etc/icingaweb2"
EnableSendfile Off
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteRule ^.*$ index.php [NC,L]
</IfModule>
</Directory>
</VirtualHost>
##### webdav.conf:
<VirtualHost *:80>
ServerName webdav.faredge.vzwops.com
ServerAdmin carlos.konstanski@verizonwireless.com
DocumentRoot "/var/www/html/webdav"
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
ErrorLog "/var/log/apache2/webdav_error_log"
CustomLog "/var/log/apache2/webdav_access_log" common
<Directory "/var/www/html/webdav">
AllowOverride limit
Options Indexes FollowSymLinks
</Directory>
</VirtualHost>
##### Webdav directory:
Create this directory only if you don't have access to an external HTTP share and you are using the webdav VirtualHost above:
- /var/www/html/webdav
### HAProxy
Use the following haproxy config, adjusting IP addresses, hostnames and credentials as needed:
global
tune.ssl.default-dh-param 2048
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
maxconn 5000
user haproxy
group haproxy
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
option dontlognull
timeout connect 10s
timeout client 60s
timeout server 180s
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats
bind 127.0.0.1:1993
mode http
option httplog
option forwardfor
stats enable
stats uri /stats
stats auth someuser:somepass
stats refresh 30s
stats show-node
stats hide-version
log global
frontend dns-admin
bind 0.0.0.0:13000
bind :::13000
mode http
option httplog
option forwardfor
default_backend dns-admin-backend
backend dns-admin-backend
balance roundrobin
mode http
option log-health-checks
option httpchk GET /dns HTTP/1.1\r\nHost:\ dns-admin.faredge.vzwops.com\r\nUser-Agent:\ curl/7.35.0\r\nAccept:\ */*\r\nAuthorization:\ Basic\ b3BlbmJvb2s6WnlsejNmZE1TZDhTVmlod0w5TnlaTHpU
default-server inter 10s fall 1 rise 1
server server-1 [2607:f160:b:10f1::7]:80 check
#server server-2 [2607:f160:b:10f1::8]:80 check
frontend far_edge_ops_api
bind 0.0.0.0:13080
bind :::13080
mode http
option httplog
option forwardfor
reqdel ^Host:
reqadd Host:\ middleware.faredge.vzwops.com
default_backend far_edge_ops_api-backend
backend far_edge_ops_api-backend
balance roundrobin
mode http
option log-health-checks
option httpchk GET /caas/ HTTP/1.1\r\nHost:\ middleware.faredge.vzwops.com\r\nUser-Agent:\ curl/7.35.0\r\nAccept:\ */*\r\nAuthorization:\ Basic\ bWlkZGxld2FyZXVzZXI6bWlkZGxld2FyZXBhc3N3b3Jk
default-server inter 10s fall 1 rise 1
server server-1 [2607:f160:b:10f1::6]:3080 check
#server server-2 [2607:f160:b:10f1::5]:3080 check
We currently only proxy to one backend for both ```dns-admin``` and
```far_edge_ops_api``` because there has been no opportunity to test
the behavior of the apps in a multiple-backend configuration. This is
why ```server-2``` is commented out. TODO: update this document when
this testing is complete.
### Icinga2
The icinga2 configuration is mostly standard. TODO: provide a link to
an internet HOWTO from which the rest of this documentation can
build. There will be only minor additions to the standard base
install.
## Jenkins
The applications are built and deployed from jenkins. The build jobs
already exist. But a new deploy job needs to be added for the new
environment which you are building.
### env.yaml
All of the far-edge builds and deploymenets are run on the jenkins
slave ```openbook-docker-slave-4.meter.vzwops.com```. Log onto this
host and edit three files in the jenkins home directory
```/var/lib/jenkins/```:
- env.yaml.ansible-queue
- env.yaml.dns-admin
- env.yaml.far-edge-ops-api
A new deployment target section needs to be added to each of these
files. Give the environment a new unique name and use the same name in
all three files.
### jenkins-job-builder (jjb)
Clone the following git repo onto your laptop:
git@gitlab.verizon.com:ONV6661_VCPSPUBLIC/jjb.git
Create an ini file called ```verizoncloudplatform.com.ini``` in the
top-level directory of your jjb git checkout with the following
contents:
#### verizoncloudplatform.com.ini:
[job_builder]
ignore_cache=True
keep_descriptions=False
include_path=.:scripts:~/git/
recursive=False
exclude=.*:manual:./development
allow_duplicates=False
[jenkins]
user=<your_jenkins_username>
password=<your_jenkins_api_token>
url=https://openbook-jenkins-master.meter.vzwops.com:8080/
timeout=120
query_plugins_info=False
Follow these steps to create the new deploy jobs:
- Open the file ```yaml/verizoncloudplatform.com/deploy-vcpfe.yaml```
in an editor.
- Add three new jobs to the list, one for each app
(```ansible-queue```, ```dns-admin``` and
```far-edge-ops-api```). Set the target attribute to the new ansible
target which you created in env.yaml in the previous section.
- ```# ./run.sh verizoncloudplatform.com```
Once this is done, log into the jenkins UI to verify that the new jobs
were created.
Push your jjb changes to git. (The ini file is gitignored; it is your
private file.)
## Application hosts
The services which run on the application hosts are as follows:
- far_edge_ops_api
### far\_edge\_ops\_api
The middleware (as ```far_edge_ops_api``` is ubiquitously known) is a
docker containerized django web application.
#### Build/deploy
The application can be built and deployed from jenkins:
https://openbook-jenkins-master.meter.vzwops.com:8080
Run the job ```docker-container-far-edge-ops-api``` to build the
docker container, and the appropriate
```far-edge-ops-api-deploy-vcpfe-<env>``` job to deploy it to an
environment.
#### Configure
It might seem backwards to perform the build and deployment before
configuring. It's a chicken-and-egg problem: the deployment needs to
create the required files and directories before configuration can
commence. For first-time deployments the process will look like: build
-> deploy -> configure -> deploy. This is true of all three
applications.
The main configuration directory is ```/etc/far-edge-ops-api/```. It
looks like the following on a working system:
$ tree /etc/far-edge-ops-api/
/etc/far-edge-ops-api/
├── modules.d
│ ├── wsgi.conf
│ └── wsgi.load
├── settings.py
└── vhosts.d
└── far-edge-ops-api.conf
```settings.py``` is a rather long file, too long to include here. Get
a copy from a known good source (a production or lab server) and edit
to suit the new environment.
```far-edge-ops-api.conf``` is a rather typical-looking apache
VirtualHosts file, but with LDAP auth added. First the file:
##### far-edge-ops-api.conf:
LDAPTrustedGlobalCert CA_BASE64 "/etc/apache2/auth/uswin_ca.pem"
LDAPTrustedGlobalCert CA_BASE64 "/etc/ssl/certs/selfsigned_root_cert.crt"
LDAPTrustedMode SSL
LDAPLibraryDebug 7
<VirtualHost *:3080>
ServerName middleware.<fqdn>
DocumentRoot "/opt/far-edge-ops-api/src/src"
WSGIScriptAlias / /opt/far-edge-ops-api/src/src/far_edge_ops_api/wsgi.py
WSGIDaemonProcess middleware.<fqdn> processes=20 threads=15 display-name=%{GROUP} python-home=/opt/far-edge-ops-api/src/venv
WSGIProcessGroup middleware.<fqdn>
Alias /static/ /opt/far-edge-ops-api/src/src/static/
TimeOut 600
SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
ErrorLog "/var/log/apache2/far-edge-ops-api_error_log"
CustomLog "/var/log/apache2/far-edge-ops-api_access_log" common
</VirtualHost>
<Directory "/opt/far-edge-ops-api/src/src">
AllowOverride all
Options FollowSymlinks
AuthName "USWIN"
AuthType Basic
AuthBasicProvider ldap
AuthLDAPURL "ldaps://vcpfe-ldap-prod.vcpfe.vzwops.com:636/DC=uswin,DC=ad,DC=vzwcorp,DC=com?sAMAccountName?sub?(objectclass=*)"
AuthLDAPBindDN "CN=SVC-VCP-LDAP,OU=SVC,OU=FNA,DC=uswin,DC=ad,DC=vzwcorp,DC=com"
AuthLDAPBindPassword "<password_for_SVC-VCP-LDAP_account>"
Require valid-user
</Directory>
<Directory "/opt/far-edge-ops-api/src/src/static">
AllowOverride limit
Require all granted
Options Indexes FollowSymLinks
</Directory>
There are two SSL certs because the far-edge stack is IPv6-only while
the production LDAP endpoint (USWIN) is IPv4-only. So we must use a
proxy. The first cert is the actual uswin cert, while the second cert
is the one for the proxy. Both of these certs must be placed on the
app hosts.
Replace ```<fqdn>``` with the DNS domain. Replace
```<password_for_SVC-VCP-LDAP_account>``` with the correct password.
OpenLDAP needs to be configured with these same certs. Since they are
self-signed, openldap will reject them unless they are listed as
exceptions.
#### /etc/ldap/ldap.conf:
TLS_CACERT /etc/apache2/auth/uswin_ca.pem
LDAPTLS_CACERT /etc/ssl/certs/self_ca_signed_cert_and_key_2.pem
Now that the configuration is complete, rerun the deployment from
jenkins. This time the application should start normally.
## Queue hosts
The services which run on the application hosts are as follows:
- ansible-queue
- dns-admin
### ansible-queue
```ansible-queue``` is a docker containerized common lisp
application.
#### Build/deploy
The application can be built and deployed from jenkins:
https://openbook-jenkins-master.meter.vzwops.com:8080
Run the job ```docker-container-ansible-queue``` to build the docker
container, and the appropriate ```ansible-queue-deploy-vcpfe-<env>```
job to deploy it to an environment.
#### Configure
Two files are required in the directory ```/etc/ansible-queue/```:
- .ansible_pass.far_edge
- options.lisp
```.ansible_pass.far_edge``` is the ansible vault password
file. Obtain a copy from an existing queue host.
```options.lisp``` is the config file for the ```ansible-queue```
application.
##### options.lisp:
((:queue (:num-icinga-process-threads 1
:num-bmc-process-threads 30
:num-nic-process-threads 20
:num-wr-process-threads 25
:num-dns-process-threads 1
:num-patch-process-threads 1
:num-hw-process-threads 20
:num-fix-process-threads 20
:icinga-wait-interval 0
:bmc-wait-interval 1
:nic-wait-interval 30
:wr-wait-interval 0
:dns-wait-interval 0
:patch-wait-interval 30
:hw-wait-interval 1
:fix-wait-interval 1
:sleep-interval 60
:ipv6 t
:vault-password-file "/etc/ansible-queue/.ansible_pass.far_edge"
:icinga-queue-url "tcp://*:5555"
:bmc-queue-url "tcp://*:5556"
:nic-queue-url "tcp://*:5557"
:wr-queue-url "tcp://*:5558"
:dns-queue-url "tcp://*:5559"
:patch-queue-url "tcp://*:5560"
:hw-queue-url "tcp://*:5561"
:fix-queue-url "tcp://*:5562"
:middleware-url "https://middleware.vcpfe.vzwops.com"
:middleware-username "SVC-Far-Edge"
:middleware-password "<password_for_SVC-Far-Edge_account>")))
Replace ```<password_for_SVC-Far-Edge_account>``` with the correct
password.
Now that the configuration is complete, rerun the deployment from
jenkins. This time the application should start normally.
### dns-admin
```dns-admin``` is a docker containerized web application written in
common lisp and clojurescript.
#### Build/deploy
The application can be built and deployed from jenkins:
https://openbook-jenkins-master.meter.vzwops.com:8080
Run the job ```docker-container-dns-admin``` to build the docker
container, and the appropriate ```dns-admin-deploy-vcpfe-<env>``` job
to deploy it to an environment.
#### Configure
Only one new config file is required. Use the following content
verbatim:
##### /etc/dns-admin/conf.lisp:
(:name "dns-admin"
:document-root "dns-admin"
:title "DNS Administration"
:meta-description "A website for administering DNS. Supports nsupdate and infoblox."
:dns (:label "CDS Infoblox"
:backend-type "infoblox"
:url "https://infoblox.alias/wapi/v2.6"))
Notice the odd-looking hostname ```infoblox.alias```. The following
needs to be added to ```/etc/hosts```:
2607:f160:8a02:8016:a0:103:0:10 infoblox.alias
Now that the configuration is complete, rerun the deployment from
jenkins. This time the application should start normally.
|