diff --git a/group_vars/central-manager-secondary-host.yml b/group_vars/central-manager-secondary-host.yml new file mode 100644 index 000000000..54c9b02eb --- /dev/null +++ b/group_vars/central-manager-secondary-host.yml @@ -0,0 +1,62 @@ +--- +nspawn_name: htcondor +nspawn_distro: "rocky" +nspawn_release: "8" +nspawn_packages: + - dhcp-client + - dnf + - glibc-langpack-en + - iproute + - iputils + - less + - passwd + - systemd + - dbus + - vim-minimal + - openssh-server + +nspawn_config: | + [Files] + {% for mount in jwd.values() %} + Bind={{ mount.path }} + {% endfor %} + + [Exec] + NotifyReady=yes + PrivateUsers=no + + [Network] + VirtualEthernet=no + +nspawn_enable: false +nspawn_start: false + +nspawn_ssh: yes +nspawn_ssh_config_path: /etc/ssh/sshd_config +nspawn_ssh_config: + Port: "2222" + ListenAddress: "127.0.0.1" + PermitRootLogin: "yes" + PubkeyAuthentication: "yes" + AuthenticationMethods: "publickey" + PasswordAuthentication: "no" + PermitEmptyPasswords: "no" + ChallengeResponseAuthentication: "no" + PermitTunnel: "no" + AllowTcpForwarding: "no" + AllowAgentForwarding: "no" + GatewayPorts: "no" +nspawn_ssh_host_keys: + ecdsa: "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBF9MMtDEfPPSaHSNUFz3b1BBtasjGT1XB2my45Lhtp4NLJv/jPxpVQ8sxRSS3+8fc9+1EZXF0AGj4D1NjqpabmQ=" + ed25519: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHMTH60CkuT9moO66XVEaUP1YelPv/aOQdqSImNNiQFh" + rsa: "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDxIgnu5/BIIzVbWM442uzwyuXPQx0jqaVfffjexwewfc2mMNnVAG7mRzcWcgr+o/lFiogkqGulkvO/a+EARs5WsWrsq5bGFcHx9DPgaT+7smu+K3t0WNiqPEykXUJppyMtaYftZSWaCSl51pg3QT29pvl95sjC3URFrQhoaLHJ2fESYJI4WuMBig/rCLaRsF6xaR38LIVfrZdA7UjG5Ncr+FXF6cpNtdvDvJXkGyuYft2p9LMh7vycdiSUL/CluC6tptgQ82JGxgyHDaxwJvyzzDukjKTUkR59ctuGthq9M/M384sCn8Z3PsGE4hkRGdL/HJZhasPIkkwJK8ekucnBR2LzlCqiTrn7HFbndqgePhJWHq0tBN53o2Vmczrbq6UVROAFDCpPKeaWa6hcdqzp0fpHrgSZEyKmMxThV8sj69E/mCh2PEgWjCXsPoJLwrW9TuPUMeXx2+Cwf4/JaFSvLBT19ADFKkzgAPeEVdJg2ZkjWZVO+xxb9e6Ahux+g7E=" +nspawn_ssh_host_certs: + # valid from 2023-10-12T14:46:00 to 2033-09-29T14:47:45 + ecdsa: "ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgIkfzNxdybaCbJ+rziM3zQy/grFSitfDOJWQS2zH4I4MAAAAIbmlzdHAyNTYAAABBBF9MMtDEfPPSaHSNUFz3b1BBtasjGT1XB2my45Lhtp4NLJv/jPxpVQ8sxRSS3+8fc9+1EZXF0AGj4D1NjqpabmQAAAAAAAAAAAAAAAIAAAAXbWFuYWdlci1zZWNvbmRhcnktZWNkc2EAAAAAAAAAAGUoBqgAAAAAd+bbEQAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAMtAPp8bfy7AWP3UZJ7pidGcG5ONdZk3o9yTUlEJNa25/ApXRJk1zMP6pR2cV9msLH/AFUrxHrMvZVZL2FwUrUu4Twcrzp/yob+BwHrIW3/Qj89ahKNxtQw9BPMUjLzLG90ig9OWP8/r642DB5O8wUjj5Q64IjvUiEH+WJMefX/Z1dAz3hIV3hVB6D7dNzqAPESpFJLp0sirS69Hz/+W4imhbfzKHajPAeaMwpO8edt24aoeURLirP1xT2JmRag/NKn6qjEI6KMe/DMvm8PT+TiFn+InJPMMdAsOtrcpprzKRZ0RELGOkynXL11VDbeVXGn5RQC3dEc4JTX8q40z0+sAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQBbd3PNc1Ezs5BDCF/Ca02Oea4hL/L3Z1G4PO1W7y3IHAVW2hFmHBmJTd2r5tO/G+n/o03j+wr59ZfKYr4sj9c99oMXA19IRl+3a7ECnG6xpnepVA8FMo8qatcTyeOlECDbS8VI8Kc+cBuSu4UZjdCIZCFGzIj9dupK22id7D/UdeqDNTZ0b+KB0NOQM6lzyLaXD75U9kOFFzWmJqRYtkFns71dhzzr1i04V+ZaPlmSz2QZ20WIqt2hX6ecU+w3U2fK0PkFy/cy3YtSzhnNRiKnmJk1U4MOCbxWQ3rFOTopX514elUZAUCw3HCU+vBIOwwDIrVlbNuCEecuMtQUfLyW /etc/ssh/ssh_host_ecdsa_key.pub" + # valid from 2023-10-12T14:46:00 to 2033-09-29T14:47:55 + ed25519: "ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAILMcMkZV0MfVGEZghy0DD2dOMTtpjE5z0Hj6Cus/C8mjAAAAIHMTH60CkuT9moO66XVEaUP1YelPv/aOQdqSImNNiQFhAAAAAAAAAAAAAAACAAAAGW1hbmFnZXItc2Vjb25kYXJ5LWVjMjU1MTkAAAAAAAAAAGUoBqgAAAAAd+bbGwAAAAAAAAAAAAAAAAAAARcAAAAHc3NoLXJzYQAAAAMBAAEAAAEBAMtAPp8bfy7AWP3UZJ7pidGcG5ONdZk3o9yTUlEJNa25/ApXRJk1zMP6pR2cV9msLH/AFUrxHrMvZVZL2FwUrUu4Twcrzp/yob+BwHrIW3/Qj89ahKNxtQw9BPMUjLzLG90ig9OWP8/r642DB5O8wUjj5Q64IjvUiEH+WJMefX/Z1dAz3hIV3hVB6D7dNzqAPESpFJLp0sirS69Hz/+W4imhbfzKHajPAeaMwpO8edt24aoeURLirP1xT2JmRag/NKn6qjEI6KMe/DMvm8PT+TiFn+InJPMMdAsOtrcpprzKRZ0RELGOkynXL11VDbeVXGn5RQC3dEc4JTX8q40z0+sAAAEUAAAADHJzYS1zaGEyLTUxMgAAAQAno9IlnZ6TLhK83xx1+qjTL2+DjYsFTVeH0D97P7QdvZ3l4VnOWJH62V79VSNA4VQ7MRgoUZkeVY6Y2OBBItGGNxn0Z/9O/yE8csoqKE0L0LJNWoEU8Xbw/rs7rr4gIUqTNqzT42dSt7p6chht8+9iCSku8bKHmmnokQOnC/tF29zC5Iq4FQoVYDMgm0YO2MN9mJ6R9zEzkcu/cPWTjPM0FY9qs/RlK7yGQXcINAxaW4a5xdlMp85LWygGRLBn+gKiCwUATW1EPx7MkuHUx+vHzeKwRDsc904KxYD9TWsrSygFAfesLY2Xh6TDVdrPCnw096K7l9EcovgSCVWPV1mM /etc/ssh/ssh_host_ed25519_key.pub" + # valid from 2023-10-12T14:47:00 to 2033-09-29T14:48:11 + rsa: "ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgQuoZdMdY7Boli6KRlNmUk2zQar66du6kmLR4PkWoHI8AAAADAQABAAABgQDxIgnu5/BIIzVbWM442uzwyuXPQx0jqaVfffjexwewfc2mMNnVAG7mRzcWcgr+o/lFiogkqGulkvO/a+EARs5WsWrsq5bGFcHx9DPgaT+7smu+K3t0WNiqPEykXUJppyMtaYftZSWaCSl51pg3QT29pvl95sjC3URFrQhoaLHJ2fESYJI4WuMBig/rCLaRsF6xaR38LIVfrZdA7UjG5Ncr+FXF6cpNtdvDvJXkGyuYft2p9LMh7vycdiSUL/CluC6tptgQ82JGxgyHDaxwJvyzzDukjKTUkR59ctuGthq9M/M384sCn8Z3PsGE4hkRGdL/HJZhasPIkkwJK8ekucnBR2LzlCqiTrn7HFbndqgePhJWHq0tBN53o2Vmczrbq6UVROAFDCpPKeaWa6hcdqzp0fpHrgSZEyKmMxThV8sj69E/mCh2PEgWjCXsPoJLwrW9TuPUMeXx2+Cwf4/JaFSvLBT19ADFKkzgAPeEVdJg2ZkjWZVO+xxb9e6Ahux+g7EAAAAAAAAAAAAAAAIAAAAVbWFuYWdlci1zZWNvbmRhcnktcnNhAAAAAAAAAABlKAbkAAAAAHfm2ysAAAAAAAAAAAAAAAAAAAEXAAAAB3NzaC1yc2EAAAADAQABAAABAQDLQD6fG38uwFj91GSe6YnRnBuTjXWZN6Pck1JRCTWtufwKV0SZNczD+qUdnFfZrCx/wBVK8R6zL2VWS9hcFK1LuE8HK86f8qG/gcB6yFt/0I/PWoSjcbUMPQTzFIy8yxvdIoPTlj/P6+uNgweTvMFI4+UOuCI71IhB/liTHn1/2dXQM94SFd4VQeg+3Tc6gDxEqRSS6dLIq0uvR8//luIpoW38yh2ozwHmjMKTvHnbduGqHlES4qz9cU9iZkWoPzSp+qoxCOijHvwzL5vD0/k4hZ/iJyTzDHQLDra3Kaa8ykWdERCxjpMp1y9dVQ23lVxp+UUAt3RHOCU1/KuNM9PrAAABFAAAAAxyc2Etc2hhMi01MTIAAAEAOXRiZFs14HScCvi+9Hp51z310t0r3SHtHhE50vEjdAsnej+/yHUtlmaYJ1l4B8SWYHHUV94KxZbQP79D8PYQextXoYldA4Vp29ow33sYF8Mr4p7Jbjyyr4GVP9RAymiZz9cuiiRqjs8qwn/UCOw4A6yaix4k0EYTJa9bpbD3MsCxJbKEdZxxL72kIKf4sGuDrd77hEtRwJFUSqz+XD96TYG+BIomnrk35Oy+oyMGhoIlSM0//cS0pHUW8fpGnRIJJbBjDETwOmaMEF5yynRSeJyWnEBPpjcA+1i7wILSxYxZb5ckGxCABYxNvlIhF8Bvdcyb4eo7B/WeEdzr5C+Pzg== /etc/ssh/ssh_host_rsa_key.pub" +nspawn_ssh_authorized_keys: + - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDV7gfNbNN5O8vH6/tM/iOFXKBP2YKRHXOmdfV8ogvu9BdVV0IPmDzk2EooVpThDE1VMv1hz3811tvBhHRJ6IgNhVIV/61w/+RazQD/AU27X8bX+Hb9EQ/bP4DW+6ySd/z5vdDLzpH5dbiMhzPEDkXVsylUT+hkQnas6cHspDhHmtKQ5MWOgDe3D/IEudTDJQe8hxxaU4TaZUmFzn7eYp9HvuK8qW0yCy4NWOxJJHA+G5wSCyLuKnaKo4AitUIzSKF1AB94oq7b96KONhPxgRptAk4OYIUTdNFbrI5HDaSNzHLnF5FbjQvG+Eu6m5nY5yvJMogE+jiuWeIXCZTCFljg287FUo0ohmbZpd802L6VXun14VumRC+rRgPrvBALo/CsyCsPIoBSTKhVElxKVOcRjmTLNfrUZM0GQxqJhIvah8BV+JTExkipPwkrKTdMAWIXvCoehxV+WMpBWqtEEzAzEoqJpaiec7HfriwsHTGESZWAPYEbFjzbHXQZtqBkbOvtokPMRmTWfWKxaplCMN6ddJeeY6faorD0w/e6lszWES1Q1ieajiPKDy37UvybKKvPTk4o3MzyzYOS4c8HQj+jnGeR5Q3ETuyz4psLyOfuBtIrfOeuxV42rFDmkYM3IrrRR+F9oklFG6Ig8DVfgQEzSG36NkgvpF4OdFvigYqXvw== cloud@vgcn" +nspawn_ssh_host_trust_container: yes diff --git a/hosts b/hosts index 00594fcb5..0973c3b0b 100644 --- a/hosts +++ b/hosts @@ -78,3 +78,9 @@ ansible_ssh_user=centos [central-manager] manager.vgcn.galaxyproject.eu ansible_ssh_user=root + +[central-manager-secondary] +manager-secondary.galaxyproject.eu ansible_host=127.0.0.1 ansible_port=2222 ansible_ssh_user=root ansible_ssh_common_args='-o HostKeyAlias=manager-secondary.galaxyproject.eu -o ProxyCommand="ssh -W %h:%p -q root@sn06.galaxyproject.eu"' + +[central-manager-secondary-host] +sn06.galaxyproject.eu ansible_ssh_user=root diff --git a/htcondor-secondary.yml b/htcondor-secondary.yml new file mode 100644 index 000000000..455efeb54 --- /dev/null +++ b/htcondor-secondary.yml @@ -0,0 +1,181 @@ +--- +- name: Systemd-nspawn container aimed at running a second HTCondor installation. + hosts: central-manager-secondary-host + handlers: + - name: Reload sshd # (in the container) + when: nspawn_ssh | default(no) + become: true + ansible.builtin.shell: + executable: /bin/bash + cmd: "systemd-run --pipe --machine {{ nspawn_name }} /bin/systemctl reload sshd" + changed_when: true + vars_files: + - mounts/mountpoints.yml + - secret_group_vars/central-manager-secondary-host.yml + pre_tasks: + # Because it is already disabled for sn06 and this setup is needed just + # temporarily. + - name: Disable SELinux. + become: true + ansible.posix.selinux: + state: disabled + roles: + - kysrpex.systemd_nspawn + post_tasks: + - name: Configure the container's sshd. + when: nspawn_ssh and (nspawn_ssh_config is defined or nspawn_ssh_config_path is defined) + become: true + block: + - name: Get the location of the container image. + ansible.builtin.shell: + executable: /bin/bash + cmd: | + set -o pipefail + machinectl image-status htcondor | grep "Path: " | awk '{$1=$1};1' | cut -d' ' -f2 + register: nspawn_image + changed_when: false + + - name: Write the sshd configuration to sshd_config. + ansible.builtin.lineinfile: + path: "{{ (nspawn_image.stdout, nspawn_ssh_config_path | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + regexp: '^\s*(?:#)?\s*{{ item.key | regex_escape() }}' + line: "{{ item.key }} {{ item.value }}" + with_dict: "{{ nspawn_ssh_config }}" + notify: Reload sshd + + - name: Replace ssh host keys (private). + when: nspawn_ssh_host_keys is defined and nspawn_ssh_host_keys_private is defined + ansible.builtin.copy: + dest: "{{ (nspawn_image.stdout, nspawn_ssh_config_path | regex_replace('(\\/*)?(.*)', '\\2') | dirname, 'ssh_host_' + item.key + '_key') | path_join }}" + content: "{{ item.value }}" + mode: "0600" + with_dict: "{{ nspawn_ssh_host_keys_private }}" + notify: Reload sshd + + - name: Replace ssh host keys (public). + when: nspawn_ssh_host_keys is defined and nspawn_ssh_host_keys_private is defined + ansible.builtin.copy: + dest: "{{ (nspawn_image.stdout, nspawn_ssh_config_path | regex_replace('(\\/*)?(.*)', '\\2') | dirname, 'ssh_host_' + item.key + '_key.pub') | path_join }}" + content: "{{ item.value }}" + mode: "0644" + with_dict: "{{ nspawn_ssh_host_keys }}" + notify: Reload sshd + + - name: Replace ssh host keys (certs). + when: nspawn_ssh_host_keys is defined and nspawn_ssh_host_keys_private is defined and nspawn_ssh_host_certs is defined + ansible.builtin.copy: + dest: "{{ (nspawn_image.stdout, nspawn_ssh_config_path | regex_replace('(\\/*)?(.*)', '\\2') | dirname, 'ssh_host_' + item.key + '_key-cert.pub') | path_join }}" + content: "{{ item.value }}" + mode: "0644" + with_dict: "{{ nspawn_ssh_host_certs }}" + notify: Reload sshd + + - name: Add certs to sshd_config. + when: nspawn_ssh_host_keys is defined and nspawn_ssh_host_keys_private is defined and nspawn_ssh_host_certs is defined + ansible.builtin.lineinfile: + path: "{{ (nspawn_image.stdout, nspawn_ssh_config_path | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + regexp: '^\s*(?:#)?\s*HostCertificate\s+.*ssh_host_{{ item.key }}_key-cert.pub' + line: "HostCertificate {{ nspawn_ssh_config_path | dirname }}/ssh_host_{{ item.key }}_key-cert.pub" + with_dict: "{{ nspawn_ssh_host_certs }}" + notify: Reload sshd + + - name: Ensure the ssh configuration directory exists (for root). + when: nspawn_ssh_authorized_keys is defined + ansible.builtin.file: + path: "{{ (nspawn_image.stdout, '/root/.ssh' | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + state: directory + owner: root + group: root + mode: "0700" + + - name: Ensure the authorized_keys file exists (for root). + when: nspawn_ssh_authorized_keys is defined + ansible.builtin.file: + path: "{{ (nspawn_image.stdout, '/root/.ssh/authorized_keys' | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + state: touch + owner: root + group: root + mode: "0600" + + - name: Authorize specific users log-in as root. + when: nspawn_ssh_authorized_keys is defined + ansible.builtin.lineinfile: + path: "{{ (nspawn_image.stdout, '/root/.ssh/authorized_keys' | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + regexp: '^\s*(?:#)?\s*{{ item | regex_escape() }}' + line: "{{ item }}" + loop: "{{ nspawn_ssh_authorized_keys }}" + + - name: Enable and start the container. + become: true + block: + - name: Enable the container. + ansible.builtin.shell: + executable: /bin/bash + cmd: "machinectl enable {{ nspawn_name }}" + register: nspawn_container_enable + changed_when: nspawn_container_enable.rc == 0 and nspawn_container_enable.stderr != '' + + - name: Check if the container is already running. + ansible.builtin.shell: + executable: /bin/bash + cmd: "machinectl show {{ nspawn_name }} -p State --value" + register: nspawn_status + changed_when: false + failed_when: false + + - name: Start the container. + ansible.builtin.shell: + executable: /bin/bash + cmd: "machinectl start {{ nspawn_name }}" + register: nspawn_container_enable + changed_when: nspawn_status.stdout != 'running' + + - name: Enable and start sshd in the container. + when: nspawn_ssh | default(no) + become: true + block: + - name: Check if sshd is enabled in the container. + ansible.builtin.shell: + executable: /bin/bash + cmd: "systemd-run --pipe --machine {{ nspawn_name }} /bin/systemctl is-enabled sshd" + register: nspawn_ssh_enabled + changed_when: false + failed_when: false + + - name: Enable sshd in the container. + become: true + ansible.builtin.shell: + executable: /bin/bash + cmd: "systemd-run --pipe --machine {{ nspawn_name }} /bin/systemctl enable sshd" + changed_when: nspawn_ssh_enabled.rc != 0 + + - name: Check if sshd is active in the container. + ansible.builtin.shell: + executable: /bin/bash + cmd: "systemd-run --pipe --machine {{ nspawn_name }} /bin/systemctl is-active sshd" + register: nspawn_ssh_active + changed_when: false + failed_when: false + + - name: Start sshd in the container. + become: true + ansible.builtin.shell: + executable: /bin/bash + cmd: "systemd-run --pipe --machine {{ nspawn_name }} /bin/systemctl start sshd" + changed_when: nspawn_ssh_active.rc != 0 + + - name: Read the container's host key. + become: true + ansible.builtin.slurp: + src: "{{ (nspawn_image.stdout, '/etc/ssh/ssh_host_ecdsa_key.pub' | regex_replace('(\\/*)?(.*)', '\\2')) | path_join }}" + register: nspawn_ssh_host_key + when: nspawn_ssh_host_trust_container + + - name: Trust the container's host key. + ansible.builtin.known_hosts: + name: "[127.0.0.1]:{{ nspawn_ssh_config.Port }}" + key: "[127.0.0.1]:{{ nspawn_ssh_config.Port }} {{ nspawn_ssh_host_key.content | b64decode }}" + when: nspawn_ssh_host_trust_container + +- name: Secondary HTCondor 10 cluster. + hosts: central-manager-secondary diff --git a/secret_group_vars/central-manager-secondary-host.yml b/secret_group_vars/central-manager-secondary-host.yml new file mode 100644 index 000000000..14d38c096 --- /dev/null +++ b/secret_group_vars/central-manager-secondary-host.yml @@ -0,0 +1,191 @@ +$ANSIBLE_VAULT;1.1;AES256 +66343834346363613636373437646633383234663666373933313565383464656636623363353330 +6538336135356632653436633163363130323433656136610a663238666137386331656534616563 +37336663366136616531663638336361656134313432313363376230373765323234383639633637 +3439623166626430320a616338633064616332393038326363316264353036396165356363326536 +39613935653565313135646132366634323963656631303562666633656433346532643236376333 +35386261313532353663303532356230313636343533343761336639623062313532653935353432 +30666338363565383236623665643762306539636565623033623264343633613034393337363963 +39613031646139366436653263306661646166626437636463636164643037316666356532353136 +39323037663238313665323165316435663037383235386634313066316361363739653165356231 +33653439333865396435616630386533316332363537623763633865663736366465356435356233 +33386131313233316133373136393565303838316232316131353732613036653664343361636533 +61323964633935303266363065306361386666383833303464393439313335373230333665656439 +62626462363136363239323065323730306131353462343564663533316165306436653038383631 +33346164323466333738343830356230366239326662376330633164363165373732316238643361 +34666137656663303965306531323564363763653432353032373837646136353239646533613037 +31623539346135663930333735633838633166346138336134303561333230366632666164373730 +61323664613966366130376237393331623534613533356330643834653863393764613563363234 +30373333356231613361353137663965646236313832623732306130343230326263303234623038 +65613131653463353734373465653265323336656330666133653562363735306638343331623562 +39386430616463383662356233363666666561633062366461333866383664646337373738633530 +32386463656438346237373264333331656336653139356266343139633565323463343061636232 +39626261376633376366356663326436313934373266343237306531303631633864346238303135 +38666332313562303263336431366230633834663337626162353034646566646438643439303332 +65666431333038653866336336356432636665373439646631336139363834613830303066336235 +34306634643063633138663938623061623134323738333838636163346537356634393038396435 +62646661623335316134306432343430373139643538366362643239326166383337303030373338 +63373665653064373365376661626632396333383163333938366134326465326163393938386461 +31303836613963663839613962383838363932613732353739326464303764643733323736313166 +39303862316538386266393434356437356666303938386163393734663836356532373537663735 +36633438656438346462393438373036316533396630383464383266626135366362616464306134 +33373838326531303934656338646461616661383564616538653765313134303266343666346630 +62613430356663373566656438313132353939323334653466333235326261616161623031396331 +32643132316133306332396533663134326664643733636530383266383439383664336263396564 +61333837313938383933646165373465343633323736626136633262653462363435323036613965 +63363337373466646336323239386363376664336432313338323236353135333531396261396664 +61663338306563353533366134333962616638636536356666316130663865373536346263643662 +35633132373739373061626339663466363566626662333063643032663137373433643664653433 +35376263373131313834383263616266393337373761333631626639663562316566363134626538 +63316663323838386561653662326330633162646635646333383562343764646132653462623339 +66353833666435656466626263653535623166313437633536636333343836626366396336643330 +34393264336364386238346431303361373034616266323830316562343636633038616365386261 +34346139633830306466326539393433633763343235616236396633313363656537333732353762 +31396663663830363231326537343661666139373832303130353766343432653062616132363266 +64303866333466646132313164623738333135613763633736616436366138396135373635623335 +62303563613465323330366336323733663233376361616535346339626136353039373737623165 +65346338623032373064666461626434313235366638616565346331636461663036356438666666 +65653661616565653234383337343037383763613231383265616532303939643936633163343235 +64373430353330353131643436306364666562626466363839396631336164366161323639303037 +35366135613830343661386337303333323637623331306335306161326431383339336665323461 +64623162653633643132656232343336333965666130643564393432343432636464303363623537 +30396664333739393330323035323437396262303031353662316235353065646330303936326233 +35396264656661653234366631353530393835653637613861616164373036346666303564646566 +39386135323438653663323635643339363161323534306365353263313930653238336663386136 +32383038343039656434656336623762336662643335663433313361663039313134643237653831 +34323139623831666433343261313834393061613132343665643762356131323631626239653035 +66656331393965663337353137633266643531633130366131636433366161626231303830323131 +62343961313966343264653731623739393137663632373931313566656532313062306538313238 +62323631326539616139333666613032333937366530306638316631633361366263383836346366 +37383664666162346163626366396262353732633562376163333338646435653635613263343962 +62353735646266613564653061306465333439636431363539643637633438363038643231333665 +62396537383430386133643761393236393734393262313432636630643963386339363334636330 +64363564613663666431626164633339373932663462323365643031393064396263386263393630 +30623566616233363766653538343230323062346635303136326465333234383537333266393964 +34653131656366663238306265343933376439303839666261623266363361336465363834326365 +34653437666565363636623334333763353933336638346630376163336165373039313738613533 +36623932623263346661353464633961643733356438396531326237636234353136336666623365 +36633038313834653039646438643431613431383133363166653431366565376237303231363735 +31333936363531353639343334326235623532613934333866643336613964323635303836636638 +66356530613137343535663239626435303334336131383336633462613136383263373762623165 +64623533326537313062343539623035636135616539646337366533356430626439633235343462 +33306633646662396532396365326163316434356637306133616632343763373662623535373635 +32623466626436633030346438643332303331646565333466613161393731396564646136353632 +61366435376630643437363437653262333962316263666535663264313664666430613436373032 +36343564656361626266626266643533633463646263663234356539396664616639386633363235 +38326335386332373463323432633563353131623032373562353264393962623737633438373339 +36633030306532353639633834656462633338663738353330613536616266613233373931323238 +63656165376162393339333435393338313562376266666464363938646461353130346264336630 +32373737633639643866323334353234613131366363663134633937653261613137323531373062 +33616230636236666362313762643237333030613031336134633732653430313061373265333236 +66646262333737303233313965326131326163343035616435313864383963646234616334666639 +32343238393736356466346366636363653531353133396164393030333865653135646463363132 +63386233313331653239643638376238353630393038343066323363363264323362626135613735 +37626239653833323066623561343831393035663939643165356135663931386365333635313338 +36663962356236316631366132363830666264636263326235623831656335306630333933656536 +32643631376136353334653032333930613134333533323633616534613337613434333039656533 +38353839363630613436396233346130366439316433616234356135373335343134316164373038 +64373434346464396363323962363465613935636439393036643737326463373638663562333334 +38393963666533343830353366303535353635653264333465373831373636613233386530353232 +38613963653261303461386536363863303934333139333063396231623366613434626363306137 +62353539383561663439373232386164356235313034373338656161396339346136333430346630 +39343462343737653532656137363433313761326464353564303138623861343637616632363131 +65616463333461363962353939653336663466643135316565393066396236326630636264663666 +62303564383339373839333338383835623138396337376135663132393766306438356333643933 +30316165623230346138633166313265346263653034643235633638313835323935616261303338 +61326538353663623236376432343332366536643231636537356564633362383733393731346230 +39316632356633373464616332353034366632383830623833353930366132633633363231363436 +66323235623635343265346336353366613933323433633338383031386162633762333465613939 +36353966646464626362663730336439323265643437656438373165363933656635643235656633 +34303535613434653862646661356131323330303961393535366231626135633437303036303133 +34633661363035323065666136636631363834653939303932623964353961333636343831656564 +35333661383561653832646361333663316563666136616539326665653864623638306162313935 +33393735393838323234343831633933393631646131363032356230333464653538306262333339 +37363263613830313434623632333732393433336234323533316364613434313536353634626133 +35366337643631313061343764376334313263303766363031356335643963633964363731373031 +36303063653861613236363033366532343131346166353837303434363638386437383665373931 +31376132313437653034623964646635623037383363383134383134613833313430373532303166 +61333166653939663362616536646339316462313033353338383935376237363563636238663237 +32396665363234333936366531646263383934326133303565303465386533313133386364613765 +64363338383462363434613732653034326366356335306361333466613564316565323832353231 +33613432366661353733613532396565383938386431376430646139623265336161356466356365 +64363037663131343639653131326235366662663835313536383266326433313338646637313261 +34393132633439313432346235636535363766326232323232303335383635386130356664653531 +32643034306661393966316437306165626231666665306239326165363062653762623334343735 +30636335326639313433646330396364653935303265376163356533646335663533633831616261 +34623038363762393963323530626538333739353063376532396337333238383762316164616461 +37303834633264643164396330313835363861303663346531663736373263306330386138383232 +34643763643633333430616136663137316639303662333937326134366230386362306263656434 +33353730363234336165313863353265306462383465343638383766303632636365653835393263 +65366165343530353235346530656435393461343863366466653765313734343338323665643265 +39393533383962616135343662346631336632383439393034366261346562656330393861346632 +61303433336334636638616438313034373130346235666435363730646231383136323738643933 +66636265316263393930623564346436616164633465363262656661316134343066323132656130 +33313336646439326364396430306464326133633266643639626533643266346337643631353438 +39656536633039306266326139316636363662646534306531373132373030623634616239633430 +36343439303164646234636665633330313335656435316539633836333037626234323034376162 +34616333306638396131313433643833386166626165396465666631336333343864373036343533 +31313363666161613362363433626562313531656436376661643639323864623330346365353239 +38646262353465333132616330646462613361306166323039373933323536343832613763353365 +32623261333835383634376639316330356565623339623862663332633766353165303835326431 +62363162643138663465356539616465373035343035396338663931666430336239313238396461 +34373766626634383763656161386537306638396438626136323230356337643932653966336138 +31613831366432326438363638633661613866366363633736363566633466303961333639666136 +30366634343235343862386535373866386238393439386431363264353932333534313830663537 +34303366643630656633363436303062666164633736663039393839353737333331336336393434 +33643663383039346261346230326637646461343730313633323964333838373434353463663935 +36616663313439393031646134663139313238323561636462373132306339343166326634333063 +61353931363233363663623130383236633337643633356434383665353431633666336136643163 +39636339643835393330663432396130626632363231653765326462653537373032306432373161 +61303732663631623933393862623663383631306333306363656362313262353632626463636433 +35333330333935323138323862666563306536656666316331333135313234303936646262613433 +62323064353265663235336363396533363435383033616336393166323938373933306430306564 +65623864383436396332643837363233616266386436313131333136623330343339386136666439 +37383730323832653930623436656631343130396333396366643966373730303866386662646365 +39633865313866316165373966613032316536373066646432656438636261306530643863366537 +38616437303730373632333830346530653934643832383631353737306562343565393133306433 +30366335613433393166326536333465346361343537626538316532363435383138313737643332 +63353631316232666364363939653930666165653237323435643464656337363036666435643565 +35356665636163636237366131346435363263343364336666326565373830336165613536376634 +32366434663265653437306163363466653831663362633762333934313566613961653663333734 +33643630303037383430313963666336636230663430336437653236623064633137366566666339 +64306137626262336539396635383830646234633833383033303835366530366362663432313138 +64333635333439616663383263626166383632623461326364306463386463336362613335363564 +39646439343131643331396635613339626566386631626561613537396365356230303535656330 +39633936396531316437383165326637333565313338636366626466646237613666373563653261 +63313132373139383863326333666537626364303339323261356138393137356363653664643837 +35356339336534623139623133643932313131323331646135623965633535323164316362336136 +30626537646365346662613265326330393637333762666635386437313232313331316562616661 +64323964373436386362656435646239396139616564363865636430346463653664336666313565 +65653765313930393864306339306132303330636636396330306465363464643839666430636333 +39343533356165376536306330656138316539663032363664386134363164623836323739303662 +65353131313433363436346431376462633638626139336233346435336230303032373232663262 +62616261653836343435633338346261363064336339333731643932616262613538633532633964 +66626530336637373437663562326433663864613434313030386631656230323732303634373831 +62343139373931633230656166616466373864656665353566386234626438656630323665613363 +30346361656237316334353939373231366139336235326663343764326661323330343062326562 +38643431313537373130316238646537346332303536376563323636363634663430623965376531 +61643431646137333939633862373565366361643036303766646661306663363164393838323637 +63626566313662633865303733656436633630386435333933656137383863336634393630326133 +66383935333832663866663461343034303764663338303362666231373563343938333431386465 +34343331613734623263666261316231636433613531646239666531303765643039613939393533 +63393736313131643838666134636336303831386633323666373462366164303234666265623238 +61393633663132656464333336646334643131393433343062363032643038393537356437643265 +38373438613161666433353361633863383737346361306563363732626234643966646336353639 +37356536313036323933616162343962613530323366366131656132376437613233303335656162 +61373164663666303434396564363335343065323033613762386264323966663165336631636533 +37303434656530343463636465326533373164633736353132346638356165373066353964626162 +36376163626263373236366638373935643231366139353964656265343134653365376339373566 +66363735616633393164343032346235376365646436626431643634333262336365613237313339 +31666432353437663262646437643837373134303635353336323565353263333561386436383737 +65363231336563643530633037316462626461613061356631343761626635393562333834653263 +63373932313763616235626461643337346634383039633765616164343730343830303030613737 +39383631626163353965643234376136363333373739373833313933376362316466356639653666 +66383839616634663830333464363466343130613238383663626233376237336337333330386232 +62343565333262643265346232643138333935303936366233373035633036396465643237316261 +31653733333030366564626337353134396465396438303431316466656631383136616562666634 +32346635343437306263383962616531663139663537613264613337656337353163633530653039 +34643332663630633631313861653735303966353936356332626133323564623962313862376563 +66343430623639306230626662343165666535316138343334643231393661336635613830303866 +30383131323531343232613137613933376539303264343064646234353131303164326361326534 +3766313064663239653864643735336337656334376630646639