mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
* Update to 4.20.0
* Update to python3
* Upgrade to JRE 17
* Upgrade to Debian 12.4.0
* VR: upgrade to python3
for f in `find systemvm/ -name *.py`;do
if grep "print " $f >/dev/null;then
2to3-2.7 -w $f
else
2to3-2.7 -p -w $f
fi
done
* java: Use JRE17 in cloudstack packages and systemvmtemplate
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
* Add --add-opens to JAVA_OPTS in systemd config
* Add --add-opens to JAVA_OPTS in systemd config for usage
* python3: fix "TypeError: a bytes-like object is required, not 'str'"
* python3: fix "ValueError: must have exactly one of create/read/write/append mode"
* Add --add-exports=java.base/sun.security.x509=ALL-UNNAMED for management server
* Use pip3 instead of pip for centos8
* python3: fix "TypeError: write() argument must be str, not bytes"
```
root@r-1037-VM:~# /opt/cloud/bin/passwd_server_ip.py 10.1.1.1
Traceback (most recent call last):
File "/opt/cloud/bin/passwd_server_ip.py", line 201, in <module>
serve()
File "/opt/cloud/bin/passwd_server_ip.py", line 187, in serve
initToken()
File "/opt/cloud/bin/passwd_server_ip.py", line 60, in initToken
f.write(secureToken)
TypeError: write() argument must be str, not bytes
root@r-1037-VM:~#
```
* Python3: fix "name 'file' is not defined"
```
root@r-1037-VM:~# /opt/cloud/bin/passwd_server_ip.py 10.1.1.1
Traceback (most recent call last):
File "/opt/cloud/bin/passwd_server_ip.py", line 201, in <module>
serve()
File "/opt/cloud/bin/passwd_server_ip.py", line 188, in serve
loadPasswordFile()
File "/opt/cloud/bin/passwd_server_ip.py", line 67, in loadPasswordFile
with file(getPasswordFile()) as f:
NameError: name 'file' is not defined
```
* python3: fix "TypeError: write() argument must be str, not bytes" (two more files)
* Upgrade jaxb version
* python3: fix more "TypeError: a bytes-like object is required, not str"
* python3: fix "Failed to update password server"
Failed to update password server due to: POST data should be bytes, an iterable of bytes, or a file object. It cannot be of type str.
* python3: fix "bad duration value: ikelifetime=24.0h"
Jan 15 13:57:20 systemvm ipsec[3080]: # bad duration value: ikelifetime=24.0h
* python3: fix password server "invalid save_password token"
* test: incease retries in test_vpc_vpn.py
* python3: fix passwd_server_ip.py
see error below
```
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: ----------------------------------------
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: Exception occurred during processing of request from ('10.1.1.129', 32782)
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: Traceback (most recent call last):
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/socketserver.py", line 650, in process_request_thread
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self.finish_request(request, client_address)
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/socketserver.py", line 360, in finish_request
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self.RequestHandlerClass(request, client_address, self)
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/socketserver.py", line 720, in __init__
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self.handle()
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/http/server.py", line 427, in handle
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self.handle_one_request()
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/http/server.py", line 415, in handle_one_request
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: method()
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/opt/cloud/bin/passwd_server_ip.py", line 120, in do_GET
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self.wfile.write(password)
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: File "/usr/lib/python3.9/socketserver.py", line 799, in write
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: self._sock.sendall(b)
Jan 15 18:51:21 systemvm passwd_server_ip.py[1507]: TypeError: a bytes-like object is required, not 'str'
```
* python3: fix self.cl.get_router_password in Redundant VRs
```
File "/opt/cloud/bin/cs/CsDatabag.py", line 154, in get_router_password
md5.update(passwd)
TypeError: Unicode-objects must be encoded before hashing"]
```
* scripts: mark multipath scripts as executable
* systemvm template: remove hyperv packages and do not export
* VR: update default RAM size of System VMs/VRs to 512MiB
Before
```
mysql> select id,name,cpu,speed,ram_size,unique_name,system_use from service_offering where name like "System%";
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
| id | name | cpu | speed | ram_size | unique_name | system_use |
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
| 3 | System Offering For Software Router | 1 | 500 | 256 | Cloud.Com-SoftwareRouter | 1 |
| 4 | System Offering For Software Router - Local Storage | 1 | 500 | 256 | Cloud.Com-SoftwareRouter-Local | 1 |
| 5 | System Offering For Internal LB VM | 1 | 256 | 256 | Cloud.Com-InternalLBVm | 1 |
| 6 | System Offering For Internal LB VM - Local Storage | 1 | 256 | 256 | Cloud.Com-InternalLBVm-Local | 1 |
| 7 | System Offering For Console Proxy | 1 | 500 | 1024 | Cloud.com-ConsoleProxy | 1 |
| 8 | System Offering For Console Proxy - Local Storage | 1 | 500 | 1024 | Cloud.com-ConsoleProxy-Local | 1 |
| 9 | System Offering For Secondary Storage VM | 1 | 500 | 512 | Cloud.com-SecondaryStorage | 1 |
| 10 | System Offering For Secondary Storage VM - Local Storage | 1 | 500 | 512 | Cloud.com-SecondaryStorage-Local | 1 |
| 11 | System Offering For Elastic LB VM | 1 | 128 | 128 | Cloud.Com-ElasticLBVm | 1 |
| 12 | System Offering For Elastic LB VM - Local Storage | 1 | 128 | 128 | Cloud.Com-ElasticLBVm-Local | 1 |
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
10 rows in set (0.00 sec)
```
New value
```
mysql> select id,name,cpu,speed,ram_size,unique_name,system_use from service_offering where name like "System%";
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
| id | name | cpu | speed | ram_size | unique_name | system_use |
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
| 3 | System Offering For Software Router | 1 | 500 | 512 | Cloud.Com-SoftwareRouter | 1 |
| 4 | System Offering For Software Router - Local Storage | 1 | 500 | 512 | Cloud.Com-SoftwareRouter-Local | 1 |
| 5 | System Offering For Internal LB VM | 1 | 256 | 512 | Cloud.Com-InternalLBVm | 1 |
| 6 | System Offering For Internal LB VM - Local Storage | 1 | 256 | 512 | Cloud.Com-InternalLBVm-Local | 1 |
| 7 | System Offering For Console Proxy | 1 | 500 | 1024 | Cloud.com-ConsoleProxy | 1 |
| 8 | System Offering For Console Proxy - Local Storage | 1 | 500 | 1024 | Cloud.com-ConsoleProxy-Local | 1 |
| 9 | System Offering For Secondary Storage VM | 1 | 500 | 512 | Cloud.com-SecondaryStorage | 1 |
| 10 | System Offering For Secondary Storage VM - Local Storage | 1 | 500 | 512 | Cloud.com-SecondaryStorage-Local | 1 |
| 11 | System Offering For Elastic LB VM | 1 | 128 | 512 | Cloud.Com-ElasticLBVm | 1 |
| 12 | System Offering For Elastic LB VM - Local Storage | 1 | 128 | 512 | Cloud.Com-ElasticLBVm-Local | 1 |
+----+----------------------------------------------------------+------+-------+----------+----------------------------------+------------+
10 rows in set (0.01 sec)
```
* debian12: fix test_network_ipv6 and test_vpc_ipv6
* python3: remove duplicated imports
* debian12: failed to start Apache2 server (SSLCipherSuite @SECLEVEL=0)
error message
```
[Sat Jan 20 22:51:14.595143 2024] [ssl:emerg] [pid 10200:tid 140417063888768] AH02562: Failed to configure certificate cloudinternal.com:443:0 (with chain), check /etc/ssl/certs/cert_apache.crt
[Sat Jan 20 22:51:14.595234 2024] [ssl:emerg] [pid 10200:tid 140417063888768] SSL Library Error: error:0A00018E:SSL routines::ca md too weak
AH00016: Configuration Failed
```
openssl version
```
root@s-167-VM:~# openssl version -a
OpenSSL 3.0.11 19 Sep 2023 (Library: OpenSSL 3.0.11 19 Sep 2023)
built on: Mon Oct 23 17:52:22 2023 UTC
platform: debian-amd64
options: bn(64,64)
compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -fzero-call-used-regs=used-gpr -DOPENSSL_TLS_SECURITY_LEVEL=2 -Wa,--noexecstack -g -O2 -ffile-prefix-map=/build/reproducible-path/openssl-3.0.11=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_BUILDING_OPENSSL -DNDEBUG -Wdate-time -D_FORTIFY_SOURCE=2
OPENSSLDIR: "/usr/lib/ssl"
ENGINESDIR: "/usr/lib/x86_64-linux-gnu/engines-3"
MODULESDIR: "/usr/lib/x86_64-linux-gnu/ossl-modules"
Seeding source: os-specific
CPUINFO: OPENSSL_ia32cap=0x80202001478bfffd:0x0
```
certificate
```
root@s-167-VM:~# keytool -printcert -rfc -file /usr/local/cloud/systemvm/certs/realhostip.crt
-----BEGIN CERTIFICATE-----
MIIFZTCCBE2gAwIBAgIHKBCduBUoKDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm
aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5
IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky
ODcwHhcNMTIwMjAzMDMzMDQwWhcNMTcwMjA3MDUxMTIzWjBZMRkwFwYDVQQKDBAq
LnJlYWxob3N0aXAuY29tMSEwHwYDVQQLDBhEb21haW4gQ29udHJvbCBWYWxpZGF0
ZWQxGTAXBgNVBAMMECoucmVhbGhvc3RpcC5jb20wggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQCDT9AtEfs+s/I8QXp6rrCw0iNJ0+GgsybNHheU+JpL39LM
TZykCrZhZnyDvwdxCoOfE38Sa32baHKNds+y2SHnMNsOkw8OcNucHEBX1FIpOBGp
h9D6xC+umx9od6xMWETUv7j6h2u+WC3OhBM8fHCBqIiAol31/IkcqDxxsHlQ8S/o
CfTlXJUY6Yn628OA1XijKdRnadV0hZ829cv/PZKljjwQUTyrd0KHQeksBH+YAYSo
2JUl8ekNLsOi8/cPtfojnltzRI1GXi0ZONs8VnDzJ0a2gqZY+uxlz+CGbLnGnlN4
j9cBpE+MfUE+35Dq121sTpsSgF85Mz+pVhn2S633AgMBAAGjggG+MIIBujAPBgNV
HRMBAf8EBTADAQEAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAOBgNV
HQ8BAf8EBAMCBaAwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5
LmNvbS9nZHMxLTY0LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcBMDkwNwYI
KwYBBQUHAgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3Np
dG9yeS8wgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3Au
Z29kYWRkeS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdv
ZGFkZHkuY29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSME
GDAWgBT9rGEyk2xF1uLuhV+auud2mWjM5zArBgNVHREEJDAighAqLnJlYWxob3N0
aXAuY29tgg5yZWFsaG9zdGlwLmNvbTAdBgNVHQ4EFgQUZyJz9/QLy5TWIIscTXID
E8Xk47YwDQYJKoZIhvcNAQEFBQADggEBAKiUV3KK16mP0NpS92fmQkCLqm+qUWyN
BfBVgf9/M5pcT8EiTZlS5nAtzAE/eRpBeR3ubLlaAogj4rdH7YYVJcDDLLoB2qM3
qeCHu8LFoblkb93UuFDWqRaVPmMlJRnhsRkL1oa2gM2hwQTkBDkP7w5FG1BELCgl
gZI2ij2yxjge6pOEwSyZCzzbCcg9pN+dNrYyGEtB4k+BBnPA3N4r14CWbk+uxjrQ
6j2Ip+b7wOc5IuMEMl8xwTyjuX3lsLbAZyFI9RCyofwA9NqIZ1GeB6Zd196rubQp
93cmBqGGjZUs3wMrGlm7xdjlX6GQ9UvmvkMub9+lL99A5W50QgCmFeI=
-----END CERTIFICATE-----
Warning:
The certificate uses the SHA1withRSA signature algorithm which is considered a security risk. This algorithm will be disabled in a future update.
```
it comes from
```
$ openssl x509 -in ./systemvm/agent/certs/realhostip.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 11277268652730408 (0x28109db8152828)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", OU = http://certificates.godaddy.com/repository, CN = Go Daddy Secure Certification Authority, serialNumber = 07969287
Validity
Not Before: Feb 3 03:30:40 2012 GMT
Not After : Feb 7 05:11:23 2017 GMT
Subject: O = *.realhostip.com, OU = Domain Control Validated, CN = *.realhostip.com
```
* debian12: use ed25519 instead of rsa as ssh-rsa has been deprecated in OpenSSH
on xenserver
```
[root@pr8497-t8906-xenserver-71-xs2 ~]# ssh -i .ssh/id_rsa.cloud -p 3922 169.254.214.153
Warning: Permanently added '[169.254.214.153]:3922' (ECDSA) to the list of known hosts.
Permission denied (publickey).
```
in the CPVM
Jan 22 19:31:09 v-1-VM sshd[2869]: userauth_pubkey: signature algorithm ssh-rsa not in PubkeyAcceptedAlgorithms [preauth]
Jan 22 19:31:09 v-1-VM sshd[2869]: Connection closed by authenticating user root 169.254.0.1 port 54704 [preauth]
```
ssh-dss (DSA) is not supported either
* debian12: add PubkeyAcceptedAlgorithms=+ssh-rsa to sshd_config
* VR: install python3 packages in case of Debian 11
* pom.xml: exclude systemvm/agent/packages/* in license check
* systemvm: do not patch router/systemvm during startup
this will cause 4.19 SYSTEM template not work, but may be expected
- python3 VS python2 (default)
- openSSL 3.0.1 VS 1.1.1w
- openssh-server 9.1 VS 8.4
* VR: patch router/systemvm if template is debian11
This supports debian 11 template by
- revert change in systemvm/debian/etc/ssh/sshd_config
- patch VR/systemvms during startup
- install packages during patching system vm/routers
* python3 flake: fix E502 the backslash is redundant between brackets
```
../debian/root/health_checks/router_version_check.py:55:70: E502 the backslash is redundant between brackets
../debian/root/health_checks/router_version_check.py:58:61: E502 the backslash is redundant between brackets
../debian/root/health_checks/router_version_check.py:67:71: E502 the backslash is redundant between brackets
../debian/root/health_checks/router_version_check.py:70:60: E502 the backslash is redundant between brackets
../debian/root/health_checks/haproxy_check.py:47:71: E502 the backslash is redundant between brackets
../debian/root/health_checks/haproxy_check.py:48:64: E502 the backslash is redundant between brackets
../debian/root/health_checks/cpu_usage_check.py:43:54: E502 the backslash is redundant between brackets
../debian/root/health_checks/cpu_usage_check.py:46:58: E502 the backslash is redundant between brackets
../debian/root/health_checks/memory_usage_check.py:31:65: E502 the backslash is redundant between brackets
../debian/root/health_checks/memory_usage_check.py:42:57: E502 the backslash is redundant between brackets
../debian/root/health_checks/memory_usage_check.py:45:63: E502 the backslash is redundant between brackets
```
* python3 flake: fix E275 missing whitespace after keyword
```
../debian/opt/cloud/bin/cs_firewallrules.py:29:20: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_dhcp.py:27:16: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_dhcp.py:36:16: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_guestnetwork.py:33:20: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_guestnetwork.py:35:16: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_vpnusers.py:37:16: E275 missing whitespace after keyword
../debian/opt/cloud/bin/merge.py:230:11: E275 missing whitespace after keyword
../debian/opt/cloud/bin/merge.py:239:19: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_remoteaccessvpn.py:24:12: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs_site2sitevpn.py:24:12: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs/CsHelper.py:90:15: E275 missing whitespace after keyword
../debian/opt/cloud/bin/cs/CsAddress.py:367:15: E275 missing whitespace after keyword
```
* python3 flake: fix configure.py
```
../debian/opt/cloud/bin/configure.py:24:22: E401 multiple imports on one line
../debian/opt/cloud/bin/configure.py:43:180: E501 line too long (294 > 179 characters)
../debian/opt/cloud/bin/configure.py:46:1: E302 expected 2 blank lines, found 1
../debian/opt/cloud/bin/configure.py:63:1: E302 expected 2 blank lines, found 1
../debian/opt/cloud/bin/configure.py:65:12: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/configure.py:72:1: E302 expected 2 blank lines, found 1
../debian/opt/cloud/bin/configure.py:310:25: E711 comparison to None should be 'if cond is not None:'
../debian/opt/cloud/bin/configure.py:312:29: E711 comparison to None should be 'if cond is None:'
../debian/opt/cloud/bin/configure.py:378:25: E711 comparison to None should be 'if cond is not None:'
../debian/opt/cloud/bin/configure.py:380:29: E711 comparison to None should be 'if cond is None:'
../debian/opt/cloud/bin/configure.py:490:29: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
../debian/opt/cloud/bin/configure.py:642:16: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/configure.py:644:18: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/configure.py:1416:1: E305 expected 2 blank lines after class or function definition, found 1
```
* python3 flake: fix other python files
```
../debian/opt/cloud/bin/vmdata.py:97:12: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/vmdata.py:99:14: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/cs/CsRedundant.py:438:53: E203 whitespace before ':'
../debian/opt/cloud/bin/cs/CsRedundant.py:461:53: E203 whitespace before ':'
../debian/opt/cloud/bin/cs/CsRedundant.py:499:5: E303 too many blank lines (2)
../debian/opt/cloud/bin/cs/CsDatabag.py:189:1: E302 expected 2 blank lines, found 1
../debian/opt/cloud/bin/cs/CsDatabag.py:193:37: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
../debian/opt/cloud/bin/cs/CsHelper.py:118:30: E231 missing whitespace after ','
../debian/opt/cloud/bin/cs/CsHelper.py:119:15: E225 missing whitespace around operator
../debian/opt/cloud/bin/cs/CsHelper.py:127:19: E225 missing whitespace around operator
../debian/opt/cloud/bin/cs/CsAddress.py:324:43: E221 multiple spaces before operator
../debian/opt/cloud/bin/cs/CsVpcGuestNetwork.py:28:1: E302 expected 2 blank lines, found 1
```
* python3 flake: fix CsNetfilter.py
```
../debian/opt/cloud/bin/cs/CsNetfilter.py:226:13: E117 over-indented
../debian/opt/cloud/bin/cs/CsNetfilter.py:233:180: E501 line too long (197 > 179 characters)
../debian/opt/cloud/bin/cs/CsNetfilter.py:241:14: E201 whitespace after '{'
../debian/opt/cloud/bin/cs/CsNetfilter.py:242:14: E201 whitespace after '{'
../debian/opt/cloud/bin/cs/CsNetfilter.py:247:18: E201 whitespace after '{'
../debian/opt/cloud/bin/cs/CsNetfilter.py:247:74: E202 whitespace before '}'
../debian/opt/cloud/bin/cs/CsNetfilter.py:248:18: E201 whitespace after '{'
```
* systemvm/test: fix sys.path
```
$ bash runtests.sh
/usr/bin/python
Python 3.10.12
Running pycodestyle to check systemvm/python code for errors
Running pylint to check systemvm/python code for errors
Python 3.10.12
pylint 2.12.2
astroid 2.9.3
Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0]
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
Running systemvm/python unit tests
....Device "eth0" does not exist.
.....................
----------------------------------------------------------------------
Ran 25 tests in 0.008s
OK
```
* Revert "systemvm template: remove hyperv packages and do not export"
This reverts commit 4383d59d031bde6eae7ebba261ff641ca0a66cd5.
* debian12: move SQL change to schema-41900to42000.sql
* debian12: update systemvm template version to 4.20 in pom.xml
* pom.xml: fix NPE if templates do not exist on download.cloudstack.org
* debian12: increase default system offering for routers to 384MiB RAM
* CKS: fix addkubernetessupportedversion failed with JRE17
```
marvin.cloudstackException.CloudstackAPIException: Execute cmd: addkubernetessupportedversion failed, due to: errorCode: 530, errorText:Cannot invoke "org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine$State.toString()" because the return value of "com.cloud.api.query.vo.TemplateJoinVO.getState()" is null
```
* python3: revert changes by 2to3 with systemvm/debian/root/health_checks/*.py
* debian12: use ISO/packages on download.cloudstack.org
* VR: Update default ram size to 384
* debian12: fix router_version_check.py after VR live-patch and add health check in test_routers.py
* debian12: fix build error after log4j 2.x merge
* VR: Update default ram size to 512MB (again)
This reverts commit 578dd2b73f380e8231ae1eb59827230757cac5e8 and efafa8c4d63775653a2cd406fca10784fbcec3e3.
* systemvmtemplate: Upgrade to Debian 12.5.0
* systemvm template: increase swap to 512MB
* VR: fix health check error due to deprecated SafeConfigParser
warning below
```
root@r-20-VM:~# /opt/cloud/bin/getRouterMonitorResults.sh true
/root/monitorServices.py:59: DeprecationWarning: The SafeConfigParser class has been renamed to ConfigParser in Python 3.2. This alias will be removed in Python 3.12. Use ConfigParser directly instead.
parser = SafeConfigParser()
```
* test: fix wget does not work in macchinina vms on vmware80u1
fixes error below
```
{Cmd: wget -t 1 -T 1 www.google.com via Host: 10.0.55.186} {returns: ["wget: '/usr/lib/libpcre.so.1' is not an ELF file", "wget: can't load library 'libpcre.so.1'"]}
```
* packaging: add message for VR memory upgrade after packages installation
---------
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
Co-authored-by: Rohit Yadav <rohit.yadav@shapeblue.com>
Co-authored-by: Vishesh <vishesh92@gmail.com>
1029 lines
40 KiB
Python
1029 lines
40 KiB
Python
# Licensed to the Apache Software Foundation (ASF) under one
|
|
# or more contributor license agreements. See the NOTICE file
|
|
# distributed with this work for additional information
|
|
# regarding copyright ownership. The ASF licenses this file
|
|
# to you under the Apache License, Version 2.0 (the
|
|
# "License"); you may not use this file except in compliance
|
|
# with the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing,
|
|
# software distributed under the License is distributed on an
|
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
# KIND, either express or implied. See the License for the
|
|
# specific language governing permissions and limitations
|
|
# under the License.
|
|
|
|
# Import Local Modules
|
|
from marvin.codes import PASS, FAILED
|
|
from nose.plugins.attrib import attr
|
|
from marvin.cloudstackTestCase import cloudstackTestCase
|
|
from marvin.cloudstackAPI import (stopVirtualMachine,
|
|
stopRouter,
|
|
startRouter)
|
|
from marvin.lib.utils import (cleanup_resources,
|
|
get_process_status,
|
|
get_host_credentials)
|
|
from marvin.lib.base import (ServiceOffering,
|
|
VirtualMachine,
|
|
Account,
|
|
Template,
|
|
ServiceOffering,
|
|
NATRule,
|
|
NetworkACL,
|
|
FireWallRule,
|
|
PublicIPAddress,
|
|
NetworkOffering,
|
|
Network,
|
|
Router,
|
|
EgressFireWallRule)
|
|
from marvin.lib.common import (get_zone,
|
|
get_test_template,
|
|
get_domain,
|
|
list_virtual_machines,
|
|
list_networks,
|
|
list_configurations,
|
|
list_routers,
|
|
list_nat_rules,
|
|
list_publicIP,
|
|
list_firewall_rules,
|
|
list_hosts)
|
|
|
|
# Import System modules
|
|
import time
|
|
import logging
|
|
|
|
|
|
def check_router_command(virtual_machine, public_ip, ssh_command, check_string, test_case, retries=5):
|
|
result = 'failed'
|
|
try:
|
|
ssh = virtual_machine.get_ssh_client(ipaddress=public_ip, retries=retries)
|
|
result = str(ssh.execute(ssh_command))
|
|
except Exception as e:
|
|
test_case.fail("Failed to SSH into the Virtual Machine: %s" % e)
|
|
|
|
logging.debug("Result from SSH into the Virtual Machine: %s" % result)
|
|
return result.count(check_string)
|
|
|
|
|
|
class TestRedundantIsolateNetworks(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
|
|
cls.logger = logging.getLogger('TestRedundantIsolateNetworks')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
cls.testClient = super(TestRedundantIsolateNetworks, cls).getClsTestClient()
|
|
cls.api_client = cls.testClient.getApiClient()
|
|
|
|
cls.services = cls.testClient.getParsedTestDataConfig()
|
|
# Get Zone, Domain and templates
|
|
cls.domain = get_domain(cls.api_client)
|
|
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
|
|
cls.services['mode'] = cls.zone.networktype
|
|
|
|
cls.hypervisor = cls.testClient.getHypervisorInfo()
|
|
|
|
cls.template = get_test_template(cls.api_client, cls.zone.id, cls.hypervisor)
|
|
if cls.template == FAILED:
|
|
assert False, "get_test_template() failed to return template"
|
|
|
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
|
cls.services["virtual_machine"]["template"] = cls.template.id
|
|
|
|
# Create an account, network, VM and IP addresses
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
admin=True,
|
|
domainid=cls.domain.id
|
|
)
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
|
|
cls.services["nw_off_persistent_RVR_egress_true"] = cls.services["nw_off_persistent_RVR"].copy()
|
|
cls.services["nw_off_persistent_RVR_egress_true"]["egress_policy"] = "true"
|
|
|
|
cls.services["nw_off_persistent_RVR_egress_false"] = cls.services["nw_off_persistent_RVR"].copy()
|
|
cls.services["nw_off_persistent_RVR_egress_false"]["egress_policy"] = "false"
|
|
|
|
cls.services["egress_80"] = {
|
|
"startport": 80,
|
|
"endport": 80,
|
|
"protocol": "TCP",
|
|
"cidrlist": ["0.0.0.0/0"]
|
|
}
|
|
|
|
cls.services["egress_53"] = {
|
|
"startport": 53,
|
|
"endport": 53,
|
|
"protocol": "UDP",
|
|
"cidrlist": ["0.0.0.0/0"]
|
|
}
|
|
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account
|
|
]
|
|
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
cleanup_resources(self.api_client, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
|
|
def test_01_RVR_Network_FW_PF_SSH_default_routes_egress_true(self):
|
|
""" Test redundant router internals """
|
|
self.logger.debug("Starting test_01_RVR_Network_FW_PF_SSH_default_routes_egress_true...")
|
|
|
|
self.logger.debug("Creating Network Offering with default egress TRUE")
|
|
network_offering_egress_true = NetworkOffering.create(
|
|
self.apiclient,
|
|
self.services["nw_off_persistent_RVR_egress_true"],
|
|
conservemode=True
|
|
)
|
|
network_offering_egress_true.update(self.api_client, state='Enabled')
|
|
|
|
self.logger.debug("Creating network with network offering: %s" % network_offering_egress_true.id)
|
|
network = Network.create(
|
|
self.apiclient,
|
|
self.services["network"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=network_offering_egress_true.id,
|
|
zoneid=self.zone.id
|
|
)
|
|
self.logger.debug("Created network with ID: %s" % network.id)
|
|
|
|
networks = Network.list(
|
|
self.apiclient,
|
|
id=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(networks, list),
|
|
True,
|
|
"List networks should return a valid response for created network"
|
|
)
|
|
nw_response = networks[0]
|
|
|
|
self.logger.debug("Deploying VM in account: %s" % self.account.name)
|
|
virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[str(network.id)]
|
|
)
|
|
|
|
self.logger.debug("Deployed VM in network: %s" % network.id)
|
|
|
|
self.cleanup.insert(0, network_offering_egress_true)
|
|
self.cleanup.insert(0, network)
|
|
self.cleanup.insert(0, virtual_machine)
|
|
|
|
vms = VirtualMachine.list(
|
|
self.apiclient,
|
|
id=virtual_machine.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(vms, list),
|
|
True,
|
|
"List Vms should return a valid list"
|
|
)
|
|
vm = vms[0]
|
|
self.assertEqual(
|
|
vm.state,
|
|
"Running",
|
|
"VM should be in running state after deployment"
|
|
)
|
|
|
|
self.logger.debug("Listing routers for network: %s" % network.name)
|
|
routers = Router.list(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(routers, list),
|
|
True,
|
|
"list router should return Primary and backup routers"
|
|
)
|
|
self.assertEqual(
|
|
len(routers),
|
|
2,
|
|
"Length of the list router should be 2 (Backup & Primary)"
|
|
)
|
|
|
|
public_ips = list_publicIP(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
zoneid=self.zone.id
|
|
)
|
|
|
|
public_ip = public_ips[0]
|
|
|
|
self.assertEqual(
|
|
isinstance(public_ips, list),
|
|
True,
|
|
"Check for list public IPs response return valid data"
|
|
)
|
|
|
|
self.logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
|
|
FireWallRule.create(
|
|
self.apiclient,
|
|
ipaddressid=public_ip.id,
|
|
protocol=self.services["natrule"]["protocol"],
|
|
cidrlist=['0.0.0.0/0'],
|
|
startport=self.services["natrule"]["publicport"],
|
|
endport=self.services["natrule"]["publicport"]
|
|
)
|
|
|
|
self.logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
|
|
nat_rule = NATRule.create(
|
|
self.apiclient,
|
|
virtual_machine,
|
|
self.services["natrule"],
|
|
public_ip.id
|
|
)
|
|
|
|
# Test SSH after closing port 22
|
|
expected = 1
|
|
ssh_command = "ping -c 3 8.8.8.8"
|
|
check_string = " 0% packet loss"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Ping to outside world from VM should be successful!"
|
|
)
|
|
|
|
expected = 1
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should be successful!"
|
|
)
|
|
|
|
EgressFireWallRule.create(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
protocol=self.services["egress_80"]["protocol"],
|
|
startport=self.services["egress_80"]["startport"],
|
|
endport=self.services["egress_80"]["endport"],
|
|
cidrlist=self.services["egress_80"]["cidrlist"]
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should NOT be successful once rule is added!"
|
|
)
|
|
|
|
return
|
|
|
|
@attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
|
|
def test_02_RVR_Network_FW_PF_SSH_default_routes_egress_false(self):
|
|
""" Test redundant router internals """
|
|
self.logger.debug("Starting test_02_RVR_Network_FW_PF_SSH_default_routes_egress_false...")
|
|
|
|
self.logger.debug("Creating Network Offering with default egress FALSE")
|
|
network_offering_egress_false = NetworkOffering.create(
|
|
self.apiclient,
|
|
self.services["nw_off_persistent_RVR_egress_false"],
|
|
conservemode=True
|
|
)
|
|
network_offering_egress_false.update(self.api_client, state='Enabled')
|
|
|
|
self.logger.debug("Creating network with network offering: %s" % network_offering_egress_false.id)
|
|
network = Network.create(
|
|
self.apiclient,
|
|
self.services["network"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=network_offering_egress_false.id,
|
|
zoneid=self.zone.id
|
|
)
|
|
self.logger.debug("Created network with ID: %s" % network.id)
|
|
|
|
networks = Network.list(
|
|
self.apiclient,
|
|
id=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(networks, list),
|
|
True,
|
|
"List networks should return a valid response for created network"
|
|
)
|
|
nw_response = networks[0]
|
|
|
|
self.logger.debug("Deploying VM in account: %s" % self.account.name)
|
|
virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[str(network.id)]
|
|
)
|
|
|
|
self.logger.debug("Deployed VM in network: %s" % network.id)
|
|
|
|
self.cleanup.insert(0, network_offering_egress_false)
|
|
self.cleanup.insert(0, network)
|
|
self.cleanup.insert(0, virtual_machine)
|
|
|
|
vms = VirtualMachine.list(
|
|
self.apiclient,
|
|
id=virtual_machine.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(vms, list),
|
|
True,
|
|
"List Vms should return a valid list"
|
|
)
|
|
vm = vms[0]
|
|
self.assertEqual(
|
|
vm.state,
|
|
"Running",
|
|
"VM should be in running state after deployment"
|
|
)
|
|
|
|
self.logger.debug("Listing routers for network: %s" % network.name)
|
|
routers = Router.list(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(routers, list),
|
|
True,
|
|
"list router should return Primary and backup routers"
|
|
)
|
|
self.assertEqual(
|
|
len(routers),
|
|
2,
|
|
"Length of the list router should be 2 (Backup & Primary)"
|
|
)
|
|
|
|
public_ips = list_publicIP(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
zoneid=self.zone.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(public_ips, list),
|
|
True,
|
|
"Check for list public IPs response return valid data"
|
|
)
|
|
|
|
public_ip = public_ips[0]
|
|
|
|
self.logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
|
|
FireWallRule.create(
|
|
self.apiclient,
|
|
ipaddressid=public_ip.id,
|
|
protocol=self.services["natrule"]["protocol"],
|
|
cidrlist=['0.0.0.0/0'],
|
|
startport=self.services["natrule"]["publicport"],
|
|
endport=self.services["natrule"]["publicport"]
|
|
)
|
|
|
|
self.logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
|
|
nat_rule = NATRule.create(
|
|
self.apiclient,
|
|
virtual_machine,
|
|
self.services["natrule"],
|
|
public_ip.id
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "ping -c 3 8.8.8.8"
|
|
check_string = " 0% packet loss"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Ping to outside world from VM should NOT be successful"
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should NOT be successful"
|
|
)
|
|
|
|
EgressFireWallRule.create(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
protocol=self.services["egress_80"]["protocol"],
|
|
startport=self.services["egress_80"]["startport"],
|
|
endport=self.services["egress_80"]["endport"],
|
|
cidrlist=self.services["egress_80"]["cidrlist"]
|
|
)
|
|
|
|
EgressFireWallRule.create(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
protocol=self.services["egress_53"]["protocol"],
|
|
startport=self.services["egress_53"]["startport"],
|
|
endport=self.services["egress_53"]["endport"],
|
|
cidrlist=self.services["egress_53"]["cidrlist"]
|
|
)
|
|
|
|
expected = 1
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should be successful once rule is added!"
|
|
)
|
|
|
|
return
|
|
|
|
@attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
|
|
def test_03_RVR_Network_check_router_state(self):
|
|
""" Test redundant router internals """
|
|
self.logger.debug("Starting test_03_RVR_Network_check_router_state...")
|
|
|
|
hypervisor = self.testClient.getHypervisorInfo()
|
|
|
|
self.logger.debug("Creating Network Offering with default egress FALSE")
|
|
network_offering_egress_false = NetworkOffering.create(
|
|
self.apiclient,
|
|
self.services["nw_off_persistent_RVR_egress_false"],
|
|
conservemode=True
|
|
)
|
|
network_offering_egress_false.update(self.apiclient, state='Enabled')
|
|
|
|
self.logger.debug("Creating network with network offering: %s" % network_offering_egress_false.id)
|
|
network = Network.create(
|
|
self.apiclient,
|
|
self.services["network"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=network_offering_egress_false.id,
|
|
zoneid=self.zone.id
|
|
)
|
|
self.logger.debug("Created network with ID: %s" % network.id)
|
|
|
|
networks = Network.list(
|
|
self.apiclient,
|
|
id=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(networks, list),
|
|
True,
|
|
"List networks should return a valid response for created network"
|
|
)
|
|
nw_response = networks[0]
|
|
|
|
self.logger.debug("Deploying VM in account: %s" % self.account.name)
|
|
virtual_machine = VirtualMachine.create(
|
|
self.apiclient,
|
|
self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[str(network.id)]
|
|
)
|
|
|
|
self.logger.debug("Deployed VM in network: %s" % network.id)
|
|
|
|
self.cleanup.insert(0, network_offering_egress_false)
|
|
self.cleanup.insert(0, network)
|
|
self.cleanup.insert(0, virtual_machine)
|
|
|
|
vms = VirtualMachine.list(
|
|
self.apiclient,
|
|
id=virtual_machine.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(vms, list),
|
|
True,
|
|
"List Vms should return a valid list"
|
|
)
|
|
vm = vms[0]
|
|
self.assertEqual(
|
|
vm.state,
|
|
"Running",
|
|
"VM should be in running state after deployment"
|
|
)
|
|
|
|
self.logger.debug("Listing routers for network: %s" % network.name)
|
|
routers = Router.list(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
listall=True
|
|
)
|
|
self.assertEqual(
|
|
isinstance(routers, list),
|
|
True,
|
|
"list router should return Primary and backup routers"
|
|
)
|
|
self.assertEqual(
|
|
len(routers),
|
|
2,
|
|
"Length of the list router should be 2 (Backup & Primary)"
|
|
)
|
|
|
|
vals = ["PRIMARY", "BACKUP", "UNKNOWN"]
|
|
cnts = [0, 0, 0]
|
|
|
|
result = "UNKNOWN"
|
|
for router in routers:
|
|
if router.state == "Running":
|
|
hosts = list_hosts(
|
|
self.apiclient,
|
|
zoneid=router.zoneid,
|
|
type='Routing',
|
|
state='Up',
|
|
id=router.hostid
|
|
)
|
|
self.assertEqual(
|
|
isinstance(hosts, list),
|
|
True,
|
|
"Check list host returns a valid list"
|
|
)
|
|
host = hosts[0]
|
|
|
|
if hypervisor.lower() in ('vmware', 'hyperv'):
|
|
result = str(get_process_status(
|
|
self.apiclient.connection.mgtSvr,
|
|
22,
|
|
self.apiclient.connection.user,
|
|
self.apiclient.connection.passwd,
|
|
router.linklocalip,
|
|
"sh /opt/cloud/bin/checkrouter.sh ",
|
|
hypervisor=hypervisor
|
|
))
|
|
else:
|
|
try:
|
|
host.user, host.passwd = get_host_credentials(
|
|
self.config, host.ipaddress)
|
|
result = str(get_process_status(
|
|
host.ipaddress,
|
|
22,
|
|
host.user,
|
|
host.passwd,
|
|
router.linklocalip,
|
|
"sh /opt/cloud/bin/checkrouter.sh "
|
|
))
|
|
|
|
except KeyError:
|
|
self.skipTest(
|
|
"Marvin configuration has no host credentials to\
|
|
check router services")
|
|
|
|
if result.count(vals[0]) == 1:
|
|
cnts[vals.index(vals[0])] += 1
|
|
|
|
if cnts[vals.index('PRIMARY')] != 1:
|
|
self.fail("No Primary or too many primary routers found %s" % cnts[vals.index('PRIMARY')])
|
|
|
|
return
|
|
|
|
|
|
class TestIsolatedNetworks(cloudstackTestCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
|
|
cls.logger = logging.getLogger('TestIsolatedNetworks')
|
|
cls.stream_handler = logging.StreamHandler()
|
|
cls.logger.setLevel(logging.DEBUG)
|
|
cls.logger.addHandler(cls.stream_handler)
|
|
|
|
cls.testClient = super(TestIsolatedNetworks, cls).getClsTestClient()
|
|
cls.api_client = cls.testClient.getApiClient()
|
|
|
|
cls.services = cls.testClient.getParsedTestDataConfig()
|
|
# Get Zone, Domain and templates
|
|
cls.domain = get_domain(cls.api_client)
|
|
cls.zone = get_zone(cls.api_client, cls.testClient.getZoneForTests())
|
|
cls.hypervisor = cls.testClient.getHypervisorInfo()
|
|
cls.services['mode'] = cls.zone.networktype
|
|
cls.template = get_test_template(
|
|
cls.api_client,
|
|
cls.zone.id,
|
|
cls.hypervisor
|
|
)
|
|
cls.services["virtual_machine"]["zoneid"] = cls.zone.id
|
|
|
|
# Create an account, network, VM and IP addresses
|
|
cls.account = Account.create(
|
|
cls.api_client,
|
|
cls.services["account"],
|
|
admin=True,
|
|
domainid=cls.domain.id
|
|
)
|
|
cls.service_offering = ServiceOffering.create(
|
|
cls.api_client,
|
|
cls.services["service_offering"]
|
|
)
|
|
|
|
cls.services["network_offering_egress_true"] = cls.services["network_offering"].copy()
|
|
cls.services["network_offering_egress_true"]["egress_policy"] = "true"
|
|
|
|
cls.services["network_offering_egress_false"] = cls.services["network_offering"].copy()
|
|
cls.services["network_offering_egress_false"]["egress_policy"] = "false"
|
|
|
|
cls.services["egress_80"] = {
|
|
"startport": 80,
|
|
"endport": 80,
|
|
"protocol": "TCP",
|
|
"cidrlist": ["0.0.0.0/0"]
|
|
}
|
|
|
|
cls._cleanup = [
|
|
cls.service_offering,
|
|
cls.account
|
|
]
|
|
|
|
return
|
|
|
|
@classmethod
|
|
def tearDownClass(cls):
|
|
try:
|
|
cleanup_resources(cls.api_client, cls._cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
def setUp(self):
|
|
self.apiclient = self.testClient.getApiClient()
|
|
self.cleanup = []
|
|
return
|
|
|
|
def tearDown(self):
|
|
try:
|
|
cleanup_resources(self.apiclient, self.cleanup)
|
|
except Exception as e:
|
|
raise Exception("Warning: Exception during cleanup : %s" % e)
|
|
return
|
|
|
|
@attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
|
|
def test_01_isolate_network_FW_PF_default_routes_egress_true(self):
|
|
""" Test redundant router internals """
|
|
self.logger.debug("Starting test_01_isolate_network_FW_PF_default_routes_egress_true...")
|
|
|
|
self.logger.debug("Creating Network Offering with default egress TRUE")
|
|
network_offering_egress_true = NetworkOffering.create(self.apiclient,
|
|
self.services["network_offering_egress_true"],
|
|
conservemode=True)
|
|
|
|
network_offering_egress_true.update(self.apiclient, state='Enabled')
|
|
|
|
self.logger.debug("Creating Network with Network Offering ID %s" % network_offering_egress_true.id)
|
|
network = Network.create(self.apiclient,
|
|
self.services["network"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=network_offering_egress_true.id,
|
|
zoneid=self.zone.id)
|
|
|
|
self.logger.debug("Deploying Virtual Machine on Network %s" % network.id)
|
|
virtual_machine = VirtualMachine.create(self.apiclient,
|
|
self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.name,
|
|
domainid=self.domain.id,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[str(network.id)])
|
|
|
|
self.logger.debug("Deployed VM in network: %s" % network.id)
|
|
|
|
self.cleanup.insert(0, network_offering_egress_true)
|
|
self.cleanup.insert(0, network)
|
|
self.cleanup.insert(0, virtual_machine)
|
|
|
|
self.logger.debug("Starting test_isolate_network_FW_PF_default_routes...")
|
|
routers = list_routers(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(routers, list),
|
|
True,
|
|
"Check for list routers response return valid data"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
len(routers),
|
|
0,
|
|
"Check list router response"
|
|
)
|
|
|
|
router = routers[0]
|
|
|
|
self.assertEqual(
|
|
router.state,
|
|
'Running',
|
|
"Check list router response for router state"
|
|
)
|
|
|
|
public_ips = list_publicIP(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
zoneid=self.zone.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(public_ips, list),
|
|
True,
|
|
"Check for list public IPs response return valid data"
|
|
)
|
|
|
|
public_ip = public_ips[0]
|
|
|
|
self.logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
|
|
FireWallRule.create(
|
|
self.apiclient,
|
|
ipaddressid=public_ip.id,
|
|
protocol=self.services["natrule"]["protocol"],
|
|
cidrlist=['0.0.0.0/0'],
|
|
startport=self.services["natrule"]["publicport"],
|
|
endport=self.services["natrule"]["publicport"]
|
|
)
|
|
|
|
self.logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
|
|
# Create NAT rule
|
|
nat_rule = NATRule.create(
|
|
self.apiclient,
|
|
virtual_machine,
|
|
self.services["natrule"],
|
|
public_ip.id
|
|
)
|
|
|
|
nat_rules = list_nat_rules(
|
|
self.apiclient,
|
|
id=nat_rule.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(nat_rules, list),
|
|
True,
|
|
"Check for list NAT rules response return valid data"
|
|
)
|
|
self.assertEqual(
|
|
nat_rules[0].state,
|
|
'Active',
|
|
"Check list port forwarding rules"
|
|
)
|
|
|
|
# Test SSH after closing port 22
|
|
expected = 1
|
|
ssh_command = "ping -c 3 8.8.8.8"
|
|
check_string = " 0% packet loss"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Ping to outside world from VM should be successful!"
|
|
)
|
|
|
|
expected = 1
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should be successful!"
|
|
)
|
|
|
|
EgressFireWallRule.create(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
protocol=self.services["egress_80"]["protocol"],
|
|
startport=self.services["egress_80"]["startport"],
|
|
endport=self.services["egress_80"]["endport"],
|
|
cidrlist=self.services["egress_80"]["cidrlist"]
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should NOT be successful once rule is added!"
|
|
)
|
|
|
|
return
|
|
|
|
@attr(tags=["advanced", "advancedns", "ssh"], required_hardware="true")
|
|
def test_02_isolate_network_FW_PF_default_routes_egress_false(self):
|
|
""" Test redundant router internals """
|
|
self.logger.debug("Starting test_02_isolate_network_FW_PF_default_routes_egress_false...")
|
|
|
|
self.logger.debug("Creating Network Offering with default egress FALSE")
|
|
network_offering_egress_false = NetworkOffering.create(self.apiclient,
|
|
self.services["network_offering_egress_false"],
|
|
conservemode=True)
|
|
|
|
network_offering_egress_false.update(self.apiclient, state='Enabled')
|
|
|
|
self.logger.debug("Creating Network with Network Offering ID %s" % network_offering_egress_false.id)
|
|
network = Network.create(self.apiclient,
|
|
self.services["network"],
|
|
accountid=self.account.name,
|
|
domainid=self.account.domainid,
|
|
networkofferingid=network_offering_egress_false.id,
|
|
zoneid=self.zone.id)
|
|
|
|
self.logger.debug("Deploying Virtual Machine on Network %s" % network.id)
|
|
virtual_machine = VirtualMachine.create(self.apiclient,
|
|
self.services["virtual_machine"],
|
|
templateid=self.template.id,
|
|
accountid=self.account.name,
|
|
domainid=self.domain.id,
|
|
serviceofferingid=self.service_offering.id,
|
|
networkids=[str(network.id)])
|
|
|
|
self.logger.debug("Deployed VM in network: %s" % network.id)
|
|
|
|
self.cleanup.insert(0, network_offering_egress_false)
|
|
self.cleanup.insert(0, network)
|
|
self.cleanup.insert(0, virtual_machine)
|
|
|
|
self.logger.debug("Starting test_isolate_network_FW_PF_default_routes...")
|
|
routers = list_routers(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(routers, list),
|
|
True,
|
|
"Check for list routers response return valid data"
|
|
)
|
|
|
|
self.assertNotEqual(
|
|
len(routers),
|
|
0,
|
|
"Check list router response"
|
|
)
|
|
|
|
router = routers[0]
|
|
|
|
self.assertEqual(
|
|
router.state,
|
|
'Running',
|
|
"Check list router response for router state"
|
|
)
|
|
|
|
public_ips = list_publicIP(
|
|
self.apiclient,
|
|
account=self.account.name,
|
|
domainid=self.account.domainid,
|
|
zoneid=self.zone.id
|
|
)
|
|
|
|
self.assertEqual(
|
|
isinstance(public_ips, list),
|
|
True,
|
|
"Check for list public IPs response return valid data"
|
|
)
|
|
|
|
public_ip = public_ips[0]
|
|
|
|
self.logger.debug("Creating Firewall rule for VM ID: %s" % virtual_machine.id)
|
|
FireWallRule.create(
|
|
self.apiclient,
|
|
ipaddressid=public_ip.id,
|
|
protocol=self.services["natrule"]["protocol"],
|
|
cidrlist=['0.0.0.0/0'],
|
|
startport=self.services["natrule"]["publicport"],
|
|
endport=self.services["natrule"]["publicport"]
|
|
)
|
|
|
|
self.logger.debug("Creating NAT rule for VM ID: %s" % virtual_machine.id)
|
|
# Create NAT rule
|
|
nat_rule = NATRule.create(
|
|
self.apiclient,
|
|
virtual_machine,
|
|
self.services["natrule"],
|
|
public_ip.id
|
|
)
|
|
|
|
nat_rules = list_nat_rules(
|
|
self.apiclient,
|
|
id=nat_rule.id
|
|
)
|
|
self.assertEqual(
|
|
isinstance(nat_rules, list),
|
|
True,
|
|
"Check for list NAT rules response return valid data"
|
|
)
|
|
self.assertEqual(
|
|
nat_rules[0].state,
|
|
'Active',
|
|
"Check list port forwarding rules"
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "ping -c 3 8.8.8.8"
|
|
check_string = " 0% packet loss"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Ping to outside world from VM should NOT be successful"
|
|
)
|
|
|
|
expected = 0
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should NOT be successful"
|
|
)
|
|
|
|
EgressFireWallRule.create(
|
|
self.apiclient,
|
|
networkid=network.id,
|
|
protocol=self.services["egress_80"]["protocol"],
|
|
startport=self.services["egress_80"]["startport"],
|
|
endport=self.services["egress_80"]["endport"],
|
|
cidrlist=self.services["egress_80"]["cidrlist"]
|
|
)
|
|
|
|
expected = 1
|
|
ssh_command = "curl -v -m 1 -o index.html -sL www.google.com"
|
|
check_string = "200 OK"
|
|
result = check_router_command(virtual_machine, nat_rule.ipaddress, ssh_command, check_string, self)
|
|
|
|
self.assertEqual(
|
|
result,
|
|
expected,
|
|
"Attempt to retrieve google.com index page should be successful once rule is added!"
|
|
)
|
|
|
|
return
|