sap-linuxlab / community.sap_install Goto Github PK
View Code? Open in Web Editor NEWAutomation for SAP - Collection of Ansible Roles for various SAP software installation
License: Apache License 2.0
Automation for SAP - Collection of Ansible Roles for various SAP software installation
License: Apache License 2.0
See https://docs.ansible.com/ansible/2.9/modules/find_module.html and https://docs.ansible.com/ansible/latest/collections/ansible/builtin/find_module.html .
And it only applies to file_type "file" as mentioned in the latter.
So in tasks/pre_install.yml and tasks/pre_install/hdblcm_prepare.yml, we would have to modify the tasks which call Ansible module "find" to search for a directory named "SAP_HANA_DATABASE".
However, in case a SAP HANA Platform Edition ZIP file had been downloaded, the hdblcm file would be in a directory named DATA_UNITS/HDB_SERVER_LINUX_XXX (with XXX denoting the hardware architecture converted to uppercase).
So in tasks/pre_install.yml, we may just search for a file named hdblcm and use the directory part of its absolute path name, for variable "sap_hana_hdblcm_path".
So when accidentally calling the new role with variables from the predecessor role sap-preconfigure, the new role would not perform any unintentional changes to managed nodes. Maybe we can also print a warning message if old parameters have been found.
This is a copy of linux-system-roles/sap-preconfigure#98, reported by alexxa:
This is a ToDo note to check on workaround for the issue when the roles fails if DNS domain is not set on the managed node, and a user needs to specify it and rerun the play.
Intentionally, Ansible doesn't allow to prompt users on tasks level, but it seems it's possible to do in a pre-task using pause + prompt + set_facts + when (dns is missing). Another solution may be an action plugin to ask the user to input a variable (or interrupt the play).
Copy of linux-system-roles/sap-hana-preconfigure#216 (comment), reported by berndfinger, initially reported as linux-system-roles/sap-hana-preconfigure#214 by bufanda:
When the HANA archives are presented from read-only directory, and the follwoing variables are set:
sap_hana_install_sarfiles_list:
- "SAPHOSTAGENT51_51-20009394.SAR "
- "IMDB_SERVER20_060_0-80002031.SAR"
sap_hana_install_software_directory: /path_to_readonly-NFS-mount
sap_hana_install_software_extract_directory: /tmp/sap-hana
The role runs into the following error:
TASK [community.sap_install.sap_hana_install : SAP HANA Pre Install - Change ownership of software directory '/rh-ava-packages/sap'] ***
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: OSError: [Errno 30] Read-only file system: b'/rh-ava-packages/sap/IMDB_CLIENT20_011_14-80002082.SAR'
There is no need to change ownership on readonly dir ....
Copy of linux-system-roles/sap-preconfigure#162 (comment), reported by https://github.com/rey217pr:
Add a way to skip group installation if sap_preconfigure_packagegroups "no" or empty.
The @server group adds additional packages that are not needed most times.
Even with @minimal-environment there are packages that are not needed for SAP.
tag_
in the tag namesap_hana_install_preinstall
is just a few more than for sap_hana_install_create_configfile
, so we do not need the latter.Copy of linux-system-roles/sap-preconfigure#168 (comment), reported by https://github.com/berndfinger:
This setting is recommend in SAP notes 2772999 v.17 and 2777782 v.23 but according to bug https://bugzilla.redhat.com/show_bug.cgi?id=1744214, the default for kernel.pid_max in RHEL 8.2 and later is 4194304.
(no comment was provided in linux-system-roles/sap-base-settings#3)
Copy of linux-system-roles/sap-hana-preconfigure#190 (comment), reported by berndfinger:
Grubby is the recommended way in RHEL 8 to modify kernel command line entries. By using grubby, we can avoid any issues related to boot entries no using variable kernelopts but using static entries instead.
Note: On platform s390x, we have to run the additional command zipl after running grubby.
See also https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/configuring-kernel-command-line-parameters_managing-monitoring-and-updating-the-kernel#setting-kernel-command-line-parameters_configuring-kernel-command-line-parameters .
See also linux-system-roles/sap-preconfigure#146 .
We can get the output of hdblcm --dump_configfile_template=... and convert the configfile template into a Jinja2 template so that we get a customized Jinja2 template for each HANA version. This addresses the fact that different HANA versions have a different set of parameters.
So we can run the role with tag sap_hana_install_tag_preinstall or sap_hana_install_tag_create_configfile, then check and if necessary modify the role variables according to the requirements of hdblcm, and finally run the HANA installation with a configfile created from the Jinja2 template.
Checksums can be retrieved from the SAP download page and stored in the second field of variables sap_hana_install_sapcar_file and sap_hana_install_sarfiles, e.g.:
# File name and checksum of SAPCAR EXE file:
sap_hana_install_sapcar_file:
- { name: 'SAPCAR_XXXX-XXXXXXXX.EXE', checksum: 'XXX' }
sap_hana_install_sarfiles:
- { name: 'IMDB_SERVERXXXXX_X-XXXXXXXX.SAR', checksum: 'XXX' }
- { name: 'SAPHOSTAGENTXXXXX-XXXXXXXX.SAR', checksum: 'XXX' }
Then the role can compare this checksum with the result of the sha256sum command run for the SAPCAR EXE file and each SAR file to be extracted by the role. We could store the result of the sha256sum command in a file named FILE.SAR.sha256sum. If this file does not exist, the role could created one.
Copy of linux-system-roles/sap-preconfigure#146 (comment), reported by https://github.com/berndfinger:
Grubby is the recommended way in RHEL 8 to modify kernel command line entries. By using grubby, we can avoid any issues related to boot entries no using variable kernelopts but using static entries instead.
Note: On platform s390x, we have to run the additional command zipl after running grubby.
See also https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_monitoring_and_updating_the_kernel/configuring-kernel-command-line-parameters_managing-monitoring-and-updating-the-kernel#setting-kernel-command-line-parameters_configuring-kernel-command-line-parameters .
File prepare_sapcar.yml should fail if no SAPCAR EXE file for the hardware architecture of the managed node was found in the software directory.
Also if the SAPCAR EXE file specified in role variable sap_hana_install_sapcar_filename
does not exist in the software directory, we should fail the role before calling the copy module, to get a nice failing message.
the default image in GCP has not installed the package NetworkManager-config-server.
This adds a NetworkManager configuration file to make it behave more like the old "network" service. In particular, it stops NetworkManager from automatically running DHCP on unconfigured ethernet devices, and allows connections with static IP addresses to be brought up even on ethernet devices with no carrier. This package is intended to be installed by default for server
deployments.
Hence the role installs it automatically, with the consequence that dhcp is no longer started on the network interfaces in GCP after reboot and the machine is disconnected from the network.
One easy option is to print a warning if that happens, the other option is to "define" the existing network config if it is unconfigured
The role is setting certain passwords in task SAP HANA Pre Install - Set password facts when using master password
if variable sap_hana_install_use_master_password
is set to y
. This leads to some warning messages for certain HANA releases indicating that if a master password is set, no other passwords should be set. Also password variables are set to an empty string in defaults/main.yml
.
I am proposing to not set any passwords at all in defaults/main.yml. In all files where a password variable is used, which are:
tasks/post_install/log_mode.yml
tasks/post_install/license.yml
tasks/post_install/hdbuserstore.yml
tasks/hana_addhosts.yml
templates/sap-nw-input.j2
sap_hana_install_master_password
if a password variable (e.g. sap_hana_install_db_system_password
) is not defined.The role currently does not detect the current SELinux status, so if the static configuration matches the desired configuration and the current status is different, it will not set the reboot requirement flag.
Copy of linux-system-roles/sap-hana-preconfigure#125 (comment), reported by alexxa:
Ansible has a built-in module service_facts
which returns service state information fact data for various service management utilities. It can be used instead of command: bash -lc "systemctl status <service>"
+ debug
modules.
Also, that bash command returns non zero code, which results in error print in red even if the ignore_errors
flag is used. It may disturb a user unnecessarily. service_facts
will print it in green.
Compare two outputs:
Before this PR:
TASK [Stop and disable service firewalld] ********************************************************************************
changed: [localhost]
TASK [Get status of firewalld] *******************************************************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["bash", "-lc", "systemctl status firewalld"], "delta": "0:00:00.016379", "end": "2020-10-14 15:52:59.913780", "msg": "non-zero return code", "rc": 3, "start": "2020-10-14 15:52:59.897401", "stderr": "", "stderr_lines": [], "stdout": "● firewalld.service - firewalld - dynamic firewall daemon\n Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)\n Active: inactive (dead)\n Docs: man:firewalld(1)\n\nOct 14 13:23:20 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...\nOct 14 13:23:21 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.\nOct 14 13:53:42 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...\nOct 14 13:53:42 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.\nOct 14 13:53:56 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...\nOct 14 13:53:57 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.\nOct 14 15:52:15 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...\nOct 14 15:52:15 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.\nOct 14 15:52:58 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...\nOct 14 15:52:59 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.", "stdout_lines": ["● firewalld.service - firewalld - dynamic firewall daemon", " Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)", " Active: inactive (dead)", " Docs: man:firewalld(1)", "", "Oct 14 13:23:20 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...", "Oct 14 13:23:21 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.", "Oct 14 13:53:42 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...", "Oct 14 13:53:42 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.", "Oct 14 13:53:56 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...", "Oct 14 13:53:57 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.", "Oct 14 15:52:15 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...", "Oct 14 15:52:15 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.", "Oct 14 15:52:58 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...", "Oct 14 15:52:59 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon."]}
...ignoring
TASK [debug] *************************************************************************************************************
ok: [localhost] => {
"command_result.stdout_lines, command_result.stderr_lines": "([u'\\u25cf firewalld.service - firewalld - dynamic firewall daemon', u' Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)', u' Active: inactive (dead)', u' Docs: man:firewalld(1)', u'', u'Oct 14 13:23:20 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...', u'Oct 14 13:23:21 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.', u'Oct 14 13:53:42 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...', u'Oct 14 13:53:42 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.', u'Oct 14 13:53:56 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...', u'Oct 14 13:53:57 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.', u'Oct 14 15:52:15 ip-10-0-1-135 systemd[1]: Starting firewalld - dynamic firewall daemon...', u'Oct 14 15:52:15 ip-10-0-1-135 systemd[1]: Started firewalld - dynamic firewall daemon.', u'Oct 14 15:52:58 ip-10-0-1-135 systemd[1]: Stopping firewalld - dynamic firewall daemon...', u'Oct 14 15:52:59 ip-10-0-1-135 systemd[1]: Stopped firewalld - dynamic firewall daemon.'], [])"
}
After this PR:
TASK [Collect facts about system services] ******************************************************************
ok: [localhost]
TASK [Get status of firewalld] ************************************************************************************************
ok: [localhost] => {
"msg": "firewalld is 'inactive' and 'disabled'\n"
}
As the result of the template processing is a file which will not be deleted after the role has finished (the file can be very useful for problem analysis or for documenting the installation steps), we should make sure that there is a comment which shows that this file has been created by the role.
See also https://docs.ansible.com/ansible/latest/collections/ansible/builtin/template_module.html .
Copy of linux-system-roles/sap-hana-preconfigure#194 (comment), reported by berndfinger:
... in /etc/sysconfig/network-scripts. So let's better ignore errors in task "Add largesend options to interfaces".
Then the SAR files can be placed in a central location and only the extracted files will be on the managed node.
This should include the ability to specify more than one tuned profile as documented in the tuned-adm man page.
It can be useful to have a look at the hdblcm configfile during execution and also to see the complete hdblcm command line before the command is called. We can set a variable with the content of the command line, then display it (it also contains the path name of the configfile), then execute it.
In case multiple installations are ongoing and extracting files to the same shared location as specified in variable sap_hana_install_software_extract_directory, we want to ensure that the extraction of SAR files only happens on one node and the other installations pause until the extraction of files has completed.
(no comment was provided in linux-system-roles/sap-preconfigure#171)
Copy of linux-system-roles/sap-preconfigure#151 (comment), reported by https://github.com/berndfinger:
A simple solution might be to run:
# awk 'BEGIN{a=1}/TASK/{gsub ("*", ""); task=$0}/RUNNING HANDLER/{a=0}/changed:/&&a==1{printf ("%s %s\n", $0, task)}'
on the output. It will print the task names in case a change was triggered by the task. Example:
changed: [managed_node_1] TASK [sap-preconfigure : Ensure required package groups are installed]
changed: [managed_node_1] TASK [sap-preconfigure : Ensure required packages are installed]
changed: [managed_node_1] TASK [sap-preconfigure : Call Reboot handler if necessary]
changed: [managed_node_1] TASK [sap-preconfigure : Set SELinux state]
changed: [managed_node_1] TASK [sap-preconfigure : Call Reboot handler if necessary]
changed: [managed_node_1] TASK [sap-preconfigure : Ensure short system hostname is set]
changed: [managed_node_1] TASK [sap-preconfigure : Ensure that the entry in /etc/hosts is correct]
changed: [managed_node_1] TASK [sap-preconfigure : Stop and disable service firewalld]
changed: [managed_node_1] TASK [sap-preconfigure : Configure tmpfs in /etc/fstab]
changed: [managed_node_1] TASK [sap-preconfigure : Trigger remounting if /dev/shm has not the expected size]
changed: [managed_node_1] => (item={'name': 'vm.max_map_count', 'value': '2147483647'}) TASK [sap-preconfigure : Set kernel parameters]
changed: [managed_node_1] => (item={'name': 'kernel.pid_max', 'value': '4194304'}) TASK [sap-preconfigure : Set kernel parameters]
changed: [managed_node_1] => (item=hard) TASK [sap-preconfigure : Set the hard and soft limit for the max number of open files per process (nofile) to 65536 for group sapsys]
changed: [managed_node_1] => (item=soft) TASK [sap-preconfigure : Set the hard and soft limit for the max number of open files per process (nofile) to 65536 for group sapsys]
changed: [managed_node_1] => (item=hard) TASK [sap-preconfigure : Set the hard and soft limit for the max number of processes per user (nproc) to unlimited for group sapsys]
changed: [managed_node_1] => (item=soft) TASK [sap-preconfigure : Set the hard and soft limit for the max number of processes per user (nproc) to unlimited for group sapsys]
changed: [managed_node_1] TASK [sap-preconfigure : Copy file /etc/tmpfiles.d/sap.conf]
Copy of linux-system-roles/sap-hana-preconfigure#64 (comment), reported by https://github.com/Klaas-:
Hi,
I think we should add support for RHV/oVirt to this role. They should be configured according to the red hat guide: https://access.redhat.com/sites/default/files/attachments/sap_hana_on_rhv_kvm_4.2_resource_guide_1.pdf
If I am not mistaken the only thing missing is the custom tuned profile: sap-hana-kvm-guest (maybe it would be a better idea to get that profile into the tuned packages and just activate it here)
This allows for easier handling of different OS installation and configuration steps. We already have the same structure in role sap_hana_preconfigure.
The role should be able to:
sap_hana_install_tag_preinstall
)/hana
, /hana/shared
, /hana/log
, and /hana/data
(proposed tag: sap_hana_install_tag_chown_hana_directories
)sap_hana_install_tag_create_configfile
)This helps analyzing problems and also reduces the time for development and testing.
Sample call for only processing the SAPCAR and SAR files:
# ansible-playbook sap-hana-install.yml --tags=sap_hana_install_tag_preinstall --skip-tags=sap_hana_install_tag_chown_hana_directories
Sample call for only creating the SAP HANA hdblcm configfile from the template file /templates/configfile.j2
:
# ansible-playbook sap-hana-install.yml --tags=sap_hana_install_tag_create_configfile
When comparing the hdblcm configfile template with the result of the Jinja2 templating, the default for the hostname is not used:
The corresponding line in the Jinja2 template is:
hostname={{ sap_hana_install_hostname|d('hana01') }}
The playbook does not set the variable sap_hana_install_hostname.
This is an extract of the comparison between the hdblcm configfile template and the result of the Jinja2 templating:
use_master_password=n | use_master_password=y
components= | components=all
hostname=hana01 | hostname=
sapadm_password= | sapadm_password=NewPass$321
sid= | sid=HD1
number= | number=00
I could not reproduce this error when testing the template processing with the same Jinja2 template in a simple playbook on the local host.
For some reason the the update of /etc/hosts fails. After running the role, here is how my /etc/hosts looks like:
10.103.15.16 rha-nw.rha-nw.c.deft-axon-212715.internal rha-nw
rha-hana.rha-nw.c.deft-axon-212715.internal rha-hana
while it has to be
10.103.15.16 rha-nw.c.deft-axon-212715.internal rha-nw
10.103.15.61 rha-hana.c.deft-axon-212715.internal rha-hana
Investigating where this happens ....
In case of multiple SAPCAR versions for the current hardware architecture, we need to execute the SAPCAR executable with option "--version". We need to ensure that at least for SAPCAR autodetection, no file is execute without checksum verification.
This is a copy of linux-system-roles/sap-preconfigure#98, reported by alexxa:
... in task "ensure required package groups are installed". An OS command which perform this task and which will result in the same error message is "yum install @server" or "yum group install server".
Copy of linux-system-roles/sap-preconfigure#174 (comment), reported by berndfinger:
The code change in berndfinger/sap-preconfigure@3b2b032 was not sufficient to solve linux-system-roles/sap-preconfigure#159.
One possible solution is to use set_fact in all tasks which can lead to a reboot requirement.
The current task "SAP HANA hdblcm prepare - Get SAPCAR executable file from folder - {{ sap_hana_install_software_directory }}" lists all SAPCAR*EXE files in the SAP HANA installation software directory on the managed node.
In case there is more than one SAPCAR version in the SAP HANA installation software directory, we can easily and reliably select the latest one as long as the output contains "kernel release" with the release as the last field, and a line with another pattern, e.g. "patch number". I verified that the following command sequence works for two SAPCAR x86_64 executables and also for one SAPCAR x86_64 executable:
for file in SAPCAR*EXE; do
printf "%s " $file;
./$file --version | awk '/kernel release/{rel=$NF}/patch number/{printf ("%s %s\n", rel, $NF)}'
done | sort -k 2 -nr -k 3 -nr | awk 'NR==1{print $1}'
Role sap_general_preconfigure wants to install compat-sap-c++ packages, so we should better let the role also enable the required SAP repos, similar to:
The role supports specifying the SAP HANA group id in variable sap_hana_install_groupid
, which is the id of the sapsys group.
The SAP HANA installation will fail if there is already a group named sapsys but with a different ID. It appears to be more appropriate to fail the role before starting the SAP HANA installation in this case.
With #57, the addhosts operation does no longer work because this part of the code had not been adapted to the dynamic configfile processing.
If there is more than one SAPHOSTAGENT file in the software directory, moving the contents of the second file to the correct location fails and the role aborts.
The same might happen if there is more than one file of any other software.
We can modify the order of checksum verification to only perform the checksum calculation after verifying that a checksum for comparison is available, as follows:
1 - Check if a specific or global checksum file exists
2 - If yes, get the checksum from the checksum file. If there is no checksum, fail
3 - Only if there is a checksum entry for the file, calculate the checksum of the file to be checked.
4 - Assert that the two checksum matches
We don't have to include a enforce_checksum_verification variable to the file dict which is passed to verify_checksum.yml, because:
We perform a checksum verification if:
1 - the variable sap_hana_install_enforce_checksum_verification is set to yes
, or
2 - if the variables for sapcar or sarfiles are not set, meaning that those files are auto-detected.
If the variable sap_hana_install_enforce_checksum_verification is not set or set to no
, and if the variables for sapcar or for the sarfiles are set, then we skip the checksum verification at all.
Copy of linux-system-roles/sap-preconfigure#172 (comment), reported by https://github.com/Klaas-):
Hi,
because of the log4j debacle we noticed log4j is installed on all our sap systems because group install of performance
(performance includes parfait which has a dependency to log4j).
https://github.com/linux-system-roles/sap-preconfigure/blob/master/vars/RedHat_7.yml#L22
I am not seeing parfait or log4j from the OS RPMs being used by SAP on our systems so I am guessing this is just installed because SAP was too lazy to properly list their dependencies.
Source of the group install requirement: https://launchpad.support.sap.com/#/notes/2002167
Maybe you could use your red hat contacts to get them to drop the requirement from their notes and/or at least remove performance from this role.
Greetings
Klaas
If a package resides on a slow file server, it is better to copy the archive before unpacking.
The variable sap_general_preconfigure_register_subscription_manager_release in tasks/RedHat/installation.yml appears before sap_general_preconfigure_set_minor_release. However, if sap_general_preconfigure_set_minor_release is set to no
, which is also the default, the variable sap_general_preconfigure_register_subscription_manager_release will not be defined.
Reverting the order of the when conditions will fix this bug.
Copy of linux-system-roles/sap-hana-preconfigure#124 (comment), reported by berndfinger:
See (for example) https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/virtualization_tuning_and_optimization_guide/chap-ksm#sect-KSM-Deactivating_KSM .
The SAP notes for recommended OS settings for SAP HANA on RHEL also have to be changed accordingly.
As per recommendation in recent Ansible module documentation, we should better rename all module names in roles to fully qualified collection names (FQCN).
RHEL 8.6 will be the next supported RHEL 8 minor release for SAP HANA, so we should add it to variable __sap_hana_preconfigure_supported_rhel_minor_releases already.
Copy of linux-system-roles/sap-hana-preconfigure#146 (comment) (comment by berndfinger):
to support the installation of HANA Cockpit
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.