From a453f4b7068611c510f75c5a75db0386d5d13211 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Thu, 24 Mar 2022 10:11:06 +0800 Subject: [PATCH 001/130] updated releasenotes docs of master --- ...mon-vulnerabilities-and-exposures-(cve).md | 2 +- .../en/docs/Releasenotes/installing-the-os.md | 30 +++++++-------- docs/en/docs/Releasenotes/key-features.md | 37 +++++++++++-------- docs/en/docs/Releasenotes/release_notes.md | 2 +- docs/en/docs/Releasenotes/user-notice.md | 5 ++- docs/en/menu/index.md | 2 +- 6 files changed, 43 insertions(+), 35 deletions(-) diff --git a/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md b/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md index 4286b2459..1485fd759 100644 --- a/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md +++ b/docs/en/docs/Releasenotes/common-vulnerabilities-and-exposures-(cve).md @@ -1,4 +1,4 @@ # Common Vulnerabilities and Exposures (CVEs) -For CVEs involved in the version, see the [CVE list](https://www.openeuler.org/en/security/cve/). +For details about the CVEs involved in the version, see the [CVE list](https://www.openeuler.org/en/security/cve/). diff --git a/docs/en/docs/Releasenotes/installing-the-os.md b/docs/en/docs/Releasenotes/installing-the-os.md index 46cb1a80c..80f737499 100644 --- a/docs/en/docs/Releasenotes/installing-the-os.md +++ b/docs/en/docs/Releasenotes/installing-the-os.md @@ -1,20 +1,20 @@ -# Installing the OS +# OS Installation ## Release Files -The openEuler release files include [ISO release pacakges](http://repo.openeuler.org/openEuler-21.09/ISO/), [VM images](http://repo.openeuler.org/openEuler-21.09/virtual_machine_img/), [containier images](http://repo.openeuler.org/openEuler-21.09/docker_img/), [edge images](http://repo.openeuler.org/openEuler-21.09/edge_img/), [embedded images](https://repo.openeuler.org/openEuler-21.09/edge_img/), and [repo sources](http://repo.openeuler.org/openEuler-21.09/). The following tables describe those files respectively. +The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. Table 1 ISO release packages | Name | Description | | ------------------------------------------ | ------------------------------------------------------------ | -| openEuler-21.03-aarch64-dvd.iso | Basic installation ISO file of the AArch64 architecture, including the core components for running the minimum system. | -| openEuler-21.03-everything-aarch64-dvd.iso | Full installation ISO file of the AArch64 architecture, including all components for running the entire system. | -| openEuler-21.03-debuginfo-aarch64-dvd.iso | ISO file for openEuler debugging in the AArch64 architecture, including the symbol table information required for debugging. | -| openEuler-21.03-x86_64-dvd.iso | Basic installation ISO file of the x86_64 architecture, including the core components for running the minimum system. | -| openEuler-21.03-everything-x86_64-dvd.iso | Full installation ISO file of the x86_64 architecture, including all components for running the entire system. | -| openEuler-21.03-debuginfo-x86_64-dvd.iso | ISO file for openEuler debugging in the x86_64 architecture, including the symbol table information required for debugging. | -| openEuler-21.03-source-dvd.iso | ISO file of the openEuler source code. | +| openEuler-22.03-LTS-aarch64-dvd.iso | Base installation ISO file of the AArch64 architecture, including the core components for running the minimum system. | +| openEuler-22.03-LTS-everything-aarch64-dvd.iso | Full installation ISO file of the AArch64 architecture, including all components for running the entire system. | +| openEuler-22.03-LTS-everything-debug-aarch64-dvd.iso | ISO file for openEuler debugging in the AArch64 architecture, including the symbol table information required for debugging. | +| openEuler-22.03-LTS-x86_64-dvd.iso | Base installation ISO file of the x86_64 architecture, including the core components for running the minimum system. | +| openEuler-22.03-LTS-everything-x86_64-dvd.iso | Full installation ISO file of the x86_64 architecture, including all components for running the entire system. | +| openEuler-22.03-LTS-everything-debuginfo-x86_64-dvd.iso | ISO file for openEuler debugging in the x86_64 architecture, including the symbol table information required for debugging. | +| openEuler-22.03-LTS-source-dvd.iso | ISO file of the openEuler source code. | | openEuler-21.09-edge-aarch64-dvd.iso | Edge ISO file in the AArch64 architecture, including the core components for running the minimum system. | | openEuler-21.09-edge-x86_64-dvd.iso | Edge ISO file in the x86_64 architecture, including the core components for running the minimum system. | @@ -22,8 +22,8 @@ Table 2 VM images | Name | Description | | -------------------------------- | -------------------------------------------------- | -| openEuler-21.03.aarch64.qcow2.xz | VM image of openEuler in the AArch64 architecture. | -| openEuler-21.03.x86_64.qcow2.xz | VM image of openEuler in the x86_64 architecture. | +| openEuler-22.03-LTS-aarch64.qcow2.xz | VM image of openEuler in the AArch64 architecture. | +| openEuler-22.03-LTS-x86_64.qcow2.xz | VM image of openEuler in the x86_64 architecture. | Note: The default password of **root** user of the VM image is **openEuler12#$**. Change the password upon the first login. @@ -51,7 +51,7 @@ Table 4 Repo sources ## Minimum Hardware Specifications -The following table lists the minimum hardware specifications for openEuler 21.03. +The following table lists the minimum hardware specifications for openEuler 22.03 LTS. Table 1 Minimum hardware requirements @@ -63,7 +63,7 @@ Table 1 Minimum hardware requirements ## Hardware Compatibility -The following table lists the supported servers and configurations of openEuler. +The following table describes the servers and configurations supported by openEuler. openEuler will support more servers in the future. Partners and developers are welcome to participate in the contribution and verification. For details about the servers supported by openEuler, see the [Compatibility List](https://www.openeuler.org/en/compatibility/). Table 1 Supported servers and configurations @@ -92,7 +92,7 @@ Table 1 Supported servers and configurations

Memory

-

32G\*4 2933MHz

+

4 x 32 GB 2933 MHz

RAID card

@@ -118,7 +118,7 @@ Table 1 Supported servers and configurations

Memory

-

32*4 2400MHz

+

4 x 32 GB 2400 MHz

RAID card

diff --git a/docs/en/docs/Releasenotes/key-features.md b/docs/en/docs/Releasenotes/key-features.md index b33be6a0a..648020be1 100644 --- a/docs/en/docs/Releasenotes/key-features.md +++ b/docs/en/docs/Releasenotes/key-features.md @@ -16,7 +16,7 @@ In-depth optimizations of scheduling, I/O, and memory management have been perfo - **Huge page vmalloc performance optimization**: When calling vmalloc() to allocate spaces that exceed the minimum size of huge pages, the huge page instead of the base page is used to map the memory, improving the TLB usage and reducing TLB misses. -- **Uncorrectable error (UCE) fault tolerance**: When a UCE occurs in the copy-on-write (COW) or pagecache scenario in kernel mode, the system kills the user-mode process instead of panicking. This feature is disabled by default, you can enable it by adding **CONFIG_UCE_KERNEL_RECOVERY** to the kernel configuration, and configure it in the kernel boot parameter interface **/proc/cmdline** (add **uce_kernel_recovery=[0,3]**) and proc interface **/proc/sys/kernel/uce_kernel_recovery**. +- **Uncorrectable error (UCE) fault tolerance**: When a UCE occurs in the copy_from_user scenario, the system kills the associated user-mode process instead of kernel panicking. This feature is disabled by default. You can enable it by adding **CONFIG_UCE_KERNEL_RECOVERY** to the kernel configuration, and configure it in the kernel boot parameter interface **/proc/cmdline** (add **uce_kernel_recovery=[0,4]**) and proc interface **/proc/sys/kernel/uce_kernel_recovery**. ## File System for New Media @@ -29,6 +29,10 @@ Various memory and storage media can be used to expand the system memory capacit - **User-mode swap**: The evicted cold memory can be swapped to the user-mode storage based on a preset etMem policy. The user-mode swap delivers a higher performance than the kernel-mode swap and the whole swap process is transparent to users. +## User-Mode Protocol Stack +The Gazelle user-mode protocol stack is added. It can be used without application program modification or recompilation, supporting high-performance and low-latency network transmission for upper-layer services. + +- **Gazelle user-mode protocol stack**: Powered by dpdk and lwip, Gazelle is a lock-free and multi-thread high-performance user-mode protocol stack to improve the network performance of applications. It can be used without modification, adaptation, or recompilation. ## Enhanced Cloud Native Scheduling @@ -36,21 +40,26 @@ In cloud service scenarios, online interactive services are sensitive to latenci - **Quality Aware Scheduler (QAS)**: It ensures that online tasks quickly preempt CPU resources, schedules tasks in a deterministic manner, and suppresses interference from offline tasks. - **Memory reclamation for OOM**: When OOM occurs, memory reclamation is preferentially performed for process groups with low priorities to ensure the normal running of online services. +- **Hybrid container deployment framework**: In a hybrid Kubernetes cluster, openEuler users only need to add online or offline labels to services. The system can automatically detect service creation and configure resources based on service priorities to implement resource isolation and preemption. + +## QEMU Hot Patch +- **LibcarePlus**: It is a hot patch framework that can fix QEMU process bugs without affecting VM services. ## KubeOS KubeOS is a container operating system, which centrally manages cloud native cluster OSs in containers. It has the following features: -- Supports OS containerization and Kubernetes interconnection for unified OS management and atomized lifecycle management -- Supports lightweight OS tailoring, which reduces unnecessary packages for quicker upgrades and replacements. +- **OS containerization**: Interconnection with Kubernetes facilitates unified OS management and atomized lifecycle management. +- **Lightweight OS tailoring**: This reduces unnecessary packages for quicker upgrades and replacements. ## Enhanced Lightweight Secure Container Based on Stratovirt, a lightweight virtualization technology, containers have low load and VMs are more secure. -- Supports UEFI boot, ACPI table construction, and addition of PCIe/PCI devices (including vrtio-pci) to VMs. -- Supports VFIO, allowing physical devices on the host to be accessed from VMs and enabling VMs to obtain high performance close to raw devices. +- **UEFI boot**: Supports UEFI boot, ACPI table construction, and addition of PCIe/PCI devices (including vrtio-pci) to VMs. +- **VFIO**: It allows physical devices on the host to be accessed from VMs and enables VMs to obtain high performance close to raw devices. +- **Hot swap of passthrough devices**: Devices such as virtio-blk-pci, virtio-net-pci, and VFIO can be hot swapped. This prevents system shutdown and service interruption caused by peripheral replacement. ## Enhanced iSulad @@ -80,14 +89,10 @@ Basic capabilities, such as lightweight, security hardening, and lightweight con - **Security hardening**: Security hardening is performed on resources such as account passwords and file permissions. OS security is enabled by default. - **Lightweight containers**: Standard container images can be deployed and run in lightweight containers in embedded scenarios. - **Multi-architecture support**: The ARM32 and ARM64 chip architectures are supported. - -## Intelligent O&M A-Ops - -The basic intelligent O&M framework provides basic capabilities such as configuration tracing, architecture awareness, and fault locating to support quick troubleshooting and reduce O&M costs. - -- **Application topology awareness**: The eBPF-based low-load probe framework provides automatic network topology awareness and detection capabilities at the application level. -- **Configuration tracing**: implements the configuration baseline and comparison functions and quickly rectify configuration problems. -- **Intelligent fault locating**: A-Ops supports exception detection and user-defined fault tree, and provides an expert-mode engine to detect system faults in real time and rectify system faults in a timely manner, reducing system downtime and O&M costs. +- **Hybrid deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. +- **Small-scale tailoring**: Small-scale tailoring based on the Yocto build package is supported. ARM Cross Compilation +- **ARM cross compilation tool**: The ARM cross compilation tool chain is provided based on GCC 10.3 of the community. +- **Distributed soft bus (DSoftBus)**: The DSoftBus of HarmonyOS is integrated to implement interconnection and interworking between embedded devices running on openEuler. ## secPaver @@ -106,5 +111,7 @@ secPaver is an SELinux policy development tool used to assist developers in deve More desktop environments are provided to ensure better development experience. -- DDE is upgraded and supports drawing board, music, and cinema applications. -- UKUI is upgraded and supports the Chinese input method and multimedia. \ No newline at end of file +- **DDE** is upgraded and supports drawing board, music, and cinema applications. +- **UKUI** is upgraded and supports the Chinese input method and multimedia. +- **kiran-desktop** is supported. +- **GNOME** is supported. \ No newline at end of file diff --git a/docs/en/docs/Releasenotes/release_notes.md b/docs/en/docs/Releasenotes/release_notes.md index 146d127b1..ce3d0b760 100644 --- a/docs/en/docs/Releasenotes/release_notes.md +++ b/docs/en/docs/Releasenotes/release_notes.md @@ -1,3 +1,3 @@ # Release Notes -This document is the release notes for the openEuler 21.03 release version. \ No newline at end of file +This document is the release notes of openEuler 22.03 LTS. \ No newline at end of file diff --git a/docs/en/docs/Releasenotes/user-notice.md b/docs/en/docs/Releasenotes/user-notice.md index 65e12ded9..60f0e9f9f 100644 --- a/docs/en/docs/Releasenotes/user-notice.md +++ b/docs/en/docs/Releasenotes/user-notice.md @@ -1,5 +1,6 @@ # User Notice -- The version number counting rule of openEuler is changed from openEuler _x.x_ to openEuler _year_._month_. For example, openEuler 21.03 indicates that the version is released in March 2020. -- The [Python core team](https://www.python.org/dev/peps/pep-0373/#update) has stopped maintaining Python 2 in January 2020. In 2020, openEuler 21.03 fixes only the critical CVE of Python 2 and will reach the end of maintenance \(EOM\) on December 31, 2020. Please switch to Python 3 as soon as possible. +- The version number counting rule of openEuler is changed from openEuler _x.x_ to openEuler _year_._month_. For example, openEuler 21.03 indicates that the version is released in March 2021. +- The [Python core team](https://www.python.org/dev/peps/pep-0373/#update) has stopped maintaining Python 2 in January 2020. Python 2 reached end of maintenance (EOM) on December 31, 2020. In 2021, openEuler 21.03 fixed only the critical CVEs related to Python 2. Please switch to Python 3 as soon as possible. +- From openEuler 22.03 LTS, only Python 3 is supported. Please switch to Python 3 to use the OS. diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 16cd18d03..d4921b293 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -5,7 +5,7 @@ headless: true - [Release Notes]({{< relref "./docs/Releasenotes/release_notes.md" >}}) - [User Notice]({{< relref "./docs/Releasenotes/user-notice.md" >}}) - [Introduction]({{< relref "./docs/Releasenotes/introduction.md" >}}) - - [Installing the OS]({{< relref "./docs/Releasenotes/installing-the-os.md" >}}) + - [OS Installation]({{< relref "./docs/Releasenotes/installing-the-os.md" >}}) - [Key Features]({{< relref "./docs/Releasenotes/key-features.md" >}}) - [Known Issues]({{< relref "./docs/Releasenotes/known-issues.md" >}}) - [Resolved Issues]({{< relref "./docs/Releasenotes/resolved-issues.md" >}}) -- Gitee From aaf41aa2079f6dd80a220cd3d62727b3fe70ed44 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Thu, 24 Mar 2022 10:45:27 +0800 Subject: [PATCH 002/130] updated installation-modes.md --- docs/en/docs/Installation/installation-modes.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/en/docs/Installation/installation-modes.md b/docs/en/docs/Installation/installation-modes.md index d291e2077..e06583f90 100644 --- a/docs/en/docs/Installation/installation-modes.md +++ b/docs/en/docs/Installation/installation-modes.md @@ -103,12 +103,14 @@ Pay attention to the capacity of the USB flash drive. The USB flash drive must h ``` # dd if=/home/testuser/Downloads/openEuler-21.09-aarch64-dvd.iso of=/dev/sdb bs=512k ``` +>![](./public_sys-resources/icon-note.gif) **NOTE** +>As described in ISOLINUX, the ISO 9660 file system created by the **mkisofs** command will boot through BIOS firmware, but only from the CD-ROM, DVD-ROM, or BD. In this case, you need to run the **isohybrid -u your.iso** command to process the ISO file and then run the **dd** command to write the ISO file to the USB flash drive. (This problem affects only the x86 architecture.) 5. After the image is written, remove the USB flash drive. No progress is displayed during the image write process. When the number sign (#) appears again, run the following command to write the data to the drive. Then exit the **root** account and remove the USB flash drive. In this case, you can use the USB drive as the installation source of the system. - ``` + ```bash # sync ``` -- Gitee From 0368f76a05b49ec6a8016c0b6cb3cbba07b3326b Mon Sep 17 00:00:00 2001 From: gomico Date: Thu, 24 Mar 2022 16:55:32 +0800 Subject: [PATCH 003/130] =?UTF-8?q?update=20translation=20for=20the=20foll?= =?UTF-8?q?owing=20zh=20docs=20LibcarePlus.md=20at=20f8953c3=20=E5=B7=A5?= =?UTF-8?q?=E5=85=B7=E4=BD=BF=E7=94=A8=E6=8C=87=E5=8D=97.md=20at=201d2e0d4?= =?UTF-8?q?=20vmtop.md=20at=201d2e0d4=20FAQ-54.md=20at=203aa66c7=20?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5iSula=E5=AE=89=E5=85=A8=E5=AE=B9=E5=99=A8.md?= =?UTF-8?q?=20at=2064692d9=20=E8=B4=A6=E6=88=B7=E5=8F=A3=E4=BB=A4.md=20at?= =?UTF-8?q?=2072fd461=20KubeEdge=E9=83=A8=E7=BD=B2=E6=8C=87=E5=8D=97.md=20?= =?UTF-8?q?at=209b782f7=20=E6=8E=A5=E5=8F=A3=E5=8F=82=E8=80=83.md=20at=20b?= =?UTF-8?q?6e7836=20=E8=99=9A=E6=8B=9F=E6=9C=BA=E7=AE=A1=E7=90=86.md=20at?= =?UTF-8?q?=20759a34f?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/Administration/faqs.md | 42 +- .../KubeEdge/kubeedge-deployment-guide.md | 1378 ++--------------- docs/en/docs/SecHarden/account-passwords.md | 34 +- docs/en/docs/StratoVirt/VM_management.md | 206 ++- docs/en/docs/StratoVirt/interconnect_isula.md | 90 +- docs/en/docs/Virtualization/LibcarePlus.md | 410 +++++ docs/en/docs/Virtualization/tool-guide.md | 197 +-- docs/en/docs/Virtualization/vmtop.md | 196 +++ docs/en/docs/secGear/api-description.md | 3 + docs/en/menu/index.md | 2 + 10 files changed, 1049 insertions(+), 1509 deletions(-) create mode 100644 docs/en/docs/Virtualization/LibcarePlus.md create mode 100644 docs/en/docs/Virtualization/vmtop.md diff --git a/docs/en/docs/Administration/faqs.md b/docs/en/docs/Administration/faqs.md index bf8aeebad..c18ba5615 100644 --- a/docs/en/docs/Administration/faqs.md +++ b/docs/en/docs/Administration/faqs.md @@ -2,17 +2,18 @@ - [FAQs](#faqs) - - [Why Is the Memory Usage of the libvirtd Service Queried by Running the systemctl and top Commands Different?](#why-is-the-memory-usage-of-the-libvirtd-service-queried-by-running-the-systemctl-and-top-commands-different) - - [An Error Occurs When stripsize Is Set to 4 During RAID 0 Volume Configuration](#an-error-occurs-when-stripsize-is-set-to-4-during-raid-0-volume-configuration) - - [Failed to Compile MariaDB Using rpmbuild](#failed-to-compile-mariadb-using-rpmbuild) - - [Failed to Start the SNTP Service Using the Default Configuration](#failed-to-start-the-sntp-service-using-the-default-configuration) - - [Installation Failure Caused by Software Package Conflict, File Conflict, or Missing Software Package](#installation-failure-caused-by-software-package-conflict-file-conflict-or-missing-software-package) - - [Failed to Downgrade libiscsi](#failed-to-downgrade-libiscsi) - - [Failed to Downgrade xfsprogs](#failed-to-downgrade-xfsprogs) - - [CPython/Lib Detects CVE-2019-9674: Zip Bomb](#cpython/lib-detects-cve-2019-9674:-zip-bomb) - - [ReDoS Attack Occurs Due to Improper Use of glibc Regular Expressions](#redos-attack-occurs-due-to-improper-use-of-glibc-regular-expressions) - - [An Error Is Reported When gdbm-devel Is Installed or Uninstalled During the Installation and Uninstallation of httpd-devel and apr-util-devel](#an-error-is-reported-when-gdbm-devel-is-installed-or-uninstalled-during-the-installation-and-uninstallation-of-httpd-devel-and-apr-util-devel) - - [An rpmdb Error Is Reported When Running the yum or dnf Command After the System Is Rebooted](#an-rpmdb-error-is-reported-when-running-the-yum-or-dnf-command-after-the-system-is-rebooted) + - [Why Is the Memory Usage of the libvirtd Service Queried by Running the systemctl and top Commands Different?](#why-is-the-memory-usage-of-the-libvirtd-service-queried-by-running-the-systemctl-and-top-commands-different) + - [An Error Occurs When stripsize Is Set to 4 During RAID 0 Volume Configuration](#an-error-occurs-when-stripsize-is-set-to-4-during-raid-0-volume-configuration) + - [Failed to Compile MariaDB Using rpmbuild](#failed-to-compile-mariadb-using-rpmbuild) + - [Failed to Start the SNTP Service Using the Default Configuration](#failed-to-start-the-sntp-service-using-the-default-configuration) + - [Installation Failure Caused by Software Package Conflict, File Conflict, or Missing Software Package](#installation-failure-caused-by-software-package-conflict-file-conflict-or-missing-software-package) + - [Failed to Downgrade libiscsi](#failed-to-downgrade-libiscsi) + - [Failed to Downgrade xfsprogs](#failed-to-downgrade-xfsprogs) + - [CPython/Lib Detects CVE-2019-9674: Zip Bomb](#cpythonlib-detects-cve-2019-9674-zip-bomb) + - [ReDoS Attack Occurs Due to Improper Use of glibc Regular Expressions](#redos-attack-occurs-due-to-improper-use-of-glibc-regular-expressions) + - [An Error Is Reported When gdbm-devel Is Installed or Uninstalled During the Installation and Uninstallation of httpd-devel and apr-util-devel](#an-error-is-reported-when-gdbm-devel-is-installed-or-uninstalled-during-the-installation-and-uninstallation-of-httpd-devel-and-apr-util-devel) + - [An rpmdb Error Is Reported When Running the yum or dnf Command After the System Is Rebooted](#an-rpmdb-error-is-reported-when-running-the-yum-or-dnf-command-after-the-system-is-rebooted) + - [Failed to Run `rpmrebuild -d /home/test filesystem` to Rebuild the **filesystem** Package](#failed-to-run-rpmrebuild--d-hometest-filesystem-to-rebuild-the-filesystem-package) @@ -331,3 +332,22 @@ A core dump occurs on the process that uses the regular expression. The glibc re Step 1 Run the `kill -9` command to terminate all running RPM-related commands. Step 2 Delete all **/var/lib/rpm/__db.00*** files. Step 3 Run the `rpmdb --rebuilddb` command to rebuild the RPM database. + +## Failed to Run `rpmrebuild -d /home/test filesystem` to Rebuild the **filesystem** Package + +### Symptom + +Failed to run the `rpmrebuild --comment-missing=y --keep-perm -b -d /home/test filesystem-3.16-3.oe1.aarch64` command to rebuild the **filesystem** package. The following information is displayed: +```shell +/usr/lib/rpmrebuild/rpmrebuild.sh:Error:(RpmBuild) Package 'filesystem-3.16-3.oe1.aarch64' build failed. +/usr/lib/rpmrebuild/rpmrebuild.sh:Error: RpmBuild +``` + +### Possible Cause +The software package creates the directory in the **%pretrans -p** phase, and modify the diretory in the **%ghost** phase. If you create a file or diretory in the diretory and use `rpmrebuild` to build the package, the created file or directory will be included in the package. + +The root cause of the symptom is that **filesystem** creates the **/proc** diretory in the **%pretrans** phase and modifies the directory in the **%ghost** phase, but some small processes are dynamically created during system running. As a result, `rpmrebuild` cannot include the processes in the package because they are not files or diretories and fails to rebuild the package. + +### Solution + +Do not use `rpmrebuild` to rebuild the **filesystem** package. \ No newline at end of file diff --git a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md index ac273dca0..e35d2bd77 100644 --- a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md +++ b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md @@ -6,19 +6,19 @@ KubeEdge is an open source system dedicated to solving problems in edge scenarios. It extends the capabilities of containerized application orchestration and device management to edge devices. Based on Kubernetes, KubeEdge provides core infrastructure support for networks, application deployment, and metadata synchronization between the cloud and the edge. KubeEdge supports MQTT and allows for custom logic to enable communication for the resource-constrained devices at the edge. KubeEdge consists of components deployed on the cloud and edge nodes. The components are now open source. -> https://kubeedge.io/ +> https://kubeedge.io/ ### iSulad iSulad is a lightweight container runtime daemon designed for IoT and cloud infrastructure. It is lightweight, fast, and is not restricted by hardware specifications or architectures. It is suitable for wide application in various scenarios, such as cloud, IoT, and edge computing. -> https://gitee.com/openeuler/iSulad +> https://gitee.com/openeuler/iSulad -## Preparations +## Cluster Overview ### Component Versions -| Component| Version| +| Component | Version | | ---------- | --------------------------------- | | OS | openEuler 21.09 | | Kubernetes | 1.20.2-4 | @@ -27,487 +27,197 @@ iSulad is a lightweight container runtime daemon designed for IoT and cloud infr ### Node Planning Example -| Node| Location| Components| -| ------------ | ------------- | -------------------------------- | -| 9.63.252.224 | Cloud| Kubernetes (Master), iSulad, CloudCore| -| 9.63.252.227 | Edge| iSulad, EdgeCore| - -### Environment Configurations +| Node | Location | Components | +| -------------- | -------- | -------------------------------- | +| cloud.kubeedge | Cloud | Kubernetes (Master), iSulad, CloudCore | +| edge.kubeedge | Edge | iSulad, EdgeCore | -Configure the following settings on the cloud and edge nodes: +> Note: You can run the `hostnamectl set-hostname [cloud,edge].kubeedge` command to set the cloud and edge node names in advance. -```bash -# Disable the firewall. -$ systemctl stop firewalld -$ systemctl disable firewalld - -# Disable SELinux. -$ setenforce 0 - -# Configure the network, and enable the required forwarding mechanism. -$ cat >> /etc/sysctl.d/k8s.conf <> /etc/hosts << EOF -9.63.252.224 cloud.kubeedge -9.63.252.227 edge.kubeedge -EOF - -# Choose an accessible NTP server to synchronize the clock. -$ ntpdate cn.pool.ntp.org - -# Install the cri-tools network tool. -$ wget --no-check-certificate https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.20.0/crictl-v1.20.0-linux-amd64.tar.gz -$ tar zxvf crictl-v1.20.0-linux-amd64.tar.gz -C /usr/local/bin - -# Install the CNI network plugins. -$ wget --no-check-certificate https://github.com/containernetworking/plugins/releases/download/v0.9.0/cni-plugins-linux-amd64-v0.9.0.tgz -$ mkdir -p /opt/cni/bin -$ tar -zxvf cni-plugins-linux-amd64-v0.9.0.tgz -C /opt/cni/bin -``` +## Preparations -### Configuring iSulad +### Tool Package Download -Configure the following settings on the cloud and edge nodes: +[kubeedge-tools](https://gitee.com/Poorunga/kubeedge-tools) provides complete offline installation packages and deployment scripts for easy and quick KubeEdge cluster deployment even if the node cannot access the Internet. ```bash -# Configure iSulad (only the items to be modified are listed). -$ cat /etc/isulad/daemon.json -{ - "registry-mirrors": [ - "docker.io" - ], - "insecure-registries": [ - "k8s.gcr.io", - "quay.io", - "hub.oepkgs.net" - ], - "pod-sandbox-image": "k8s.gcr.io/pause:3.2", - "network-plugin": "cni", - "cni-bin-dir": "/opt/cni/bin", - "cni-conf-dir": "/etc/cni/net.d", -} - -# Configure the proxy if the node cannot directly access the Internet. Otherwise, skip this section. -$ cat /usr/lib/systemd/system/isulad.service -[Service] -Type=notify -Environment="HTTP_PROXY=http://..." -Environment="HTTPS_PROXY=http://..." - -# Restart the iSulad and set it to start upon system startup. -$ systemctl daemon-reload && systemctl restart isulad -``` +# Download and decompress the kubeedge-tools package on both the cloud and edge nodes. +$ wget -O kubeedge-tools.zip https://gitee.com/Poorunga/kubeedge-tools/repository/archive/master.zip +$ unzip kubeedge-tools.zip -### Deploying the Kubernetes Components +# Go to the kubeedge-tools directory for all the subsequent operations. +$ cd kubeedge-tools-master +``` -Install and deploy the Kubernetes components on the cloud node only. +### Kubernetes Deployment -```bash -# Install the Kubernetes tools. -$ yum install kubernetes-master kubernetes-kubeadm kubernetes-client kubernetes-kubelet -# Set kubelet to start upon system startup. -$ systemctl enable kubelet --now +Perform the following operations on the cloud node only. -# Note that the system proxy must be canceled before using the kubeadm init command. -$ unset `env | grep -iE "tps?_proxy" | cut -d= -f1` -$ env | grep proxy +#### Initializing the Cloud Environment -# Run the kubeadm init command. -$ kubeadm init --kubernetes-version v1.20.2 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock -# The default Kubernetes component image is gcr.k8s.io. You can add the --image-repository=xxx option to configure a custom image repository address (to test your own Kubernetes image). - -# Note that the network segment specified by pod-network-cidr cannot overlap the network segment of the host machine. Otherwise, the network is inaccessible. -# You are advised to run the init command before configuring the network. -Your Kubernetes control-plane has initialized successfully! +```bash +$ ./setup-cloud.sh +``` -To start using your cluster, you need to run the following as a regular user: +#### Deploying Kubernetes - mkdir -p $HOME/.kube - sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config - sudo chown $(id -u):$(id -g) $HOME/.kube/config +Deploy Kubernetes by referring to the [Kubernetes Cluster Deployment Guide](https://docs.openeuler.org/en/docs/21.09/docs/Kubernetes/Kubernetes.html). -You should now deploy a pod network to the cluster. -Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: - https://kubernetes.io/docs/concepts/cluster-administration/addons/ +> Note: Preferentially, use `kubeadm` to deploy Kubernetes if the cloud node has access to the Internet. The procedure is as follows: -Then you can join any number of worker nodes by running the following on each as root: +```bash +$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +... +Your Kubernetes control-plane has initialized successfully! ... -# Run the commands as prompted. -mkdir -p $HOME/.kube -cp -i /etc/kubernetes/admin.conf $HOME/.kube/config -chown $(id -u):$(id -g) $HOME/.kube/config -# The commands make a copy of admin.conf, which is a kubectl configuration file initialized by the kubeadm command. -# The file contains important configurations, such as the authentication information. - -# You can reset the configurations if an error occurs when running the init command. -$ kubeadm reset - -# If "Unable to read config path "/etc/kubernetes/manifests"" is displayed, run the following command: -$ mkdir -p /etc/kubernetes/manifests +# After Kubernetes is installed, copy the specified file to the directory as prompted. +# mkdir -p $HOME/.kube +# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +# sudo chown $(id -u):$(id -g) $HOME/.kube/config ``` -### Configuring the Network +#### Configuring Network for the Cloud Container -Because **the Calico network plugin cannot run on edge nodes**, `flannel` is used instead. The [issue](https://github.com/kubeedge/kubeedge/issues/2788#issuecomment-907627687) has been submitted to the KubeEdge community. - -The cloud and edge nodes are in different network environments and require different **affinity**. Therefore, two flannel configuration files are required. +Container Network Interface (CNI) software that provides network for Kubernetes nodes include [flannel](https://github.com/flannel-io/flannel), [Calico](https://github.com/projectcalico/calico), [Cilium](https://github.com/cilium/cilium), and more. If you have not decided which CNI software to use, run the following command to configure network for the cloud container: ```bash -# Download the flannel network plugin. -$ wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml - -# Prepare for network configuration for the cloud node. -$ cp kube-flannel.yml kube-flannel-cloud.yml - -# Modify the network configuration for the cloud node. -$ patch kube-flannel-cloud.yml - < -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959661 424578 signcerts.go:100] Succeed to creating token -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959716 424578 server.go:44] start unix domain socket server -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.959973 424578 uds.go:71] listening on: //var/lib/kubeedge/kubeedge.sock -Aug 29 10:50:15 cloud.kubeedge cloudcore[424578]: I0829 10:50:15.966693 424578 server.go:64] Starting cloudhub websocket server -Aug 29 10:50:17 cloud.kubeedge cloudcore[424578]: I0829 10:50:17.847150 424578 upstream.go:63] Start upstream devicecontroller +# active (running) indicates a normal status +$ systemctl status cloudcore | grep running + Active: active (running) since Fri 2022-03-04 10:54:30 CST; 5min ago ``` CloudCore has been deployed on the cloud node. Then, deploy EdgeCore on the edge node. -### Managing the Edge Node - -Run the `keadm join` command on the edge node to manage it. +### EdgeCore Deployment -#### Modifying iSulad Configurations +Perform the following operations only on the edge node unless otherwise specified. -File path: `/etc/isulad/daemon.json` +#### Initializing the Edge Environment ```bash -{ - # Set pod-sandbox-image. - "pod-sandbox-image": "kubeedge/pause:3.1", - # The listening port `10350` of EdgeCore conflicts with the WebSocket port of iSulad. As a result, EdgeCore cannot be started. To resolve the conflict, change the value of `websocket-server-listening-port` in the iSulad configuration file (`/etc/isulad/daemon.json`) to `10351`. - "websocket-server-listening-port": 10351, -} +$ ./setup-edge.sh ``` -After the configuration file is modified, run the `systemctl restart isulad` command to restart iSulad. +#### Managing the Edge Node +```bash +# Run the keadm gettoken command on the cloud node. +$ keadm gettoken +96058ab80ffbeb87fe58a79bfb19ea13f9a5a6c3076a17c00f80f01b406b4f7c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDY0NDg4NzF9.1mJegWB7SUVjgf-OvAqILgbZXeMHR9eOzMxpNFc42SI +# Save this token for subsequent steps. -#### Connecting EdgeCore to CloudCore + +# Run the keadm join command on the edge node. +# Set --cloudcore-ipport to the IP address and port number (10000) of the cloud node. Set --token to the token saved in the previous step. +$ keadm join --cloudcore-ipport=clou_node_IP_address:10000 --kubeedge-version=1.8.0 --token=96058ab80ffbeb87fe58a79bfb19ea13f9a5a6c3076a17c00f80f01b406b4f7c.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2NDY0NDg4NzF9.1mJegWB7SUVjgf-OvAqILgbZXeMHR9eOzMxpNFc42SI +... +KubeEdge edgecore is running... +``` + +#### Configuring EdgeCore ```bash -# Obtain a token on the cloud node. -$ keadm gettoken -28c25d3b137593f5bbfb776cf5b19866ab9727cab9e97964dd503f87cd52cbde.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzAyOTE4MTV9.aGUyCi9gdysVtMu0DQzrD5TcV_DcXob647YeqcOxKDA - -# Run the keadm join command to connect EdgeCore to CloudCore. -# --cloudcore-ipport is a mandatory parameter. 10000 is the default port of CloudCore. -$ keadm join --cloudcore-ipport=9.63.252.224:10000 --kubeedge-version=1.8.0 --token=28c25d3b137593f5bbfb776cf5b19866ab9727cab9e97964dd503f87cd52cbde.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzAyOTE4MTV9.aGUyCi9gdysVtMu0DQzrD5TcV_DcXob647YeqcOxKDA -Host has mosquit+ already installed and running. Hence skipping the installation steps !!! -kubeedge-v1.8.0-linux-amd64.tar.gz checksum: -checksum_kubeedge-v1.8.0-linux-amd64.tar.gz.txt content: -[Run as service] start to download service file for edgecore -[Run as service] success to download service file for edgecore -kubeedge-v1.8.0-linux-amd64/ -kubeedge-v1.8.0-linux-amd64/edge/ -kubeedge-v1.8.0-linux-amd64/edge/edgecore -kubeedge-v1.8.0-linux-amd64/cloud/ -kubeedge-v1.8.0-linux-amd64/cloud/csidriver/ -kubeedge-v1.8.0-linux-amd64/cloud/csidriver/csidriver -kubeedge-v1.8.0-linux-amd64/cloud/admission/ -kubeedge-v1.8.0-linux-amd64/cloud/admission/admission -kubeedge-v1.8.0-linux-amd64/cloud/cloudcore/ -kubeedge-v1.8.0-linux-amd64/cloud/cloudcore/cloudcore -kubeedge-v1.8.0-linux-amd64/version - -KubeEdge edgecore is running, For logs visit: journalctl -u edgecore.service -b +$ ./patch-edge.sh ``` -At this time, the deployment of EdgeCore is not complete because Docker is used in the default settings. You need to modify the configuration file to connect EdgeCore to iSulad. +#### Configuring Network for the Edge Container -#### Modifying EdgeCore Configurations +If you have not decided which CNI software to use, run the following command to configure network for the edge container: ```bash -# Enable systemd to manage EdgeCore. -# Copy edgecore.service to /usr/lib/systemd/system. -$ cp /etc/kubeedge/edgecore.service /usr/lib/systemd/system - -# Modify the EdgeCore configurations. -$ cd /etc/kubeedge/config -$ patch edgecore.yaml - < - -# You can see that Nginx has been successfully deployed on the edge node. +# Check whether Nginx is deployed on the edge node and running. +$ kubectl get pod -owide | grep nginx +nginx-deployment-84b99f4bf-jb6sz 1/1 Running 0 30s 10.244.1.2 edge.kubeedge ``` #### Testing the Function ```bash -# Test whether the function is running properly. -# Run the curl command on the edge node to access the IP address of Nginx, which is 10.244.2.4. -$ curl 10.244.2.4:80 +# Access the IP address of Nginx on the edge node. +$ curl 10.244.1.2:80 Welcome to nginx! @@ -525,868 +235,4 @@ Commercial support is available at ``` -The deployment of KubeEdge and iSulad is complete. - -## Deploying the KubeEdge Cluster Using Binary Files - -You can also deploy the KubeEdge cluster using binary files. Only two RPM packages are required: `cloudcore` (on the cloud node) and `edgecore` (on the edge node). -> The KubeEdge deployment using binary files is for testing only. Do not use this method in the production environment. - -### Deploying CloudCore on the Cloud Node - -> Log in to the cloud host. - -#### Installing the `cloudcore` RPM Package - -```bash -$ yum install kubeedge-cloudcore -``` - -#### Creating CRDs - -```bash -$ kubectl apply -f /etc/kubeedge/crds/devices/ -$ kubectl apply -f /etc/kubeedge/crds/reliablesyncs/ -$ kubectl apply -f /etc/kubeedge/crds/router/ -``` - -#### Preparing the Configuration File - -```bash -$ cloudcore --defaultconfig > /etc/kubeedge/config/cloudcore.yaml -``` - -Modify CloudCore configurations by referring to **Deploying CloudCore Using Keadm**. - -#### Running CloudCore - -```bash -$ pkill cloudcore -$ systemctl start cloudcore -``` - -### Deploying EdgeCore on the Edge Node - -> Log in to the edge host. - -#### Installing the `edgecore` RPM Package - -```bash -$ yum install kubeedge-edgecore -``` - -#### Preparing the Configuration File - -```bash -$ edgecore --defaultconfig > /etc/kubeedge/config/edgecore.yaml -``` - -Modify EdgeCore configurations by referring to **Deploying EdgeCore Using Keadm**. - - - -```bash -$ kubectl get secret -nkubeedge tokensecret -o=jsonpath='{.data.tokendata}' | base64 -d -1c4ff11289a14c59f2cbdbab726d1857262d5bda778ddf0de34dd59d125d3f69.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzE0ODM3MzN9.JY77nMVDHIKD9ipo03Y0mSbxief9qOvJ4yMNx1yZpp0 - -# Add the obtained token to the configuration file. -sed -i -e "s|token: .*|token: ${token}|g" /etc/kubeedge/config/edgecore.yaml - -# The value of the token variable is obtained in the previous step. -``` - -#### Running EdgeCore - -```bash -$ pkill edgecore -$ systemctl start edgecore -``` - -## Appendix - -### kube-flannel-cloud.yml - -```bash -# Application scenario: cloud node ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: psp.flannel.unprivileged - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default - seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default - apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default - apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default -spec: - privileged: false - volumes: - - configMap - - secret - - emptyDir - - hostPath - allowedHostPaths: - - pathPrefix: "/etc/cni/net.d" - - pathPrefix: "/etc/kube-flannel" - - pathPrefix: "/run/flannel" - readOnlyRootFilesystem: false - # Users and groups - runAsUser: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - fsGroup: - rule: RunAsAny - # Privilege Escalation - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - # Capabilities - allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] - defaultAddCapabilities: [] - requiredDropCapabilities: [] - # Host namespaces - hostPID: false - hostIPC: false - hostNetwork: true - hostPorts: - - min: 0 - max: 65535 - # SELinux - seLinux: - # SELinux is unused in CaaSP - rule: 'RunAsAny' ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -rules: -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: ['psp.flannel.unprivileged'] -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch -- apiGroups: - - "" - resources: - - nodes/status - verbs: - - patch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flannel -subjects: -- kind: ServiceAccount - name: flannel - namespace: kube-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: flannel - namespace: kube-system ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: kube-flannel-cfg - namespace: kube-system - labels: - tier: node - app: flannel -data: - cni-conf.json: | - { - "name": "cbr0", - "cniVersion": "0.3.1", - "plugins": [ - { - "type": "flannel", - "delegate": { - "hairpinMode": true, - "isDefaultGateway": true - } - }, - { - "type": "portmap", - "capabilities": { - "portMappings": true - } - } - ] - } - net-conf.json: | - { - "Network": "10.244.0.0/16", - "Backend": { - "Type": "vxlan" - } - } ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: kube-flannel-cloud-ds - namespace: kube-system - labels: - tier: node - app: flannel -spec: - selector: - matchLabels: - app: flannel - template: - metadata: - labels: - tier: node - app: flannel - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: node-role.kubernetes.io/agent - operator: DoesNotExist - hostNetwork: true - priorityClassName: system-node-critical - tolerations: - - operator: Exists - effect: NoSchedule - serviceAccountName: flannel - initContainers: - - name: install-cni - image: quay.io/coreos/flannel:v0.14.0 - command: - - cp - args: - - -f - - /etc/kube-flannel/cni-conf.json - - /etc/cni/net.d/10-flannel.conflist - volumeMounts: - - name: cni - mountPath: /etc/cni/net.d - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - containers: - - name: kube-flannel - image: quay.io/coreos/flannel:v0.14.0 - command: - - /opt/bin/flanneld - args: - - --ip-masq - - --kube-subnet-mgr - resources: - requests: - cpu: "100m" - memory: "50Mi" - limits: - cpu: "100m" - memory: "50Mi" - securityContext: - privileged: false - capabilities: - add: ["NET_ADMIN", "NET_RAW"] - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: run - mountPath: /run/flannel - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - volumes: - - name: run - hostPath: - path: /run/flannel - - name: cni - hostPath: - path: /etc/cni/net.d - - name: flannel-cfg - configMap: - name: kube-flannel-cfg - -``` - -### kube-flannel-edge.yml - -```bash -# Application scenario: edge node ---- -apiVersion: policy/v1beta1 -kind: PodSecurityPolicy -metadata: - name: psp.flannel.unprivileged - annotations: - seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default - seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default - apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default - apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default -spec: - privileged: false - volumes: - - configMap - - secret - - emptyDir - - hostPath - allowedHostPaths: - - pathPrefix: "/etc/cni/net.d" - - pathPrefix: "/etc/kube-flannel" - - pathPrefix: "/run/flannel" - readOnlyRootFilesystem: false - # Users and groups - runAsUser: - rule: RunAsAny - supplementalGroups: - rule: RunAsAny - fsGroup: - rule: RunAsAny - # Privilege Escalation - allowPrivilegeEscalation: false - defaultAllowPrivilegeEscalation: false - # Capabilities - allowedCapabilities: ['NET_ADMIN', 'NET_RAW'] - defaultAddCapabilities: [] - requiredDropCapabilities: [] - # Host namespaces - hostPID: false - hostIPC: false - hostNetwork: true - hostPorts: - - min: 0 - max: 65535 - # SELinux - seLinux: - # SELinux is unused in CaaSP - rule: 'RunAsAny' ---- -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -rules: -- apiGroups: ['extensions'] - resources: ['podsecuritypolicies'] - verbs: ['use'] - resourceNames: ['psp.flannel.unprivileged'] -- apiGroups: - - "" - resources: - - pods - verbs: - - get -- apiGroups: - - "" - resources: - - nodes - verbs: - - list - - watch -- apiGroups: - - "" - resources: - - nodes/status - verbs: - - patch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: flannel -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: flannel -subjects: -- kind: ServiceAccount - name: flannel - namespace: kube-system ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: flannel - namespace: kube-system ---- -kind: ConfigMap -apiVersion: v1 -metadata: - name: kube-flannel-cfg - namespace: kube-system - labels: - tier: node - app: flannel -data: - cni-conf.json: | - { - "name": "cbr0", - "cniVersion": "0.3.1", - "plugins": [ - { - "type": "flannel", - "delegate": { - "hairpinMode": true, - "isDefaultGateway": true - } - }, - { - "type": "portmap", - "capabilities": { - "portMappings": true - } - } - ] - } - net-conf.json: | - { - "Network": "10.244.0.0/16", - "Backend": { - "Type": "vxlan" - } - } ---- -apiVersion: apps/v1 -kind: DaemonSet -metadata: - name: kube-flannel-edge-ds - namespace: kube-system - labels: - tier: node - app: flannel -spec: - selector: - matchLabels: - app: flannel - template: - metadata: - labels: - tier: node - app: flannel - spec: - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: node-role.kubernetes.io/agent - operator: Exists - hostNetwork: true - priorityClassName: system-node-critical - tolerations: - - operator: Exists - effect: NoSchedule - serviceAccountName: flannel - initContainers: - - name: install-cni - image: quay.io/coreos/flannel:v0.14.0 - command: - - cp - args: - - -f - - /etc/kube-flannel/cni-conf.json - - /etc/cni/net.d/10-flannel.conflist - volumeMounts: - - name: cni - mountPath: /etc/cni/net.d - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - containers: - - name: kube-flannel - image: quay.io/coreos/flannel:v0.14.0 - command: - - /opt/bin/flanneld - args: - - --ip-masq - - --kube-subnet-mgr - - --kube-api-url=http://127.0.0.1:10550 - resources: - requests: - cpu: "100m" - memory: "50Mi" - limits: - cpu: "100m" - memory: "50Mi" - securityContext: - privileged: false - capabilities: - add: ["NET_ADMIN", "NET_RAW"] - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - volumeMounts: - - name: run - mountPath: /run/flannel - - name: flannel-cfg - mountPath: /etc/kube-flannel/ - volumes: - - name: run - hostPath: - path: /run/flannel - - name: cni - hostPath: - path: /etc/cni/net.d - - name: flannel-cfg - configMap: - name: kube-flannel-cfg - -``` - -### cloudcore.service - -```bash -# Application scenario: cloud node -# File path: /usr/lib/systemd/system/cloudcore.service -[Unit] -Description=cloudcore.service - -[Service] -Type=simple -ExecStart=/usr/local/bin/cloudcore -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -### cloudcore.yaml - -```bash -# Application scenario: cloud node -# File path: /etc/kubeedge/config/cloudcore.yaml -apiVersion: cloudcore.config.kubeedge.io/v1alpha1 -commonConfig: - tunnelPort: 10351 -kind: CloudCore -kubeAPIConfig: - burst: 200 - contentType: application/vnd.kubernetes.protobuf - kubeConfig: /root/.kube/config - master: "" - qps: 100 -modules: - cloudHub: - advertiseAddress: - - 9.63.252.224 - dnsNames: - - "" - edgeCertSigningDuration: 365 - enable: true - https: - address: 0.0.0.0 - enable: true - port: 10002 - keepaliveInterval: 30 - nodeLimit: 1000 - quic: - address: 0.0.0.0 - enable: false - maxIncomingStreams: 10000 - port: 10001 - tlsCAFile: /etc/kubeedge/ca/rootCA.crt - tlsCAKeyFile: /etc/kubeedge/ca/rootCA.key - tlsCertFile: /etc/kubeedge/certs/server.crt - tlsPrivateKeyFile: /etc/kubeedge/certs/server.key - tokenRefreshDuration: 12 - unixsocket: - address: unix:///var/lib/kubeedge/kubeedge.sock - enable: true - websocket: - address: 0.0.0.0 - enable: true - port: 10000 - writeTimeout: 30 - cloudStream: - enable: false - streamPort: 10003 - tlsStreamCAFile: /etc/kubeedge/ca/streamCA.crt - tlsStreamCertFile: /etc/kubeedge/certs/stream.crt - tlsStreamPrivateKeyFile: /etc/kubeedge/certs/stream.key - tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt - tlsTunnelCertFile: /etc/kubeedge/certs/server.crt - tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key - tunnelPort: 10004 - deviceController: - buffer: - deviceEvent: 1 - deviceModelEvent: 1 - updateDeviceStatus: 1024 - context: - receiveModule: devicecontroller - responseModule: cloudhub - sendModule: cloudhub - enable: true - load: - updateDeviceStatusWorkers: 1 - dynamicController: - enable: true - edgeController: - buffer: - configMapEvent: 1 - deletePod: 1024 - endpointsEvent: 1 - podEvent: 1 - queryConfigMap: 1024 - queryEndpoints: 1024 - queryNode: 1024 - queryPersistentVolume: 1024 - queryPersistentVolumeClaim: 1024 - querySecret: 1024 - queryService: 1024 - queryVolumeAttachment: 1024 - ruleEndpointsEvent: 1 - rulesEvent: 1 - secretEvent: 1 - serviceAccountToken: 1024 - serviceEvent: 1 - updateNode: 1024 - updateNodeStatus: 1024 - updatePodStatus: 1024 - context: - receiveModule: edgecontroller - responseModule: cloudhub - sendModule: cloudhub - sendRouterModule: router - enable: true - load: - ServiceAccountTokenWorkers: 4 - UpdateRuleStatusWorkers: 4 - deletePodWorkers: 4 - queryConfigMapWorkers: 4 - queryEndpointsWorkers: 4 - queryNodeWorkers: 4 - queryPersistentVolumeClaimWorkers: 4 - queryPersistentVolumeWorkers: 4 - querySecretWorkers: 4 - queryServiceWorkers: 4 - queryVolumeAttachmentWorkers: 4 - updateNodeStatusWorkers: 1 - updateNodeWorkers: 4 - updatePodStatusWorkers: 1 - nodeUpdateFrequency: 10 - router: - address: 0.0.0.0 - enable: false - port: 9443 - restTimeout: 60 - syncController: - enable: true - -``` - -### edgecore.service - -```bash -# Application scenario: edge node -# File path: /etc/systemd/system/edgecore.service -[Unit] -Description=edgecore.service - -[Service] -Type=simple -ExecStart=/usr/local/bin/edgecore -Restart=always -RestartSec=10 - -[Install] -WantedBy=multi-user.target -``` - -### edgecore.yaml - -```bash -# Application scenario: edge node -# File path: /etc/kubeedge/config/edgecore.yaml -apiVersion: edgecore.config.kubeedge.io/v1alpha1 -database: - aliasName: default - dataSource: /var/lib/kubeedge/edgecore.db - driverName: sqlite3 -kind: EdgeCore -modules: - dbTest: - enable: false - deviceTwin: - enable: true - edgeHub: - enable: true - heartbeat: 15 - httpServer: https://9.63.252.224:10002 - projectID: e632aba927ea4ac2b575ec1603d56f10 - quic: - enable: false - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.227:10001 - writeDeadline: 15 - rotateCertificates: true - tlsCaFile: /etc/kubeedge/ca/rootCA.crt - tlsCertFile: /etc/kubeedge/certs/server.crt - tlsPrivateKeyFile: /etc/kubeedge/certs/server.key - token: ""# Enter the token obtained from the cloud side. - websocket: - enable: true - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.224:10000 - writeDeadline: 15 - edgeMesh: - enable: false - lbStrategy: RoundRobin - listenInterface: docker0 - listenPort: 40001 - subNet: 9.251.0.0/16 - edgeStream: - enable: false - handshakeTimeout: 30 - readDeadline: 15 - server: 9.63.252.224:10004 - tlsTunnelCAFile: /etc/kubeedge/ca/rootCA.crt - tlsTunnelCertFile: /etc/kubeedge/certs/server.crt - tlsTunnelPrivateKeyFile: /etc/kubeedge/certs/server.key - writeDeadline: 15 - edged: - cgroupDriver: cgroupfs - cgroupRoot: "" - cgroupsPerQOS: true - clusterDNS: "" - clusterDomain: "" - cniBinDir: /opt/cni/bin - cniCacheDirs: /var/lib/cni/cache - cniConfDir: /etc/cni/net.d - concurrentConsumers: 5 - devicePluginEnabled: false - dockerAddress: unix:///var/run/docker.sock - edgedMemoryCapacity: 7852396000 - enable: true - enableMetrics: true - gpuPluginEnabled: false - hostnameOverride: edge.kubeedge - imageGCHighThreshold: 80 - imageGCLowThreshold: 40 - imagePullProgressDeadline: 60 - maximumDeadContainersPerPod: 1 - networkPluginMTU: 1500 - nodeIP: 9.63.252.227 - nodeStatusUpdateFrequency: 10 - podSandboxImage: kubeedge/pause:3.1 - registerNode: true - registerNodeNamespace: default - remoteImageEndpoint: unix:///var/run/isulad.sock - remoteRuntimeEndpoint: unix:///var/run/isulad.sock - runtimeRequestTimeout: 2 - runtimeType: remote - volumeStatsAggPeriod: 60000000000 - eventBus: - enable: true - eventBusTLS: - enable: false - tlsMqttCAFile: /etc/kubeedge/ca/rootCA.crt - tlsMqttCertFile: /etc/kubeedge/certs/server.crt - tlsMqttPrivateKeyFile: /etc/kubeedge/certs/server.key - mqttMode: 2 - mqttQOS: 0 - mqttRetain: false - mqttServerExternal: tcp://127.0.0.1:1883 - mqttServerInternal: tcp://127.0.0.1:1884 - mqttSessionQueueSize: 100 - metaManager: - contextSendGroup: hub - contextSendModule: websocket - enable: true - metaServer: - debug: false - enable: true - podStatusSyncInterval: 60 - remoteQueryTimeout: 60 - serviceBus: - enable: false - -``` - -### daemon.json - -```bash -# Application scenarios: cloud and edge nodes -# File path: /etc/isulad/daemon.json -{ - "group": "isula", - "default-runtime": "lcr", - "graph": "/var/lib/isulad", - "state": "/var/run/isulad", - "engine": "lcr", - "log-level": "ERROR", - "pidfile": "/var/run/isulad.pid", - "log-opts": { - "log-file-mode": "0600", - "log-path": "/var/lib/isulad", - "max-file": "1", - "max-size": "30KB" - }, - "log-driver": "stdout", - "container-log": { - "driver": "json-file" - }, - "hook-spec": "/etc/default/isulad/hooks/default.json", - "start-timeout": "2m", - "storage-driver": "overlay2", - "storage-opts": [ - "overlay2.override_kernel_check=true" - ], - "registry-mirrors": [ - "docker.io" - ], - "insecure-registries": [ - "k8s.gcr.io", - "quay.io", - "hub.oepkgs.net" - ], - "pod-sandbox-image": "k8s.gcr.io/pause:3.2", # Set this parameter to kubeedge/pause:3.1 for edge nodes. - "websocket-server-listening-port": 10351, - "native.umask": "secure", - "network-plugin": "cni", - "cni-bin-dir": "/opt/cni/bin", - "cni-conf-dir": "/etc/cni/net.d", - "image-layer-check": false, - "use-decrypted-key": true, - "insecure-skip-verify-enforce": false -} -``` +The deployment of KubeEdge is complete. diff --git a/docs/en/docs/SecHarden/account-passwords.md b/docs/en/docs/SecHarden/account-passwords.md index 66c373ad5..4ccfd0c14 100644 --- a/docs/en/docs/SecHarden/account-passwords.md +++ b/docs/en/docs/SecHarden/account-passwords.md @@ -1,13 +1,13 @@ # Account Passwords - [Account Passwords](#account-passwords) - - [Shielding System Accounts](#shielding-system-accounts) - - [Restricting Permissions on the su Command](#restricting-permissions-on-the-su-command) - - [Setting Password Complexity](#setting-password-complexity) - - [Setting the Password Validity Period](#setting-the-password-validity-period) - - [Setting Password Encryption Algorithms](#setting-password-encryption-algorithms) - - [Locking an Account After Three Login Failures](#locking-an-account-after-three-login-failures) - - [Hardening the su Command](#hardening-the-su-command) + - [Shielding System Accounts](#shielding-system-accounts) + - [Restricting Account Permissions on the su Command](#restricting-account-permissions-on-the-su-command) + - [Setting Password Complexity](#setting-password-complexity) + - [Setting the Password Validity Period](#setting-the-password-validity-period) + - [Setting Password Encryption Algorithms](#setting-password-encryption-algorithms) + - [Locking an Account After Three Login Failures](#locking-an-account-after-three-login-failures) + - [Hardening the su Command](#hardening-the-su-command) ## Shielding System Accounts @@ -26,11 +26,11 @@ usermod -L -s /sbin/nologin $systemaccount >![](./public_sys-resources/icon-note.gif) **NOTE:** >_$systemaccount_ indicates the system account. -## Restricting Permissions on the su Command +## Restricting Account Permissions on the su Command ### Description -The **su** command is used to switch user accounts. To improve system security, only the user **root** and users in the wheel group can use the **su** command. +The **su** command is used to switch user accounts. To improve system security, only the user **root** and users in the **wheel** group can use the **su** command. ### Implementation @@ -86,12 +86,12 @@ This section provides an example for configuring password complexity. - At least one space or one of the following special characters: \` \~ ! @ \# $ % ^ & \* \( \) - \_ = + \\ | \[ \{ \} \] ; : ' " , < . \> / ? -3. Cannot be the same as an account or the account in reverse order. +3. Cannot be the same as an account name or the account name in reverse order. 4. Cannot be the last five passwords used. **Implementation** -Add the following content to the first two lines of password in the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files: +Add the following content to the first two lines of the **password** configuration item in the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files: ``` password requisite pam_pwquality.so minlen=8 minclass=3 enforce_for_root try_first_pass local_users_only retry=3 dcredit=0 ucredit=0 lcredit=0 ocredit=0 @@ -271,16 +271,16 @@ password sufficient pam_unix.so sha512 shadow nullok try_first_pass use_au ### Description -To ensure user system security, you are advised to set the maximum number of incorrect password attempts \(three attempts are recommended\) and the automatic unlocking time \(300 seconds are recommended\) for a locked account. +To ensure user system security, you are advised to set the maximum number of failed login attempts \(three attempts are recommended\) and the automatic unlocking time \(300 seconds are recommended\) for a locked account. -If an account is locked, any input is invalid but does not cause the locking timer to recount. Records of the user's invalid inputs are cleared once unlocked. The preceding settings protect passwords from being forcibly cracked and improve system security. +If an account is locked, any input is invalid but does not reset the locking countdown timer. Records of the user's invalid inputs are cleared once unlocked. The preceding settings protect passwords from being forcibly cracked and improve system security. >![](./public_sys-resources/icon-note.gif) **NOTE:** ->By default, the maximum number of incorrect password attempts is 3 in openEuler. After the system is locked, the automatic unlock time is 60 seconds. +>By default, the maximum number of failed login attempts is 3 in openEuler. After an account is locked, the automatic unlock time is 60 seconds. ### Implementation -The password complexity is set by modifying the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files. The maximum number of incorrect password attempts is set to **3**, and the unlocking time after the system is locked is set to **300** seconds. The configuration is as follows: +The password complexity is set by modifying the **/etc/pam.d/password-auth** and **/etc/pam.d/system-auth** files. The maximum number of failed login attempts is set to **3**, and the unlocking time after an account is locked is set to **300** seconds. The configuration is as follows: ``` auth required pam_faillock.so preauth audit deny=3 even_deny_root unlock_time=300 @@ -304,12 +304,12 @@ auth sufficient pam_faillock.so authsucc audit deny=3 even_deny_root u

deny=3

-

A user account will be locked after three login attempts.

+

A user account will be locked after three failed login attempts.

unlock_time=300

-

A locked common user account is automatically unlocked in 300 seconds.

+

A locked common user account is automatically unlocked after 300 seconds.

even_deny_root

diff --git a/docs/en/docs/StratoVirt/VM_management.md b/docs/en/docs/StratoVirt/VM_management.md index c58a74382..7796925b1 100644 --- a/docs/en/docs/StratoVirt/VM_management.md +++ b/docs/en/docs/StratoVirt/VM_management.md @@ -165,25 +165,51 @@ QMP provides the quit command to exit a VM, that is, to exit the StratoVirt proc StratoVirt allows you to adjust the number of disks when a VM is running. That is, you can add or delete VM disks without interrupting services. -#### Hot Plugged-in Disks +**Note** + +* For a standard VM, the **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* For a standard VM, devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding Disks **Usage:** +Lightweight VM: + ``` {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} {"execute": "device_add", "arguments": {"id": "drive-0", "driver": "virtio-blk-mmio", "addr": "0x1"}} ``` +Standard VM: + +``` +{"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} +{"execute":"device_add", "arguments":{"id":"drive-0", "driver":"virtio-blk-pci", "drive": "drive-0", "addr":"0x0", "bus": "pcie.1"}} +``` + **Parameters:** -- The value of **node-name** in **blockdev-add** must be the same as the value of **id** in **device_add**. For example, both values are **drive-0** in the preceding example. -- **/path/to/block** is the image path of the hot plugged-in disks. It cannot be the path of the disk image that boots the rootfs. -- For **addr**, **0x0** is mapped to **vda** of the VM, **0x1** is mapped to **vdb**, and so on. To be compatible with the QMP protocol, **addr** can be replaced by **lun**, but **lun=0** is mapped to the **vdb** of the client. -- StratoVirt supports a maximum of six virtio-blk disks. Note this when hot plugging in disks. +- For a lightweight VM, the value of **node-name** in **blockdev-add** must be the same as that of **id** in **device_add**. For example, the values of **node-name** and **id** are both **drive-0** as shown above. + +- For a standard VM, the value of **drive** must be the same as that of **node-name** in **blockdev-add**. + +- **/path/to/block** is the image path of the hot added disks. It cannot be the path of the disk image that boots the rootfs. + +- For a lightweight VM, the value of **addr**, starting from **0x0**, is mapped to a virtio device on the VM. **0x0** is mapped to **vda**, **0x1** is mapped to **vdb**, and so on. To be compatible with the QMP protocol, **addr** can be replaced by **lun**, but **lun=0** is mapped to the **vdb** of the guest machine. For a standard VM, the value of **addr** must be **0x0**. + +- For a standard VM, **bus** indicates the name of the bus to mount the device. Currently, the device can be hot added only to the root port device. The value of **bus** must be the ID of the root port device. + +- For a lightweight VM, StratoVirt supports a maximum of six virtio-blk disks. Note this when hot adding disks. For a standard VM, the maximum number of hot added disks depends on the number of root port devices. **Example:** +Lightweight VM: + ``` <- {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} -> {"return": {}} @@ -191,29 +217,70 @@ StratoVirt allows you to adjust the number of disks when a VM is running. That i -> {"return": {}} ``` -#### Hot Plugged-out Disks +Standard VM: + +``` +<- {"execute": "blockdev-add", "arguments": {"node-name": "drive-0", "file": {"driver": "file", "filename": "/path/to/block"}, "cache": {"direct": true}, "read-only": false}} +-> {"return": {}} +<- {"execute":"device_add", "arguments":{"id":"drive-0", "driver":"virtio-blk-pci", "drive": "drive-0", "addr":"0x0", "bus": "pcie.1"}} +-> {"return": {}} +``` +#### Hot Removing Disks **Usage:** -**{"execute": "device_del", "arguments": {"id":"drive-0"}}** +Lightweight VM: + +``` +{"execute": "device_del", "arguments": {"id":"drive-0"}} +``` + +Standard VM: + +``` +{"execute": "device_del", "arguments": {"id":"drive-0"}} +{"execute": "blockdev-del", "arguments": {"node-name": "drive-0"}} +``` **Parameters:** -**id** indicates the ID of the hot plugged-out disk. +**id** indicates the ID of the disk to be hot removed. +- **node-name** indicates the backend name of the disk. **Example:** +Lightweight VM: + ``` <- {"execute": "device_del", "arguments": {"id": "drive-0"}} -> {"event":"DEVICE_DELETED","data":{"device":"drive-0","path":"drive-0"},"timestamp":{"seconds":1598513162,"microseconds":367129}} -> {"return": {}} ``` +Standard VM: + +``` +<- {"execute": "device_del", "arguments": {"id":"drive-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"drive-0","path":"drive-0"},"timestamp":{"seconds":1598513162,"microseconds":367129}} +<- {"execute": "blockdev-del", "arguments": {"node-name": "drive-0"}} +-> {"return": {}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. ### Hot-Pluggable NICs StratoVirt allows you to adjust the number of NICs when a VM is running. That is, you can add or delete VM NICs without interrupting services. -#### Hot Plugged-in NICs +**Note** + +* For a standard VM, the **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* For a standard VM, devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding NICs **Preparations (Requiring the root Permission)** @@ -239,21 +306,36 @@ StratoVirt allows you to adjust the number of NICs when a VM is running. That is **Usage:** +Lightweight VM: + ``` {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} {"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-mmio", "addr":"0x0"}} ``` +Standard VM: + +``` +{"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} +{"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-pci", "addr":"0x0", "netdev": "net-0", "bus": "pcie.1"}} +``` + **Parameters:** -- **id** in **netdev_add** must be the same as that in **device_add**. **ifname** is the name of the backend tap device. +- For a lightweight VM, **id** in **netdev_add** must be the same as that in **device_add**. **ifname** is the name of the backend tap device. + +- For a standard VM, the value of **netdev** must be the value of **id** in **netdev_add**. -- For **addr**, **0x0** is mapped to **eth0** of the VM, **0x1** is mapped to **eth1**, and so on. +- For a lightweight VM, the value of **addr**, starting from **0x0**, is mapped to an NIC on the VM. **0x0** is mapped to **eth0 **, **0x1** is mapped to **eth1**. For a standard VM, the value of **addr** must be **0x0**. -- StratoVirt supports a maximum of two virtio-net NICs. Therefore, pay attention to the specification restrictions when hot plugging in NICs. +- For a standard VM, **bus** indicates the name of the bus to mount the device. Currently, the device can be hot added only to the root port device. The value of **bus** must be the ID of the root port device. + +- For a lightweight VM, StratoVirt supports a maximum of two virtio-net NICs. Therefore, pay attention to the specification restrictions when hot adding in NICs. For a standard VM, the maximum number of hot added disks depends on the number of root port devices. **Example:** +Lightweight VM: + ``` <- {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} -> {"return": {}} @@ -263,24 +345,120 @@ StratoVirt allows you to adjust the number of NICs when a VM is running. That is **addr:0x0** corresponds to **eth0** in the VM. -#### Hot Plugged-out NICs +Standard VM: + +``` +<- {"execute":"netdev_add", "arguments":{"id":"net-0", "ifname":"tap0"}} +-> {"return": {}} +<- {"execute":"device_add", "arguments":{"id":"net-0", "driver":"virtio-net-pci", "addr":"0x0", "netdev": "net-0", "bus": "pcie.1"}} +-> {"return": {}} +``` + +#### Hot Removing NICs **Usage:** -**{"execute": "device_del", "arguments": {"id": "net-0"}}** +Lightweight VM: + +``` +{"execute": "device_del", "arguments": {"id": "net-0"}} +``` + +Standard VM: + +``` +{"execute": "device_del", "arguments": {"id":"net-0"}} +{"execute": "netdev_del", "arguments": {"id": "net-0"}} +``` + **Parameters:** **id**: NIC ID, for example, **net-0**. +- **id** in **netdev_del** indicates the backend name of the NIC. + **Example:** +Lightweight VM: + ``` <- {"execute": "device_del", "arguments": {"id": "net-0"}} -> {"event":"DEVICE_DELETED","data":{"device":"net-0","path":"net-0"},"timestamp":{"seconds":1598513339,"microseconds":97310}} -> {"return": {}} ``` +Standard VM: + +``` +<- {"execute": "device_del", "arguments": {"id":"net-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"net-0","path":"net-0"},"timestamp":{"seconds":1598513339,"microseconds":97310}} +<- {"execute": "netdev_del", "arguments": {"id": "net-0"}} +-> {"return": {}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. + +### Hot-swappable Pass-through Devices + +You can add or delete the passthrough devices of a StratoVirt standard VM when it is running. + +**Note** + +* The **CONFIG_HOTPLUG_PCI_PCIE=y** configuration must be enabled for the VM kernel. + +* Devices can be hot added to the root port. The root port device must be configured before the VM is started. + +* You are not advised to hot swap a device when the VM is being started, stopped, or under high internal pressure. Otherwise, the VM may become abnormal because the drivers on the VM cannot respond in a timely manner. + +#### Hot Adding Pass-through Devices + +**Usage:** + +``` +{"execute":"device_add", "arguments":{"id":"vfio-0", "driver":"vfio-pci", "bus": "pcie.1", "addr":"0x0", "host": "0000:1a:00.3"}} +``` + +**Parameters:** + +- **id** indicates the ID of the hot added device. + +- **bus** indicates the name of the bus to mount the device. + +- **addr** indicates the slot and function numbers to mount the device. Currently, **addr** must be set to **0x0**. + +- **host** indicates the domain number, bus number, slot number, and function number of the passthrough device on the host machine. + +**Example:** + +``` +<- {"execute":"device_add", "arguments":{"id":"vfio-0", "driver":"vfio-pci", "bus": "pcie.1", "addr":"0x0", "host": "0000:1a:00.3"}} +-> {"return": {}} +``` + +#### Hot Removing Pass-through Devices + +**Usage:** + +``` +{"execute": "device_del", "arguments": {"id": "vfio-0"}} +``` + +**Parameters:** + +- **id** indicates the ID of the device to be hot removed, which is specified when the device is hot added. + +**Example:** + +``` +<- {"execute": "device_del", "arguments": {"id": "vfio-0"}} +-> {"return": {}} +-> {"event":"DEVICE_DELETED","data":{"device":"vfio-0","path":"vfio-0"},"timestamp":{"seconds":1614310541,"microseconds":554250}} +``` + +A **DEVICE_DELETED** event indicates that the device is removed from StratoVirt. + ## Using Ballon Devices The balloon device is used to reclaim idle memory from a VM. It called by running the QMP command. diff --git a/docs/en/docs/StratoVirt/interconnect_isula.md b/docs/en/docs/StratoVirt/interconnect_isula.md index 02ee4d5cb..baa77be73 100644 --- a/docs/en/docs/StratoVirt/interconnect_isula.md +++ b/docs/en/docs/StratoVirt/interconnect_isula.md @@ -51,7 +51,7 @@ The following describes how to install and configure iSulad and kata-containers. ], ``` -3. Restart isulad. +3. Restart **isulad**. ```shell # systemctl daemon-reload @@ -76,15 +76,18 @@ The following describes how to install and configure iSulad and kata-containers. This section describes how to interconnect StratoVirt with kata-containers to access the iSula container ecosystem. -1. Modify the kata configuration file. Its default path is **/usr/share/defaults/kata-containers/configuration.toml**. You can also configure the file by referring to **configuration-stratovirt.toml** in the same directory. Set the Hypervisor type of the secure container to **stratovirt**, kernel to the absolute path of the kernel image of kata-containers, and initrd to the **initrd** image file of kata-containers. (If you use Yum to install kata-containers, the two image files are downloaded and stored in the **/var/lib/kata/** directory by default. You can also use other images during the configuration.) +#### Connecting to a Lightweight VM - The configurations are as follows: +1. Modify the kata configuration file. Its default path is **/usr/share/defaults/kata-containers/configuration.toml**. You can also configure the file by referring to **configuration-stratovirt.toml** in the same directory. Modify the **hypervisor** type of the secure container to **stratovirt**, **kernel** to the absolute path of the kernel image of kata-containers, and **initrd** to the **initrd** image file of kata-containers. (If you use Yum to install kata-containers, the two image files are downloaded and stored in the **/var/lib/kata/** directory by default. You can also use other images during the configuration.) + + The modified configurations are as follows: ```shell [hypervisor.stratovirt] path = "/usr/bin/stratovirt" kernel = "/var/lib/kata/kernel" initrd = "/var/lib/kata/kata-containers-initrd.img" + machine_type = "microvm" block_device_driver = "virtio-mmio" use_vsock = true enable_netmon = true @@ -95,7 +98,7 @@ This section describes how to interconnect StratoVirt with kata-containers to ac disable_vhost_net = true ``` -2. Run the `isula` command **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. +2. Run the `isula` command with **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. ```shell # isula run -tid --runtime "io.containerd.kata.v2" --net=none --name test busybox:latest sh @@ -103,7 +106,7 @@ This section describes how to interconnect StratoVirt with kata-containers to ac 3. Run the `isula ps` command to check whether the secure container **test** is running properly. Then run the following command to access the container: - ``` + ```shell # isula exec –ti test sh ``` @@ -141,3 +144,80 @@ This section describes how to interconnect StratoVirt with kata-containers to ac ``` You can now run container commands in the **test** container. + +#### Connecting to a Standard VM + +To use a StratoVirt standard VM as the sandbox of a secure container, you need to modify some other configurations. + +1. The configurations are as follows: + + ```shell + [hypervisor.stratovirt] + path = "/usr/bin/stratovirt" + kernel = "/var/lib/kata/kernel" + initrd = "/var/lib/kata/kata-containers-initrd.img" + # x86_64 architecture + machine_type = "q35" + # AArch64 architecture + machine_type = "virt" + block_device_driver = "virtio-blk" + pcie_root_port = 2 + use_vsock = true + enable_netmon = true + internetworking_model = "tcfilter" + sandbox_cgroup_with_emulator = false + disable_new_netns = false + disable_block_device_use = false + disable_vhost_net = true + ``` + + In the configurations above, modify the VM type according to the architecture of the host machine. Change the value of **block_device_driver** to **virtio-blk**. StratoVirt supports only devices hot-plugged to the root port. Set a proper value of **pcie_root_port** based on the number of devices to be hot-plugged. + +2. Install the firmware required for starting a standard VM. + + x86_64 architecture: + + ```shell + # yum install -y edk2-ovmf + ``` + + AArch64 architecture: + + ```shell + # yum install -y edk2-aarch64 + ``` + +3. Build and replace the binary file of kata-containers 2.x. + + Currently, a StratoVirt standard VMs can only be used as the sandbox of a kata-containers 2.x container (corresponding to the openEuler-21.09 branch in the kata-containers repository). You need to download and compile the kata-containers source code and replace the **containerd-shim-kata-v2** binary file in the **/usr/bin** directory. + + ```shell + # mkdir -p /root/go/src/github.com/ + # cd /root/go/src/github.com/ + # git clone https://gitee.com/src-openeuler/kata-containers.git + # cd kata-containers + # git checkout openEuler-21.09 + # ./apply-patches + # cd src/runtime + # make + ``` + + Back up the kata binary file in the **/usr/bin/** directory and replace it with the compiled binary file **containerd-shim-kata-v2**. + + ```shell + # cp /usr/bin/containerd-shim-kata-v2 /usr/bin/containerd-shim-kata-v2.bk + # cp containerd-shim-kata-v2 /usr/bin/containerd-shim-kata-v2 + ``` + +4. Run the `isula` command with **root** permissions to start the BusyBox secure container and interconnect StratoVirt with it. + + ```shell + # isula run -tid --runtime "io.containerd.kata.v2" --net=none --name test busybox:latest sh + ``` + +5. Run the `isula ps` command to check whether the secure container **test** is running properly. Then run the following command to access the container: + + ```shell + # isula exec -ti test sh + ``` + diff --git a/docs/en/docs/Virtualization/LibcarePlus.md b/docs/en/docs/Virtualization/LibcarePlus.md new file mode 100644 index 000000000..d554c3fc5 --- /dev/null +++ b/docs/en/docs/Virtualization/LibcarePlus.md @@ -0,0 +1,410 @@ +# LibcarePlus + + + +- [LibcarePlus](#libcareplus) + - [Overview](#overview) + - [Hardware and Software Requirements](#hardware-and-software-requirements) + - [Precautions and Constraints](#precautions-and-constraints) + - [Installing LibcarePlus](#installing-libcareplus) + - [Software Installation Dependencies](#software-installation-dependencies) + - [Installing LibcarePlus](#installing-libcareplus-1) + - [Creating LibcarePlus Hot Patches](#creating-libcareplus-hot-patches) + - [Introduction](#introduction) + - [Manual Creation](#manual-creation) + - [Creation Through a Script](#creation-through-a-script) + - [Applying the LibcarePlus Hot Patch](#applying-the-libcareplus-hot-patch) + - [Preparation](#preparation) + - [Loading the Hot Patch](#loading-the-hot-patch) + - [Querying a Hot Patch](#querying-a-hot-patch) + - [Uninstalling the Hot Patch](#uninstalling-the-hot-patch) + + + +## Overview + +LibcarePlus is a hot patch framework for user-mode processes. It can perform hot patch operations on target processes running on the Linux system without restarting the processes. Hot patches can be used to fix CVEs and urgent bugs that do not interrupt application services. + +## Hardware and Software Requirements + +The following software and hardware requirements must be met to use LibcarePlus on openEuler: + +- Currently, the x86 and ARM64 architectures are supported. + +- LibcarePlus can run on any Linux distribution that supports **libunwind**, **elfutils**, and **binutils**. +- LibcarePlus uses the **ptrace()** system call, which requires the kernel configuration option enabled for the corresponding Linux distribution. +- LibcarePlus needs the symbol table of the original executable file when creating a hot patch. Do not strip the symbol table too early. +- On the Linux OS where SELinux is enabled, manually adapt the SELinux policies. + +## Precautions and Constraints + +When using LibcarePlus, comply with the following hot patch specifications and constraints: + +- Only the code written in the C language is supported. The assembly language is not supported. +- Only user-mode programs are supported. Dynamic library patches are not supported. +- The code file name must comply with the C language identifier naming specifications. That is, the code file name consists of letters (A-Z and a-z), digits (0-9), and underscores (_) but the first character cannot be a digit. Special characters such as hyphens (-) and dollar signs ($) are not allowed. +- Incremental patches are supported. Multiple patches can be installed on a process. However, you need to design the patch installation and uninstallation management. Generally, the installation and uninstallation comply with the first-in, last-out (FILO) rule. +- Automatic patch loading is not natively supported. You can design an automatic patch loading method for a specific process. +- Patch query is supported. +- The static function patch is restricted by the symbol table that can find the function in the system. +- Hot patches are process-specific. That is, a hot patch of a dynamic library can be applied only to process that invoke the dynamic library. +- The number of patches that can be applied to a process is limited by the range of the jump instruction and the size of the hole in the virtual memory address space. Generally, up to 512 patches can be applied to a process. +- Thread local storage (TLS) variables of the initial executable (IE) model can be modified. +- Symbols defined in a patch cannot be used in subsequent patches. +- Hot patches are not supported in the following scenarios: + - Infinite loop function, non-exit function, inline function, initialization function, and non-maskable interrupt (NMI) function + - Replacing global variables + - Functions less than 5 bytes + - Modifying the header file + - Adding or deleting the input and output parameters of the target function + - Changing (adding, deleting, or modifying) data structure members + - Modifying the C files that contain GCC macros such as __LINE__ and __FILE__ + - Modifying the Intel vector assembly instruction + +## Installing LibcarePlus + +### Software Installation Dependencies + +The LibcarePlus running depends on **libunwind**, **elfutils**, and **binutils**. On the openEuler system configured with the Yum repo, you can run the following commands to install the software on which LibcarePlus depends: + +``` shell +# yum install -y binutils elfutils elfutils-libelf-devel libunwind-devel +``` + +#### Installing LibcarePlus + +```shell +# yum install libcareplus -y +``` + +Check whether LibcarePlus is installed. + +``` shell +# libcare-ctl -h +usage: libcare-ctl [options] [args] + +Options: + -v - verbose mode + -h - this message + +Commands: + patch - apply patch to a user-space process + unpatch- unapply patch from a user-space process + info - show info on applied patches +``` + +## Creating LibcarePlus Hot Patches + +### Introduction + +LibcarePlus hot patch creation methods: + +- Manual creation +- Creation through a script + +The process of manually creating a hot patch is complex. For a project with a large amount of code, for example, QEMU, it is extremely difficult to manually create a hot patch. You are advised to use the script provided by LibcarePlus to generate a hot patch file with one click. + +#### Manual Creation + +The following takes the original file **foo.c** and the patch file **bar.c** as examples to describe how to manually create a hot patch. + +1. Prepare the original file and patch file written in the C language. For example, **foo.c** and **bar.c**. + +
+ Expand foo.c +

+ + ``` c + // foo.c + #include + #include + + void print_hello(void) + { + printf("Hello world!\n"); + } + + int main(void) + { + while (1) { + print_hello(); + sleep(1); + } + } + ``` + +

+
+ +
+ Expand bar.c +

+ + ``` c + // bar.c + #include + #include + + void print_hello(void) + { + printf("Hello world %s!\n", "being patched"); + } + + int main(void) + { + while (1) { + print_hello(); + sleep(1); + } + } + ``` + +

+
+ +2. Build the original file and patch file to obtain the assembly files **foo.s** and **bar.s**. + + ``` shell + # gcc -S foo.c + # gcc -S bar.c + # ls + bar.c bar.s foo.c foo.s + ``` + +3. Run `kpatch_gensrc` to compare **foo.s** and **bar.s** and generate the **foobar.s** file that contains the assembly content of the original file and the differences. + + ``` shell + # sed -i 's/bar.c/foo.c/' bar.s + # kpatch_gensrc --os=rhel6 -i foo.s -i bar.s -o foobar.s --force-global + ``` + + By default, `kpatch_gensrc` compares the original files in the same C language. Therefore, before the comparison, you need to run the `sed` command to change the file name **bar.c** in the patch assembly file **bar.s** to the original file name **foo.c**. Call `kpatch_gensrc` to specify the input files as **foo.s** and **bar.s** and the output file as **foobar.s**. + +4. Build the assembly file **foo.s** in the original file and the generated assembly file **foobar.s** to obtain the executable files **foo** and **foobar**. + + ``` shell + # gcc -o foo foo.s + # gcc -o foobar foobar.s -Wl,-q + ``` + + The **-Wl, -q** linker options reserve the relocation sections in **foobar**. + +5. Use `kpatch_strip` to remove the duplicate content from the executables **foo** and **foobar** and reserve the content required for creating hot patches. + + ``` shell + # kpatch_strip --strip foobar foobar.stripped + # kpatch_strip --rel-fixup foo foobar.stripped + # strip --strip-unneeded foobar.stripped + # kpatch_strip --undo-link foo foobar.stripped + ``` + + The options in the preceding command are described as follows: + + - **--strip** removes useless sections for patch creation from **foobar**. + - **--rel-fixup** repairs the address of the variables and functions accessed in the patch. + - **strip --strip-unneeded** removes the useless symbol information for hot patch relocation. + - **--undo-link** changes the symbol address in a patch from absolute to relative. + +6. Create a hot patch file. + + After the preceding operations, the contents required for creating the hot patch are obtained. Run the `kpatch_make` command to input parameters Build ID of the original executable file and **foobar.stripped** (output file of `kpatch_strip`) to `kpatch_make` to generate a hot patch file. + + ``` shell + # str=$(readelf -n foo | grep 'Build ID') + # substr=${str##* } + # kpatch_make -b $substr -i 0001 foobar.stripped -o foo.kpatch + # ls + bar.c bar.s foo foobar foobar.s foobar.stripped foo.c foo.kpatch foo.s + ``` + + The final hot patch file **foo.kpatch** whose patch ID is **0001** is obtained. + +#### Creation Through a Script + +This section describes how to use LibcarePlus built-in **libcare-patch-make** script to create a hot patch file. The original file **foo.c** and patch file **bar.c** are used as an example. + +1. Run the `diff` command to generate the comparison file of **foo.c** and **bar.c**. + + ``` shell + # diff -up foo.c bar.c > foo.patch + ``` + + The content of the **foo.patch** file is as follows: + +
+ Expand foo.patch +

+ + + ``` diff + --- foo.c 2020-12-09 15:39:51.159632075 +0800 + +++ bar.c 2020-12-09 15:40:03.818632220 +0800 + @@ -1,10 +1,10 @@ + -// foo.c + +// bar.c + #include + #include + + void print_hello(void) + { + - printf("Hello world!\n"); + + printf("Hello world %s!\n", "being patched"); + } + + int main(void) + ``` + +

+
+ + +2. Write the **makefile** for building **foo.c** as follows: + +
+ Expand makefile +

+ + ``` makefile + all: foo + + foo: foo.c + $(CC) -o $@ $< + + clean: + rm -f foo + + install: foo + mkdir $$DESTDIR || : + cp foo $$DESTDIR + ``` + +

+
+ + +3. After the **makefile** is done, directly call `libcare-patch-make`. If `libcare-patch-make` asks you which file to install the patch, enter the original file name, as shown in the following: + + ``` shell + # libcare-patch-make --clean -i 0001 foo.patch + rm -f foo + BUILDING ORIGINAL CODE + /usr/local/bin/libcare-cc -o foo foo.c + INSTALLING ORIGINAL OBJECTS INTO /libcareplus/test/lpmake + mkdir $DESTDIR || : + cp foo $DESTDIR + applying foo.patch... + can't find file to patch at input line 3 + Perhaps you used the wrong -p or --strip option? + The text leading up to this was: + -------------------------- + |--- foo.c 2020-12-10 09:43:04.445375845 +0800 + |+++ bar.c 2020-12-10 09:48:36.778379648 +0800 + -------------------------- + File to patch: foo.c + patching file foo.c + BUILDING PATCHED CODE + /usr/local/bin/libcare-cc -o foo foo.c + INSTALLING PATCHED OBJECTS INTO /libcareplus/test/.lpmaketmp/patched + mkdir $DESTDIR || : + cp foo $DESTDIR + MAKING PATCHES + Fixing up relocation printf@@GLIBC_2.2.5+fffffffffffffffc + Fixing up relocation print_hello+0 + patch for /libcareplus/test/lpmake/foo is in /libcareplus/test/patchroot/700297b7bc56a11e1d5a6fb564c2a5bc5b282082.kpatch + ``` + + After the command is executed, the output indicates that the hot patch file is in the **patchroot** directory of the current directory, and the executable file is in the **lpmake** directory. By default, the Build ID is used to name a hot patch file generated by a script. + + + +## Applying the LibcarePlus Hot Patch + +This following uses the original file **foo.c** and patch file **bar.c** as an example to describe how to use the LibcarePlus hot patch. + +### Preparation + +Before using the LibcarePlus hot patch, prepare the original executable file **foo** and hot patch file **foo.kpatch**. + +### Loading the Hot Patch + +The procedure for applying the LibcarePlus hot patch is as follows: + +1. In the first shell window, run the executable file to be patched: + + ``` shell + # ./lpmake/foo + Hello world! + Hello world! + Hello world! + ``` + +2. In the second shell window, run the `libcare-ctl` command to apply the hot patch: + + ``` shell + # libcare-ctl -v patch -p $(pidof foo) ./foo.kpatch + ``` + + If the hot patch is applied successfully, the following information is displayed in the second shell window: + + ``` shell + 1 patch hunk(s) have been successfully applied to PID '10999' + ``` + + The following information is displayed for the target process running in the first shell window: + + ``` shell + Hello world! + Hello world! + Hello world being patched! + Hello world being patched! + ``` + + +### Querying a Hot Patch + +The procedure for querying a LibcarePlus hot patch is as follows: + +1. Run the following command in the second shell window: + + ```shell + # libcare-ctl info -p $(pidof foo) + + ``` + + If a hot patch is installed, the following information is displayed in the second shell window: + + ```shell + Pid: 551763 + Target: foo + Build id: df05a25bdadd282812d3ee5f0a460e69038575de + Applied patch number: 1 + Patch id: 0001 + ``` + + + + +### Uninstalling the Hot Patch + +The procedure for uninstalling the LibcarePlus hot patch is as follows: + +1. Run the following command in the second shell window: + + ``` shell + # libcare-ctl unpatch -p $(pidof foo) + ``` + + If the hot patch is uninstalled successfully, the following information is displayed in the second shell window: + + ``` shell + 1 patch hunk(s) were successfully cancelled from PID '10999' + ``` + +2. The following information is displayed for the target process running in the first shell window: + + ``` shell + Hello world being patched! + Hello world being patched! + Hello world! + Hello world! + ``` diff --git a/docs/en/docs/Virtualization/tool-guide.md b/docs/en/docs/Virtualization/tool-guide.md index 06bbb1650..565ebecf3 100644 --- a/docs/en/docs/Virtualization/tool-guide.md +++ b/docs/en/docs/Virtualization/tool-guide.md @@ -1,196 +1 @@ -# Tool Guide - -- [vmtop](#vmtop) - -## vmtop - -### Overview - -vmtop is a user-mode tool running on the host machine. You can use the vmtop tool to dynamically view the usage of VM resources in real time, such as CPU usage, memory usage, and the number of vCPU traps. Therefore, the vmtop tool can be used to locate virtualization problems and optimize performance. - -#### Multi-Architecture Support - -Currently, the vmtop supports the AArch64 and x86_64 processor architectures. - -#### Display Item Description - -The vmtop display items vary according to the processor architecture. This document describes the meaning of each display item and whether it is displayed in the corresponding architecture. -Note: The following sampling difference refers to the difference between two times of data obtained in a specified interval. - -##### **Display Items of the AArch64 and x86_64 Architectures** - -- VM/task-name: VM/Process name -- DID: VM ID -- PID: PID of the qemu process of the VM -- %CPU: CPU usage of a process -- EXTsum: Total number of KVM exits (sampling difference) -- S: Process status -- P: ID of the physical CPU occupied by a process -- %ST: Ratio of the preemption time to the CPU running time -- %GUE: Ratio of the VM internal occupation time to the CPU running time -- %HYP: Virtualization overhead ratio - -##### Display Items Only for the Aarch64 Architecture - -- EXThvc: Number of hvc-exits (sampling difference) -- EXTwfe: Number of wfe-exits (sampling difference) -- EXTwfi: Number of wfi-exits (sampling difference) -- EXTmmioU: Number of mmioU-exits (sampling difference) -- EXTmmioK: Number of mmioK-exits (sampling difference) -- EXTfp: Number of fp-exits (sampling difference) -- EXTirq: Number of irq-exits (sampling difference) -- EXTsys64: Number of sys64 exits (sampling difference) -- EXTmabt: Number of mem abort exits (sampling difference) - -##### Display Items Only for the x86_64 Architecture - -- PFfix: Number of page faults (sampling difference) -- PFgu: Number of times that page faults are injected to the guest OS (sampling difference) -- INvlpg: Number of times that a TLB item is flushed (one of the TLB items, which is not fixed) -- EXTio: Number of io VM-exit times (sampling difference) -- EXTmmio: Number of mmio VM-exit times (sampling difference) -- EXThalt: Number of halt VM-exit times (sampling difference) -- EXTsig: Number of VM-exits caused by signal processing (sampling difference) -- EXTirq: Number of VM-exits caused by interrupts (sampling difference) -- EXTnmiW: Number of VM-exit times caused by non-maskable interrupts (sampling difference) -- EXTirqW: Interruptwindow mechanism. When the interrupt function is enabled, exit is used to inject interrupts (sampling difference) -- IrqIn: Number of times that IRQ interrupts are injected (sampling difference) -- NmiIn: Number of times that NMI interrupts are injected (sampling difference) -- TLBfl: Number of times that the entire TLB is flushed (sampling difference) -- HostReL: Number of times that the host status is overloaded (sampling difference) -- Hyperv: Number of times that the guest OS is simulated to call hypercal in virtualization-assistant mode (sampling difference) -- EXTcr: Number of times that the access to the CR register exits (sampling difference) -- EXTrmsr: Number of times that the read MSR exits (sampling difference) -- EXTwmsr: Number of times that the write MSR exits (sampling difference) -- EXTapic: Number of APIC write times (sampling difference) -- EXTeptv: Ept page fault exit times (sampling difference) -- EXTeptm: Number of Ept error exits (sampling difference) -- EXTpau: Number of times that the VCPU pauses and exits (sampling difference) - -### Usage - -vmtop is a command line tool. You can directly run the vmtop in command line mode. -In addition, the vmtop tool provides different options for querying different information. - -#### Syntax - -```sh -vmtop [option] -``` - -#### Option Description - -- -d: sets the refresh interval, in seconds. -- -H: displays the VM thread information. -- -n: sets the number of refresh times and exits after the refresh is complete. -- -b: displays Batch mode, which can be used to redirect to a file. -- -h: displays help information. -- -v: displays versions. -- -p: monitors the VM with a specified ID. - -#### Keyboard Shortcut - -Shortcut key used when the vmtop is running. - -- H: displays or stops the VM thread information. The information is displayed by default. -- up/down: moves the VM list upwards or downwards. -- left/right: moves the cursor leftwards or rightwards to display the columns that are hidden due to the screen width. -- f: enters the editing mode of a monitoring item and selects the monitoring item to be enabled. -- q: exits the vmtop process. - -### Example - -Run the vmtop command on the host. - -```sh -vmtop -``` - -The command output is as follows: - -```sh -vmtop - 2020-09-14 09:54:48 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP - 2 example 4054916 13.0 0 0 1206 10 0 144 62 174 0 1452 S 106 0.0 99.7 16.0 -``` - -As shown in the output, there is only one VM named "example" on the host. The ID is 2. The CPU usage is 13.0%. The total number of traps within one second is 1452. The physical CPU occupied by the VM process is CPU 106. The ratio of the VM internal occupation time to the CPU running time is 99.7%. - -1. Display VM thread information. -Press H to display the thread information. - -```sh -vmtop - 2020-09-14 10:11:27 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP - 2 example 4054916 13.0 0 0 1191 17 4 120 76 147 0 1435 S 119 0.0 123.7 4.0 - |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 - |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 - |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 - |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 0.0 0.0 0.0 - |_ CPU 0/KVM 4054933 3.0 0 0 280 6 4 28 19 41 0 350 S 105 0.0 27.9 0.0 - |_ CPU 1/KVM 4054934 3.0 0 0 260 0 0 16 12 36 0 308 S 31 0.0 20.0 0.0 - |_ CPU 2/KVM 4054935 3.0 0 0 341 0 0 44 20 26 0 387 R 108 0.0 27.9 4.0 - |_ CPU 3/KVM 4054936 5.0 0 0 310 11 0 32 25 44 0 390 S 103 0.0 47.9 0.0 - |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 0.0 0.0 0.0 - |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 0.0 0.0 0.0 - |_ worker 4143738 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 -``` - -The example VM has 11 threads, including the vCPU thread, vnc_worker, and IO mon_iotreads. Each thread also displays detailed CPU usage and trap information. - -2. Select the monitoring item. -Enter f to edit the monitoring item. - -```sh -field filter - select which field to be showed -Use up/down to navigate, use space to set whether chosen filed to be showed -'q' to quit to normal display - - * DID - * VM/task-name - * PID - * %CPU - * EXThvc - * EXTwfe - * EXTwfi - * EXTmmioU - * EXTmmioK - * EXTfp - * EXTirq - * EXTsys64 - * EXTmabt - * EXTsum - * S - * P - * %ST - * %GUE - * %HYP -``` - -All monitoring items are displayed by default. You can press the up or down key to select a monitoring item, press the space key to set whether to display or hide the monitoring item, and press the q key to exit. -After %ST, %GUE, and %HYP are hidden, the following information is displayed: - -```sh -vmtop - 2020-09-14 10:23:25 - 1.0 -Domains: 1 running - - DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P - 2 example 4054916 12.0 0 0 1213 14 1 144 68 168 0 1464 S 125 - |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 125 - |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 - |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 - |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 - |_ CPU 0/KVM 4054933 2.0 0 0 303 6 0 29 10 35 0 354 S 98 - |_ CPU 1/KVM 4054934 4.0 0 0 279 0 0 39 17 49 0 345 S 1 - |_ CPU 2/KVM 4054935 3.0 0 0 283 0 0 33 20 40 0 343 S 122 - |_ CPU 3/KVM 4054936 3.0 0 0 348 8 1 43 21 44 0 422 S 110 - |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 - |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 - |_ worker 1794 0.0 0 0 0 0 0 0 0 0 0 0 S 126 -``` - -%ST, %GUE, and %HYP will not be displayed on the screen. +To help users better use virtualization, openEuler provides a set of tools, including vmtop and LibcarePlus. This section describes how to install and use these tools. \ No newline at end of file diff --git a/docs/en/docs/Virtualization/vmtop.md b/docs/en/docs/Virtualization/vmtop.md new file mode 100644 index 000000000..346cc01c2 --- /dev/null +++ b/docs/en/docs/Virtualization/vmtop.md @@ -0,0 +1,196 @@ +# Tool Guide + +- [vmtop](#vmtop) + +## vmtop + +### Overview + +vmtop is a user-mode tool running on the host machine. You can use the vmtop tool to dynamically view the usage of VM resources in real time, such as CPU usage, memory usage, and the number of vCPU traps. Therefore, the vmtop tool can be used to locate virtualization problems and optimize performance. + +#### Multi-Architecture Support + +Currently, the vmtop supports the AArch64 and x86_64 processor architectures. + +#### Display Item Description + +The vmtop display items vary according to the processor architecture. This document describes the meaning of each display item and whether it is displayed in the corresponding architecture. +Note: The following sampling difference refers to the difference between two times of data obtained in a specified interval. + +##### **Display Items of the AArch64 and x86_64 Architectures** + +- VM/task-name: VM/Process name +- DID: VM ID +- PID: PID of the qemu process of the VM +- %CPU: CPU usage of a process +- EXTsum: Total number of KVM exits (sampling difference) +- S: Process status +- P: ID of the physical CPU occupied by a process +- %ST: Ratio of the preemption time to the CPU running time +- %GUE: Ratio of the VM internal occupation time to the CPU running time +- %HYP: Virtualization overhead ratio + +##### Display Items Only for the Aarch64 Architecture + +- EXThvc: Number of hvc-exits (sampling difference) +- EXTwfe: Number of wfe-exits (sampling difference) +- EXTwfi: Number of wfi-exits (sampling difference) +- EXTmmioU: Number of mmioU-exits (sampling difference) +- EXTmmioK: Number of mmioK-exits (sampling difference) +- EXTfp: Number of fp-exits (sampling difference) +- EXTirq: Number of irq-exits (sampling difference) +- EXTsys64: Number of sys64 exits (sampling difference) +- EXTmabt: Number of mem abort exits (sampling difference) + +##### Display Items Only for the x86_64 Architecture + +- PFfix: Number of page faults (sampling difference) +- PFgu: Number of times that page faults are injected to the guest OS (sampling difference) +- INvlpg: Number of times that a TLB item is flushed (one of the TLB items, which is not fixed) +- EXTio: Number of io VM-exit times (sampling difference) +- EXTmmio: Number of mmio VM-exit times (sampling difference) +- EXThalt: Number of halt VM-exit times (sampling difference) +- EXTsig: Number of VM-exits caused by signal processing (sampling difference) +- EXTirq: Number of VM-exits caused by interrupts (sampling difference) +- EXTnmiW: Number of VM-exit times caused by non-maskable interrupts (sampling difference) +- EXTirqW: Interruptwindow mechanism. When the interrupt function is enabled, exit is used to inject interrupts (sampling difference) +- IrqIn: Number of times that IRQ interrupts are injected (sampling difference) +- NmiIn: Number of times that NMI interrupts are injected (sampling difference) +- TLBfl: Number of times that the entire TLB is flushed (sampling difference) +- HostReL: Number of times that the host status is overloaded (sampling difference) +- Hyperv: Number of times that the guest OS is simulated to call hypercall in virtualization-assistant mode (sampling difference) +- EXTcr: Number of times that the access to the CR register exits (sampling difference) +- EXTrmsr: Number of times that the read MSR exits (sampling difference) +- EXTwmsr: Number of times that the write MSR exits (sampling difference) +- EXTapic: Number of APIC write times (sampling difference) +- EXTeptv: Ept page fault exit times (sampling difference) +- EXTeptm: Number of Ept error exits (sampling difference) +- EXTpau: Number of times that the VCPU pauses and exits (sampling difference) + +### Usage + +vmtop is a command line tool. You can directly run the vmtop in command line mode. +In addition, the vmtop tool provides different options for querying different information. + +#### Syntax + +```sh +vmtop [option] +``` + +#### Option Description + +- -d: sets the refresh interval, in seconds. +- -H: displays the VM thread information. +- -n: sets the number of refresh times and exits after the refresh is complete. +- -b: displays Batch mode, which can be used to redirect to a file. +- -h: displays help information. +- -v: displays versions. +- -p: monitors the VM with a specified ID. + +#### Keyboard Shortcut + +Shortcut key used when the vmtop is running. + +- H: displays or stops the VM thread information. The information is displayed by default. +- up/down: moves the VM list upwards or downwards. +- left/right: moves the cursor leftwards or rightwards to display the columns that are hidden due to the screen width. +- f: enters the editing mode of a monitoring item and selects the monitoring item to be enabled. +- q: exits the vmtop process. + +### Example + +Run the vmtop command on the host. + +```sh +vmtop +``` + +The command output is as follows: + +```sh +vmtop - 2020-09-14 09:54:48 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP + 2 example 4054916 13.0 0 0 1206 10 0 144 62 174 0 1452 S 106 0.0 99.7 16.0 +``` + +As shown in the output, there is only one VM named "example" on the host. The ID is 2. The CPU usage is 13.0%. The total number of traps within one second is 1452. The physical CPU occupied by the VM process is CPU 106. The ratio of the VM internal occupation time to the CPU running time is 99.7%. + +1. Display VM thread information. +Press H to display the thread information. + +```sh +vmtop - 2020-09-14 10:11:27 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P %ST %GUE %HYP + 2 example 4054916 13.0 0 0 1191 17 4 120 76 147 0 1435 S 119 0.0 123.7 4.0 + |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 + |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 0.0 0.0 0.0 + |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 + |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 0.0 0.0 0.0 + |_ CPU 0/KVM 4054933 3.0 0 0 280 6 4 28 19 41 0 350 S 105 0.0 27.9 0.0 + |_ CPU 1/KVM 4054934 3.0 0 0 260 0 0 16 12 36 0 308 S 31 0.0 20.0 0.0 + |_ CPU 2/KVM 4054935 3.0 0 0 341 0 0 44 20 26 0 387 R 108 0.0 27.9 4.0 + |_ CPU 3/KVM 4054936 5.0 0 0 310 11 0 32 25 44 0 390 S 103 0.0 47.9 0.0 + |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 0.0 0.0 0.0 + |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 0.0 0.0 0.0 + |_ worker 4143738 0.0 0 0 0 0 0 0 0 0 0 0 S 120 0.0 0.0 0.0 +``` + +The example VM has 11 threads, including the vCPU thread, vnc_worker, and IO mon_iotreads. Each thread also displays detailed CPU usage and trap information. + +2. Select the monitoring item. +Enter f to edit the monitoring item. + +```sh +field filter - select which field to be showed +Use up/down to navigate, use space to set whether chosen filed to be showed +'q' to quit to normal display + + * DID + * VM/task-name + * PID + * %CPU + * EXThvc + * EXTwfe + * EXTwfi + * EXTmmioU + * EXTmmioK + * EXTfp + * EXTirq + * EXTsys64 + * EXTmabt + * EXTsum + * S + * P + * %ST + * %GUE + * %HYP +``` + +All monitoring items are displayed by default. You can press the up or down key to select a monitoring item, press the space key to set whether to display or hide the monitoring item, and press the q key to exit. +After %ST, %GUE, and %HYP are hidden, the following information is displayed: + +```sh +vmtop - 2020-09-14 10:23:25 - 1.0 +Domains: 1 running + + DID VM/task-name PID %CPU EXThvc EXTwfe EXTwfi EXTmmioU EXTmmioK EXTfp EXTirq EXTsys64 EXTmabt EXTsum S P + 2 example 4054916 12.0 0 0 1213 14 1 144 68 168 0 1464 S 125 + |_ qemu-kvm 4054916 0.0 0 0 0 0 0 0 0 0 0 0 S 125 + |_ qemu-kvm 4054928 0.0 0 0 0 0 0 0 0 0 0 0 S 119 + |_ signalfd_com 4054929 0.0 0 0 0 0 0 0 0 0 0 0 S 120 + |_ IO mon_iothr 4054932 0.0 0 0 0 0 0 0 0 0 0 0 S 117 + |_ CPU 0/KVM 4054933 2.0 0 0 303 6 0 29 10 35 0 354 S 98 + |_ CPU 1/KVM 4054934 4.0 0 0 279 0 0 39 17 49 0 345 S 1 + |_ CPU 2/KVM 4054935 3.0 0 0 283 0 0 33 20 40 0 343 S 122 + |_ CPU 3/KVM 4054936 3.0 0 0 348 8 1 43 21 44 0 422 S 110 + |_ memory_lock 4054940 0.0 0 0 0 0 0 0 0 0 0 0 S 126 + |_ vnc_worker 4054944 0.0 0 0 0 0 0 0 0 0 0 0 S 118 + |_ worker 1794 0.0 0 0 0 0 0 0 0 0 0 0 S 126 +``` + +%ST, %GUE, and %HYP will not be displayed on the screen. diff --git a/docs/en/docs/secGear/api-description.md b/docs/en/docs/secGear/api-description.md index 6e48a8c83..ec94310aa 100644 --- a/docs/en/docs/secGear/api-description.md +++ b/docs/en/docs/secGear/api-description.md @@ -10,6 +10,9 @@ Creates an enclave API. Initialization API. The function calls different TEE creation functions based on the type to initialize the enclave context in different TEE solutions. This API is called by the REE. +>![](./public_sys-resources/icon-note.gif) **说明:** +> Due to Intel SGX restrictions, memory mapping contention exists when multiple thread invoke cc_enclave_create concurrently. As a result, the creation of the enclave API may fail. Avoid concurrent invocations of cc_enclave_create in your code. + **Function Declarations:** cc_enclave_result_t cc_enclave_create(const char* path, enclave_type_t type, uint32_t version,uint32_t flags,const enclave_features_t* features,uint32_t features_count, diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 16cd18d03..0aaaacf6d 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -67,6 +67,8 @@ headless: true - [VM Maintainability Management]({{< relref "./docs/Virtualization/vm-maintainability-management.md" >}}) - [Best Practices]({{< relref "./docs/Virtualization/best-practices.md" >}}) - [Tool Guide]({{< relref "./docs/Virtualization/tool-guide.md" >}}) + - [vmtop]({{< relref "./docs/Virtualization/vmtop.md" >}}) + - [LibcarePlus]({{< relref "./docs/Virtualization/LibcarePlus.md" >}}) - [Appendix]({{< relref "./docs/Virtualization/appendix.md" >}}) - [StratoVirt Virtualization User Guide]({{< relref "./docs/StratoVirt/StratoVrit_guidence.md" >}}) - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_intoduction.md" >}}) -- Gitee From 91b84794931e2cd36d097bf6f7070e69bfff93dc Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 24 Mar 2022 17:51:12 +0800 Subject: [PATCH 004/130] =?UTF-8?q?=E8=A1=A5=E5=85=85=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E6=8C=87=E5=AF=BC=E6=96=87=E6=A1=A3=EF=BC=8C=E5=88=B7=E6=96=B0?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=BC=80=E5=8F=91=E6=96=87=E6=A1=A3=EF=BC=8C?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E7=B4=A2=E5=BC=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 100 ++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 152 ++++++++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 143 ++++++++++++++++ .../public_sys-resources/hosttools.png | Bin 0 -> 175700 bytes ...77\347\224\250\346\226\271\346\263\225.md" | 45 ------ ...05\344\270\216\350\277\220\350\241\214.md" | 49 ++++-- ...\273\272\346\214\207\345\257\274.markdown" | 4 + docs/zh/menu/index.md | 5 +- 8 files changed, 436 insertions(+), 62 deletions(-) create mode 100644 "docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" create mode 100644 docs/zh/docs/Embedded/public_sys-resources/hosttools.png delete mode 100644 "docs/zh/docs/Embedded/\344\275\277\347\224\250\346\226\271\346\263\225.md" create mode 100644 "docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" new file mode 100644 index 000000000..283757eed --- /dev/null +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -0,0 +1,100 @@ +# 基于openEuler Embedded的SDK应用开发 + +当前发布的镜像除了体验openEuler Embedded的基本功能外,还可以进行基本的应用开发,也即在openEuler Embedded上运行用户自己的程序。本章主要介绍如何基于openEuler Embedded的SDK进行应用开发。 + + + +- [安装SDK](#安装SDK) +- [使用SDK编译](#使用SDK编译) + + +### 安装SDK + +1. **执行SDK自解压安装脚本** + +运行如下命令: + +``` {.sourceCode .console} +sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh +``` + +根据提示输入工具链的安装路径,默认路径是/opt/openeuler/\/;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 + +举例如下: + +``` +sh ./openeuler-glibc-x86_64-openeuler-image-armv7a-qemu-arm-toolchain-22.03.sh`` +openEuler embedded(openEuler Embedded Reference Distro) SDK installer version 22.03 +================================================================ +Enter target directory for SDK (default: /opt/openeuler/22.03): sdk +You are about to install the SDK to "/usr1/openeuler/sdk". Proceed [Y/n]? y +Extracting SDK...............................................done +Setting it up...SDK has been successfully set up and is ready to be used. +Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. +$ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +2. **设置SDK环境变量** + +运行source命令。上例中前一步执行结束最后已打印source命令,运行即可。 + +``` {.sourceCode .console} +. /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +3. **查看是否安装成功** + +运行如下命令,查看是否安装成功、环境设置成功。 + +``` {.sourceCode .console} +arm-openeuler-linux-gnueabi-gcc -v +``` + +### 使用SDK编译 + +下面以使用SDK编译hello world为样例。 + +1. **准备代码** + +以构建一个hello world程序为例,运行在openEuler Embedded根文件系统镜像中。 + +创建一个hello.c文件,源码如下: + +``` c +#include + +int main(void) +{ + printf("hello world\n"); +} +``` + +编写CMakelist.txt,和hello.c文件放在同一个目录。 + +``` +project(hello C) + +add_executable(hello hello.c) +``` + +2. **编译生成二进制** + +进入hello.c文件所在目录,使用工具链编译,命令如下: + +``` {.sourceCode .console} +cmake .. +make +``` + +把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述使能共享文件系统场景。 + +3. **运行用户态程序** + +在openEuler Embedded系统中运行hello程序。 + +``` {.sourceCode .console} +cd /tmp/myfiles/ +./hello +``` + +如运行成功,则会输出\"hello world\"。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..2074cf578 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,152 @@ +openEuler Embedded容器构建指导 +============================== + +由于openEuler Embedded构建过程需要基于openEuler操作系统,且需要安装较多系统工具和构建工具。为方便开发人员快速搭建构建环境,我们将构建过程所依赖的操作系统和工具封装到一个容器中,这就使得开发人员可以快速搭建一个构建环境,进而投入到代码开发中去,避免在准备环境阶段消耗大量时间。 + + + +- [环境准备](#环境准备) + - [安装docker](#安装docker) + - [获取容器镜像](#获取容器镜像) + - [准备容器构建环境](#准备容器构建环境) +- [openEuler Embedded版本构建](#openEuler Embedded版本构建) + - [下载源码](#下载源码) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +## 环境准备 + +需要使用docker创建容器环境,为了确保docker成功安装,需满足以下软件硬件要求: + +- 操作系统: 推荐使用Ubuntu、Debian和RHEL(Centos、Fedora等) +- 内核: 推荐3.8及以上的内核 +- 驱动: 内核必须支持一种合适的存储驱动,例如: Device Mapper、AUFS、vfs、btrfs、ZFS +- 架构: 运行64位架构的计算机(x86\_64和amd64) + +### 安装docker + +------------- + +1. 检查当前环境是否已安装docker工具 + +运行如下命令,可以看到当前docker版本信息,则说明当前环境已安装docker,无需再次安装。 + +``` {.sourceCode .console} +docker version +``` + +2. 如果没有安装,可参考官方链接安装 + +官网地址: ,openEuler环境可参考Centos安装Docker。 + +例如openEuler环境docker安装命令如下: + +``` +sudo yum install docker +``` + +### 获取容器镜像 + +--------------- + +通过docker pull命令拉取华为云中的镜像到宿主机。命令如下: + +``` +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +``` + +### 准备容器构建环境 + +------------------- + +#### 1.启动容器 + +可通过docker run命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: + +``` +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +``` + +参数说明: + +- -i 让容器的标准输入保持打开 +- -d 让 Docker 容器在后台以守护态(Daemonized)形式运行 +- -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上 +- \--network 将容器连接到(host)网络 +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest + (镜像名称:镜像版本) +- bash 进入容器的方式 + +#### 2.查看已启动的容器id + +``` +docker ps +``` + +#### 3.进入容器 + +``` +docker exec -it 容器id bash +``` + +构建环境已准备完成,下面就可以在容器中进行构建了。 + +## openEuler Embedded版本构建 + +### 下载源码 + +1. 获取源码下载脚本 + +``` +git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v /usr1/openeuler/src/yocto-meta-openeuler +``` + +2. 通过脚本下载源码 + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +sh download_code.sh /usr1/openeuler/src +``` + +### 编译构建 + +- 编译架构: aarch64-std、aarch64-pro、arm-std、raspberrypi4-64 +- 构建目录: /usr1/build +- 源码目录: /usr1/openeuler/src +- 编译器所在路径: /usr1/openeuler/gcc/openeuler\_gcc\_arm64le + +>![](./public_sys-resources/icon-note.gif) **说明:** +>- 不同的编译架构使用不同的编译器,aarch64-std、aarch64-pro、raspberrypi4-64使用openeuler\_gcc\_arm64le编译器,arm-std使用openeuler\_gcc\_arm32le编译器。 +>- 下面以以aarch64-std目标架构编译为例。 + +1. 将/usr1目录所属群组改为openeuler,否则切换至openeuler用户构建会存在权限问题。 + +``` +chown -R openeuler:users /usr1 +``` + +2. 切换至openeuler用户。 + +``` +su openeuler +``` + +3. 进入构建脚本所在路径,运行编译脚本。 + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +source compile.sh aarch64-std /usr1/build /usr1/openeuler/gcc/openeuler_gcc_arm64le +bitbake openeuler-image +``` + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面aarch64-std的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..fc4974d26 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,143 @@ +openEuler Embedded构建指导 +===================== + +本章主要介绍如何构建openEuler Embedded。 + + + +- [环境准备](#环境准备) + - [Yocto中主机端命令使用](#Yocto中主机端命令使用) + - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) + - [已安装好工具的构建容器](#已安装好工具的构建容器) +- [openEuler Embedded版本构建](#openEuler Embedded版本构建) + - [构建代码下载](#构建代码下载) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +环境准备 +-------------- + +### Yocto中主机端命令使用 + +Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 + +为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 + +Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: + +![](./public_sys-resources/hosttools.png) + +当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: + +| 工具名 | 用途 | +| ------ | ------------- | +| cmake | cmake构建工具 | +| ninjia | ninja构建系统 | + +### openEuler Embedded所需构建工具 + +- 构建OS + + [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- 安装系统额外工具 + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- 预编译的交叉工具链和库 + + Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 + + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + + - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [ARM64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + +### 已安装好工具的构建容器 + +openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 + +使用者可以通过如下链接获得容器镜像直接用于编译: + +​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +具体构建指导请参考[openEuler Embedded容器构建指导](https://docs.openeuler.org/zh/22.03_LTS/docs/Embedded/openEuler Embedded容器构建指导.html)。 + +## openEuler Embedded版本构建 + +### 构建代码下载 + +openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: + +><顶层目录openeuler_embedded> +>├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 +>├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 + +1. 获取源码下载脚本 + + 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: + + - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 + - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 + - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 + +2. 通过脚本下载源码 + + - 下载最新代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - 下载指定版本代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 + +### 编译构建 + +一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 + +编译脚本的主要流程说明: + +1. 设置PATH增加额外工具路径 +2. TEMPLATECONF指定local.conf.sample等配置文件路径 +3. 调用poky仓的oe-init-build-env进行初始化配置 +4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 +5. 在编译目录执行bitbake openeuler-image编译openEuler + Embedded的image和sdk +6. 执行完发布件在编译目录的output目录下 + +运行编译脚本,以编译标准arm架构为例,编译方法如下: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git a/docs/zh/docs/Embedded/public_sys-resources/hosttools.png b/docs/zh/docs/Embedded/public_sys-resources/hosttools.png new file mode 100644 index 0000000000000000000000000000000000000000..83bb076a7763d522dde36168b1f713e524141531 GIT binary patch literal 175700 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≀xz@bFQS4ry9XjQoA0sw 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�(R?AoPm92`mzaRGj^aKz8aO;Uq9oyUI4 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

7SmeGEkt$2AqN! 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

tP&tSUE2a(A~VxEqz%h;(C}?~`GE)-O-J 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 - -int main(void) -{ - printf("hello openEuler\r\n"); -} -``` - -然后在宿主机上使用对应的工具链编译, 相应命令如下: -```shell -export PATH=$PATH:/opt/openEuler_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin -aarch64-linux-gnu-gcc --sysroot= hello.c -o hello -mv hello /temp -``` -把交叉编译好的hello程序拷贝到/tmp目录下,然后参照使能共享文件系统中的描述,使得openEuler embedded可以访问宿主机的目录。 - -3. **运行用户态程序** - -在openEuler embedded中运行hello程序。 -```shell -cd /tmp/host -./hello -``` -如运行成功,openEuler Embedded的shell中就会输出hello openEuler。 diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index f20caf191..8111524af 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -27,11 +27,17 @@ - 内核镜像**zImage**: 基于openEuler社区Linux 5.10代码构建得到。相应的内核配置可通过如下链接获取: - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel), 针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) + - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) - 根文件系统镜像(依据具体需求,以下二选一) + - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器等软件包。该镜像适合进行更加丰富的功能探索。 + + - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 + +- SDK(Software Development Kit)工具 + + - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -40,7 +46,7 @@ --- **注意事项** -- 建议使用QEMU5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在QEMU中使能,则运行时可能会产生错误,此时可能需要从源码重新编译QEMU。 +- 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 >![](./public_sys-resources/icon-note.gif) **说明:** @@ -48,6 +54,11 @@ --- +qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: + +``` {.sourceCode .console} +qemu-system-aarch64 --version +``` ### 极简运行场景 @@ -56,11 +67,11 @@ 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```shell +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```shell +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd ``` @@ -82,18 +93,18 @@ qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```sh +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```sh +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` 2. **映射文件系统** 在openEuler Embedded启动并登录之后,需要运行如下命令,映射(mount)共享文件系统 -```shell +``` cd /tmp mkdir host mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host @@ -104,7 +115,7 @@ mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host 在openEuler Embedded中,运行如下命令: -```shell +``` cd /tmp/host ls ``` @@ -116,34 +127,40 @@ ls 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: -```shell +``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` 针对aarch64(ARM Cortex A57),运行如下命令: -```shell +``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` 2. **宿主上建立虚拟网卡** -在宿主机上需要建立名为tap0的虚拟网卡,可以借助/etc/qemu-ifup脚本实现,其执行需要root权限,具体内容如下: +在宿主机上需要建立名为tap0的虚拟网卡,可以借助脚本实现,创建qemu-ifup脚本,放在/etc/下,具体内容如下: -```sh +``` #!/bin/bash ifconfig $1 192.168.10.1 up ``` +其执行需要root权限: + +``` +chmod a+x qemu-ifup +``` + 通过qemu-ifup脚本,宿主机上将创建名为tap0的虚拟网卡,地址为192.168.10.1。 3. **配置openEuler embedded网卡** openEuler Embedded登陆后,执行如下命令: -```shell +``` ifconfig eth0 192.168.10.2 ``` 4. **确认网络连通** 在openEuler Embedded中,执行如下命令: -```shell +``` ping 192.168.10.1 ``` @@ -151,4 +168,4 @@ ping 192.168.10.1 --- >![](./public_sys-resources/icon-note.gif) **说明:** - >如需openEuler embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 + >如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 diff --git "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..f9776a511 --- /dev/null +++ "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,4 @@ +openEuler Embedded构建指导 +===================== + +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index c949493c2..10868e4af 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -140,7 +140,10 @@ headless: true - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - - [使用方法]({{< relref "./docs/Embedded/使用方法.md" >}}) + - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/构建指导.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [openEuler Embedded容器构建指导]({{< relref "./docs/Embedded/openEuler Embedded容器构建指导.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From 8a2088afeab17b83c366553609bb8db394b30868 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 24 Mar 2022 17:58:59 +0800 Subject: [PATCH 005/130] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=8F=91=E8=A1=8C?= =?UTF-8?q?=E8=AF=B4=E6=98=8E=E4=B8=AD=E5=85=B3=E9=94=AE=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E9=87=8C=E7=9A=84=E5=B5=8C=E5=85=A5=E5=BC=8F=E9=95=9C=E5=83=8F?= =?UTF-8?q?=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...05\263\351\224\256\347\211\271\346\200\247.md" | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index f9dbd8291..5ea9dcfe0 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -68,15 +68,12 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 - **边缘轻量化**,内存占用少,可在资源受限情况下工作。 ## 嵌入式镜像 -提供轻量化、安全和容器等基础能力,支持ARM32、ARM64芯片架构。 -- **轻量化**,提供OS镜像 < 5M, 运行底噪<15 M, 以及<5S快速启动等能力。 -- **安全加固**,对账户口令、文件权限等资源安全加固,OS默认安全使能 -- **轻量容器**,面向嵌入式场景的轻量容器运行时,支持标准容器镜像的部署运行。 -- **多架构支持**,支持ARM32和ARM64芯片架构。 -- **混合部署**,:支持soc内实时和非实时多平面混合部署。 -- **开放小型化裁剪**,开放基于Yocto构建包的小型化定制裁剪能力。ARM交叉编译工具 -- **支持ARM交叉编译工具**,基于社区10.3版本gcc提供ARM版本交叉编译工具链 -- **A支持分布式软总线**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通 +- **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 +- **多硬件支持**,新增支持树莓派作为嵌入式场景通用硬件。 +- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 +- **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 +- **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 +- **嵌入式软件包支持**,新增80+嵌入式领域常用软件包的构建。 ## secPaver secPaver是一款SELinux安全策略开发工具,用于辅助开发人员为应用程序开发安全策略。 -- Gitee From eda887d2ddb2de720939d4b6fbf94733edd31272 Mon Sep 17 00:00:00 2001 From: reus Date: Thu, 24 Mar 2022 20:00:33 +0800 Subject: [PATCH 006/130] add score_admin.yaml for documentation debugging --- score_admins.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 score_admins.yaml diff --git a/score_admins.yaml b/score_admins.yaml new file mode 100644 index 000000000..fd5ef5469 --- /dev/null +++ b/score_admins.yaml @@ -0,0 +1,5 @@ +score_admins: + amy_mayun + zhangcuihong + lanlanbenming + rachel_123456 \ No newline at end of file -- Gitee From 28880315c17a53e99ba9a6e6f756abd2428a713a Mon Sep 17 00:00:00 2001 From: fushanqing Date: Sun, 27 Mar 2022 06:31:37 +0800 Subject: [PATCH 007/130] =?UTF-8?q?=E5=A2=9E=E5=8A=A0NestOS=E7=9B=B8?= =?UTF-8?q?=E5=85=B3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/NestOS/overview.md | 3 + ...77\347\224\250\346\226\271\346\263\225.md" | 493 ++++++++++++++++++ ...71\346\200\247\346\217\217\350\277\260.md" | 103 ++++ ...05\344\270\216\351\203\250\347\275\262.md" | 129 +++++ ...63\351\224\256\347\211\271\346\200\247.md" | 8 + docs/zh/menu/index.md | 4 + 6 files changed, 740 insertions(+) create mode 100644 docs/zh/docs/NestOS/overview.md create mode 100644 "docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" create mode 100644 "docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" create mode 100644 "docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" diff --git a/docs/zh/docs/NestOS/overview.md b/docs/zh/docs/NestOS/overview.md new file mode 100644 index 000000000..808961df7 --- /dev/null +++ b/docs/zh/docs/NestOS/overview.md @@ -0,0 +1,3 @@ +# NestOS用户指南 + +本文介绍云底座操作系统NestOS的安装部署与各个特性说明和使用方法,使用户能够快速了解并使用NestOS。NestOS搭载iSulad、docker、podman等主流容器基础平台,克服了由于用户修改系统内容、用户服务对系统组件依赖,以及系统软件包升级时不稳定中间态等种种导致升级过程不可靠的因素,最终以一种轻量级、定制化的操作系统呈现出来,并且具备十分便捷的集群组建能力。镜像下载地址详见[NestOS仓库](https://gitee.com/openeuler/NestOS)。 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" "b/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" new file mode 100644 index 000000000..24148750a --- /dev/null +++ "b/docs/zh/docs/NestOS/\344\275\277\347\224\250\346\226\271\346\263\225.md" @@ -0,0 +1,493 @@ +# K8S+iSulad 搭建 + +**以下步骤在master节点和node节点均需执行**,本教程以master为例 + +## 开始之前 + +需准备如下内容 +1.NestOS-22.03-date.x86_64.iso +2.一台主机用作master,一台主机用作node + +## 组件下载 + +编辑源文件,添加k8s的阿里云源 + +``` +vi /etc/yum.repos.d/openEuler.repo +``` + +添加如下内容 + +``` +[kubernetes] +name=Kubernetes +baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +enabled=1 +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +``` + +下载k8s组件以及同步系统时间所用组件 + +``` +rpm-ostree install kubelet kubeadm kubectl ntp ntpdate wget +``` + +重启生效 + +``` +systemctl reboot +``` + +选择最新的版本分支进入系统 + +## 配置环境 + +### 修改主机名,以master为例 + +``` +hostnamectl set-hostname k8s-master +sudo -i +``` + +编辑/etc/hosts + +``` +vi /etc/hosts +``` + +添加如下内容,ip为主机ip + +``` +192.168.237.133 k8s-master +192.168.237.135 k8s-node01 +``` + +### 同步系统时间 + +``` +ntpdate time.windows.com +systemctl enable ntpd +``` + +``` +关闭swap分区,防火墙,selinux +``` + +NestOS默认无swap分区,默认关闭防火墙 +关闭selinux如下 + +``` +vi /etc/sysconfig/selinux +修改为SELINUX=disabled +``` + +### 网络配置,开启相应的转发机制 + +创建配置文件 + +``` +vi /etc/sysctl.d/k8s.conf +``` + +添加如下内容 + +``` +net.bridge.bridge-nf-call-iptables=1 +net.bridge.bridge-nf-call-ip6tables=1 +net.ipv4.ip_forward=1 +``` + +使配置生效 + +``` +modprobe br_netfilter +sysctl -p /etc/sysctl.d/k8s.conf +``` + +## 配置iSula + +查看k8s需要的系统镜像,需注意pause的版本号 + +``` +kubeadm config images list +``` + +修改daemon配置文件 + +``` +vi /etc/isulad/daemon.json +``` + +``` +##关于添加项的解释说明## +registry-mirrors 设置为"docker.io" +insecure-registries 设置为"rnd-dockerhub.huawei.com" +pod-sandbox-image 设置为"registry.aliyuncs.com/google_containers/pause:3.5"(使用阿 +里云,pause版本可在上一步查看) +network-plugin 设置为"cni"。 +cni-bin-dir 设置为"/opt/cni/bin"; +cni-conf-dir 设置为"/etc/cni/net.d" +``` + +修改后的完整文件如下 + +``` +{"group": "isula", +"default-runtime": "lcr", +"graph": "/var/lib/isulad", +"state": "/var/run/isulad", +"engine": "lcr", +"log-level": "ERROR", +"pidfile": "/var/run/isulad.pid", +"log-opts": { +"log-file-mode": "0600", +"log-path": "/var/lib/isulad", +"max-file": "1", +"max-size": "30KB" +}, +"log-driver": "stdout", +"container-log": { +"driver": "json-file" +}, +"hook-spec": "/etc/default/isulad/hooks/default.json", +"start-timeout": "2m", +"storage-driver": "overlay2", +"storage-opts": [ +"overlay2.override_kernel_check=true" +], +"registry-mirrors": [ +"docker.io" +], +"insecure-registries": [ +"rnd-dockerhub.huawei.com" +], +"pod-sandbox-image": "registry.aliyuncs.com/google_containers/pause:3.5", +"native.umask": "secure", +"network-plugin": "cni", +"cni-bin-dir": "/opt/cni/bin", +"cni-conf-dir": "/etc/cni/net.d", +"image-layer-check": false, +"use-decrypted-key": true, +"insecure-skip-verify-enforce": false +} +``` + +启动相关服务 + +``` +systemctl restart isulad +systemctl enable isulad +systemctl enable kubelet +``` + +**以上为master,node节点均需执行的操作。** + +## master节点初始化 + +**该部分仅master节点执行。** +初始化,在这一步会拉取镜像,需等待一小段时间。也可在该步骤之前手动拉取镜像。 + +``` +kubeadm init --kubernetes-version=1.22.2 --apiserver-advertise- +address=192.168.237.133 --cri-socket=/var/run/isulad.sock --image-repository +registry.aliyuncs.com/google_containers --service-cidr=10.10.0.0/16 --pod- +network-cidr=10.122.0.0/16 +``` + +``` +##关于初始化参数的解释说明## +kubernetes-version 为当前安装的版本 +apiserver-advertise-address 为master节点ip +cri-socket 指定引擎为isulad +image-repository 指定镜像源为阿里云,可省去修改tag的步骤 +service-cidr 指定service分配的ip段 +pod-network-cidr 指定pod分配的ip段 +``` + +初始化成功后,复制最后两行内容方便后续node节点加入使用 + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +**注意**:添加--cri-socket=/var/run/isulad.sock以使用isulad为容器引擎 +查看下载好的镜像 + +``` +isula images +``` + +按照初始化成功所提示,配置集群 + +``` +mkdir -p $HOME/.kube +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +chown $(id -u):$(id -g) $HOME/.kube/config +export KUBECONFIG=/etc/kubernetes/admin.conf +source /etc/profile +``` + +查看健康状态 + +``` +kubectl get cs +``` + +可能存在controller-manager,scheduler状态为unhealthy的情况,解决方法如下: +编辑相关配置文件 + +``` +vi /etc/kubernetes/manifests/kube-controller-manager.yaml +``` + +``` +注释如下内容: +--port=0 +修改hostpath: +将所有/usr/libexec/kubernetes/kubelet-plugins/volume/exec 修改为/opt/libexec/... +``` + +``` +vi /etc/kubernetes/manifests/kube-scheduler.yaml +``` + +``` +注释如下内容: +--port=0 +``` + +修改完成后,再次查看健康状态 + +## 配置网络插件 + +仅需要在master节点配置网络插件,但是要在**所有节点**提前拉取镜像,拉取镜像指令如下。 + +``` +isula pull calico/node:v3.19.3 +isula pull calico/cni:v3.19.3 +isula pull calico/kube-controllers:v3.19.3 +isula pull calico/pod2daemon-flexvol:v3.19.3 +``` + +**以下步骤仅在master节点执行** +获取配置文件 + +``` +wget https://docs.projectcalico.org/v3.19/manifests/calico.yaml +``` + +编辑calico.yaml 修改所有/usr/libexec/... 为 /opt/libexec/... +然后执行如下命令完成calico的安装: + +``` +kubectl apply -f calico.yaml +``` + +通过kubectl get pod -n kube-system查看calico是否安装成功 +通过kubectl get pod -n kube-system查看是否所有pod状态都为running + +## node节点加入集群 + +在node节点执行如下指令,将node节点加入集群 + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +通过kubectl get node 查看master,node节点状态是否为ready + +至此,k8s部署成功。 + +# rpm-ostree使用 + +## rpm-ostree安装软件包 + +安装wget + +``` +rpm-ostree install wget +``` + +重启系统,可在启动时通过键盘上下按键选择rpm包安装完成后或安装前的系统状态,其中【ostree:0】为安装之后的版本。 + +``` +systemctl reboot +``` + +查看wget是否安装成功 + +``` +rpm -qa | grep wget +``` + +## rpm-ostree 手动更新升级 NestOS + +在NestOS中执行命令可查看当前rpm-ostree状态,可看到当前版本号 + +``` +rpm-ostree status +``` + +执行检查命令查看是否有升级可用,发现存在新版本 + +``` +rpm-ostree upgrade --check +``` + +预览版本的差异 + +``` +rpm-ostree upgrade --preview +``` + +在最新版本中,我们将nano包做了引入。 +执行如下指令会下载最新的ostree和RPM数据,不需要进行部署 + +``` +rpm-ostree upgrade --download-only +``` + +重启NestOS,重启后可看到系统的新旧版本两个状态,选择最新版本的分支进入 + +``` +rpm-ostree upgrade --reboot +``` + +## 比较NestOS版本差别 + +检查状态,确认此时ostree有两个版本,分别为LTS.20210927.dev.0和LTS.20210928.dev.0 + +``` +rpm-ostree status +``` + +根据commit号比较2个ostree的差别 + +``` +rpm-ostree db diff 55eed9bfc5ec fe2408e34148 +``` + +## 系统回滚 + +当一个系统更新完成,之前的NestOS部署仍然在磁盘上,如果更新导致了系统出现问题,可以使用之前的部署回滚系统。 + +### 临时回滚 + +要临时回滚到之前的OS部署,在系统启动过程中按住shift键,当引导加载菜单出现时,在菜单中选择相关的分支。 + +### 永久回滚 + +要永久回滚到之前的操作系统部署,登录到目标节点,运行rpm-ostree rollback,此操作将使用之前的系统部署作为默认部署,并重新启动到其中。 +执行命令,回滚到前面更新前的系统。 + +``` +rpm-ostree rollback +``` + +重启后失效。 + +## 切换版本 + +在上一步将NestOS回滚到了旧版本,可以通过命令切换当前 NestOS 使用的rpm-ostree版本,将旧版本切换为新版本。 + +``` +rpm-ostree deploy -r 22.03.20220325.dev.0 +``` + +重启后确认目前NestOS已经使用的是新版本的ostree了。 + + +# zincati自动更新使用 + +zincati负责NestOS的自动更新,zincati通过cincinnati提供的后端来检查当前是否有可更新版本,若检测到有可能新版本,会通过rpm-ostree进行下载。 + +目前系统默认关闭zincati自动更新服务,可通过修改配置文件设置为开机自动启动自动更新服务。 + +``` +vi /etc/zincati/config.d/95-disable-on-dev.toml +``` + +将updates.enabled设置为true +同时增加配置文件,修改cincinnati后端地址 + +``` +vi /etc/zincati/config.d/update-cincinnati.toml +``` + +添加如下内容 + +``` +[cincinnati] +base_url="http://nestos.org.cn:8080" +``` + +重新启动zincati服务 + +``` +systemctl restart zincati.service +``` + +当有新版本时,zincati会自动检测到可更新版本,此时查看rpm-ostree状态,可以看到状态是“busy”,说明系统正在升级中。 + +一段时间后NestOS将自动重启,此时再次登录NestOS,可以再次确认rpm-ostree的状态,其中状态转为"idle",而且当前版本已经是“20220325”,这说明rpm-ostree版本已经升级了。 + +查看zincati服务的日志,确认升级的过程和重启系统的日志。另外日志显示的"auto-updates logic enabled"也说明更新是自动的。 + +# 定制NestOS + +我们可以使用nestos-installer 工具对原始的NestOS ISO文件进行加工,将Ignition文件打包进去从而生成定制的 NestOS ISO文件。使用定制的NestOS ISO文件可以在系统启动完成后自动执行NestOS的安装,因此NestOS的安装会更加简单。 + +在开始定制NestOS之前,需要做如下准备工作: + +- 下载 NestOS ISO +- 准备 config.ign文件 + +## 生成定制NestOS ISO文件 + +### 设置参数变量 + +``` +$ export COREOS_ISO_ORIGIN_FILE=nestos-22.03.20220324.x86_64.iso +$ export COREOS_ISO_CUSTOMIZED_FILE=my-nestos.iso +$ export IGN_FILE=config.ign +``` + +### ISO文件检查 + +确认原始的NestOS ISO文件中是没有包含Ignition配置。 + +``` +$ nestos-installer iso ignition show $COREOS_ISO_ORIGIN_FILE + +Error: No embedded Ignition config. +``` + +### 生成定制NestOS ISO文件 + +将Ignition文件和原始NestOS ISO文件打包生成定制的NestOS ISO文件。 + +``` +$ nestos-installer iso ignition embed $COREOS_ISO_ORIGIN_FILE --ignition-file $IGN_FILE $COREOS_ISO_ORIGIN_FILE --output $COREOS_ISO_CUSTOMIZED_FILE +``` + +### ISO文件检查 + +确认定制NestOS ISO 文件中已经包含Ignition配置了 + +``` +$ nestos-installer iso ignition show $COREOS_ISO_CUSTOMIZED_FILE +``` + +执行命令,将会显示Ignition配置内容 + +## 安装定制NestOS ISO文件 + +使用定制的 NestOS ISO 文件可以直接引导安装,并根据Ignition自动完成NestOS的安装。在完成安装后,我们可以直接在虚拟机的控制台上用nest/password登录NestOS。 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" "b/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" new file mode 100644 index 000000000..3bcae9e30 --- /dev/null +++ "b/docs/zh/docs/NestOS/\345\212\237\350\203\275\347\211\271\346\200\247\346\217\217\350\277\260.md" @@ -0,0 +1,103 @@ +# 功能特性描述 + +## 容器技术 + +NestOS通过容器化 (containerized) 的运算环境向应用程序提供运算资源,应用程序之间共享系统内核和资源,但是彼此之间又互不可见。这意味着应用程序将不会再被直接安装到操作系统中,而是通过 Docker 运行在容器中。大大降低了操作系统、应用程序及运行环境之间的耦合度。相对于传统的应用程序部署部署方式而言,在NestOS 集群中部署应用程序更加灵活便捷,应用程序运行环境之间的干扰更少,而且操作系统自身的维护也更加容易。 + +## rpm-ostree + +### 系统更新 + +rpm-ostree是一种镜像/包混合系统,可以看成是rpm和ostree的合体。一方面它提供了基于rpm的软件包安装管理方式,另一方面它提供了基于ostree的操作系统更新升级。rpm-ostree将这两种操作都视为对操作系统的更新,每次对系统的更新都像rpm-ostree在提交“Transaction-事务”,从而确保更新全部成功或全部失败,允许在更新系统后回滚到更新前的状态。 + +rpm-ostree在更新操作系统的时候会有2个bootable区域,分别为更新前和更新后的,对系统的更新升级只有在重启操作系统后才生效。如果软件安装或升级出现问题,通过rpm-ostree回滚会使nestos系统返回到先前的状态。我们可以查看nestos的“/ostree/”和“/boot/”目录,它们是ostree Repository环境并且可以观察到boot使用哪个ostree。 + +### 文件系统 + +在rpm-ostree的文件系统布局中,只有/etc和/var是唯一可写的目录,/var中的任何数据不会被触及,而是在升级过程中共享。在系统升级的过程中采用新的默认值/etc,并将更改添加到顶部。这意味着升级将会接收/etc中新的默认文件,这是一个非常关键的特性。 + +Ostree旨在可以并行安装多个独立操作系统的版本,ostree依赖于一个新的ostree 目录,该目录实际上可以并行安装在现有的操作系统或者是占据物理/root目录的发行版本中。每台客户机和每组部署上都存储在 /ostree/deploy/STATEROOT/CHECKSUM 上,而且还有一个ostree存储库存储在 /ostree/repo 中。每个部署主要由一组指向存储库的硬链接组成,这意味着每个版本都进行了重复数据的删除并且升级过程中只消耗了与新文件成比例的磁盘空间加上一些恒定的开销。 + +Ostree模型强调的是OS只读内容保存在 /usr 中,它附带了用于创建Linux只读安装以防止无意损坏的代码,对于给定的操作系统,每个部署之间都有一个 /var 共享的可供读写的目录。Ostree核心代码不触及该目录的内容,如何管理和升级状态取决于每个操作系统中的代码。 + +### 系统扩展 + +出于安全性和可维护性的考虑,nestos让基础镜像尽可能保持小巧和精简。但是在某些情况下,需要向基本操作系统本身添加软件,例如驱动软件,VPN等等,因为它们比较难容器化。这些包拓展了操作系统的功能,为此,rpm-ostree将这些包视为拓展,而不是仅仅在用户运行时提供。也就是说,目前nestos对于实际安装哪些包没有限制,默认情况下,软件包是从openEuler仓库下载的。 + +要对软件包进行分层,需要重新编写一个systemd单元来执行rpm-ostree命令安装所需要的包,所做的更改应⽤于新部署,重新启动才能生效。 + +## nestos-installer + +nestos-installer是一个帮助安装Nestos的程序,它可以执行以下操作: + +(1)安装操作系统到一个目标磁盘,可使用Ignition和首次引导内核参数对其进行自定义(nestos-installer install) + +(2)下载并验证各种云平台、虚拟化或者裸机平台的操作系统映像(nestos-installer download) + +(3)列出可供下载的nestos镜像(nestos-installer list-stream) + +(4)在ISO中嵌入一个Ignition配置,以自定义地从中启动操作系统(nestos-installer iso ignition) + +(5)将Ignition配置包装在initd映像中,该映像可以被加入到PXE initramfs中以自定义从中启动的操作系统(nestos-installer pxe ignition) + +## zincati + +Zincati是nestos自动更新的代理,它作为Cincinnati和rpm-ostree的客户端,负责自动更新/重启机器。Zincati有如下特点: + +(1)支持自动更新代理,支持分阶段推出 + +(2)通过toml配置文件支持运行时自定义,用户自定义配置文件可覆盖默认配置 + +(3)多种更新策略 + +(4)通过维护窗口每周在特定时间范围内进行更新的策略 + +(5)收集和导出本地运行的zincati内部指标,可提供给Prometheus以减轻跨大量节点的监控任务 + +(6)具有可配置优先级的日志记录 + +(7)通过Cincinnati协议支持复杂的更新图 + +(8)通过外部锁管理器支持集群范围的重启编排 + +## 系统初始化(Ignition) + +Ignition 是一个与分发无关的配置实用程序,不仅用于安装,还读取配置文件(JSON 格式)并根据该配置nestos系统。可配置的组件包括存储和文件系统、systemd单元和用户。 + +Ignition仅在系统第一次引导期间运行一次(在initramfs中)。因为 Ignition 在启动过程的早期运行,所以它可以在用户空间开始启动之前重新分区磁盘、格式化文件系统、创建用户和写入文件。 因此,systemd 服务在 systemd 启动时已经写入磁盘,从而加快了启动速度。 + +(1)Ignition 仅在第一次启动时运行 + +Ignition 旨在用作配置工具,而不是配置管理工具。 Ignition 鼓励不可变的基础设施,其中机器修改要求用户丢弃旧节点并重新配置机器。 + +(2)Ignition不是在任何情况下都可以完成配置 + +Ignition 执行它需要的操作,使系统与 Ignition 配置中描述的状态相匹配。 如果由于任何原因 Ignition 无法提供配置要求的确切机器,Ignition 会阻止机器成功启动。例如,如果用户想要获取托管在 https://example.com/foo.conf 的文档并将其写入磁盘,如果无法解析给定的 URL,Ignition 将阻止机器启动。 + +(3)Ignition只是声明性配置 + +Ignition配置只描述了系统的状态,没有列出 Ignition 应该采取的一系列步骤。 + +Ignition 配置不允许用户提供任意逻辑(包括 Ignition 运行的脚本)。用户只需描述哪些文件系统必须存在、哪些文件必须创建、哪些用户必须存在等等。任何进一步的定制都必须使用由 Ignition 创建的 systemd 服务。 + +(4)Ignition配置不应手写 + +Ignition 配置被设计为人类可读但难以编写,是为了阻止用户尝试手动编写配置。可以使用Butane或类似工具生成或转化生成Ignition 配置。 + +## Afterburn + +Afterburn是类似于云平台一样的一次性代理,可以用于与特定的提供者的元数据端点进行交互,通常和Ignition结合使用。 + +Afterburn包含了很多可以在实例生命周期中不同时间段运行的模块。下面的服务是根据特定的平台可能在第一次启动时在initramfs中运行的: + +(1)设置本地主机名 + +(2)加入网络命令行参数 + +以下的功能是在一定条件下,作为systemd服务单元在一些平台上才能使用的: + +(1)为本地系统用户安装公共SSH密钥 + +(2)从实例元数据中检索属性 + +(3)给提供者登记以便报道成功的启动或实例供应 \ No newline at end of file diff --git "a/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" new file mode 100644 index 000000000..6eb2dca54 --- /dev/null +++ "b/docs/zh/docs/NestOS/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -0,0 +1,129 @@ +# 安装与部署 + +## 在 VMware 上部署 NestOS + +本指南展示了如何在VMware虚拟机管理程序上配置最新的 NestOS。 + +目前NestOS仅支持x86_64架构。 + +### 开始之前 + +​ 在开始部署 NestOS 之前,需要做如下准备工作: + +- 下载 NestOS ISO +- 准备 config.bu 文件 +- 配置 butane 工具(Linux环境/win10环境) +- 安装有VMware的宿主机 + +### 初步安装与启动 + +#### 启动 NestOS + +初次启动 NestOS ,ignition 尚未安装,可根据系统提示使用 nestos-installer 组件进行ignition的安装。 + +### 配置 ignition 文件 + +#### 获取 Butane + +可以通过 Butane 将 bu 文件转化为 igniton 文件。ignition 配置文件被设计为可读但难以编写,是为了 +阻止用户尝试手动编写配置。 +Butane 提供了多种环境的支持,可以在 linux/windows 宿主机中或容器环境中进行配置。 + +``` +docker pull quay.io/coreos/butane:release +``` + +#### 生成登录密码 + +在宿主机执行如下命令,并输入你的密码。 + +``` +# openssl passwd -1 -salt yoursalt +Password: +$1$yoursalt$1QskegeyhtMG2tdh0ldQN0 +``` + +#### 生成ssh-key + +在宿主机执行如下命令,获取公钥和私钥以供后续 ssh 登录。 + +``` +# ssh-keygen -N '' -f ./id_rsa +Generating public/private rsa key pair. +Your identification has been saved in ./id_rsa +Your public key has been saved in ./id_rsa.pub +The key fingerprint is: +SHA256:4fFpDDyGHOYEd2fPaprKvvqst3T1xBQuk3mbdon+0Xs root@host-12-0-0-141 +``` + +``` +The key's randomart image is: ++---[RSA 3072]----+ +| ..= . o . | +| * = o * . | +| + B = * | +| o B O + . | +| S O B o | +| * = . . | +| . +o . . | +| +.o . .E | +| o*Oo ... | ++----[SHA256]-----+ +``` + +可以在当前目录查看id_rsa.pub公钥 + +``` +# cat id_rsa.pub +ssh-rsa +AAAAB3NzaC1yc2... +``` + +#### 编写bu文件 + +进行最简单的初始配置,如需更多详细的配置,参考后面的 ignition 详解。 +如下为最简单的 config.bu 文件 + +``` +variant: fcos +version: 1.1.0 +passwd: + users: + - name: nest + password_hash: "$1$yoursalt$1QskegeyhtMG2tdh0ldQN0" + ssh_authorized_keys: + - "ssh-rsa + AAAAB3NzaC1yc2EAAA..." +``` + +#### 生成ignition文件 + +将 config.bu 通过 Butane 工具转换为 config.ign 文件,如下为在容器环境下进行转换。 + +``` +# docker run --interactive --rm quay.io/coreos/butane:release \ +--pretty --strict < your_config.bu > transpiled_config.ign +``` + +### 安装 NestOS + +将宿主机生成的的config.ign文件通过scp拷贝到前面初步启动的 NestOS 中,该OS目前运行在内存中, +并没有安装到硬盘。 + +``` +sudo -i +scp root@your_ipAddress:/root/config.ign /root +``` + +根据系统所给提示,执行如下指令完成安装。 + +``` +nestos-installer install /dev/sda --ignition-file config.ign +``` + +安装完成后重启 NestOS 。 + +``` +systemctl reboot +``` +完成 diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 5ea9dcfe0..382d97667 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -79,6 +79,14 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 secPaver是一款SELinux安全策略开发工具,用于辅助开发人员为应用程序开发安全策略。 - **策略管理**,提供高阶配置语言,根据策略配置文件内容生成SELinux策略文件,降低SElinux使用门槛。 +## NestOS +NestOS是一款在openEuler社区CloudNative sig组孵化的云底座操作系统,专注于提供最佳的容器主机,大规模下安全的运行容器化工作负载。 +- **开箱即用的容器平台**,搭载了iSulad、docker、podman 、cri-o等主流容器基础平台。 +- **简单易用的安装配置过程**,采用了Ignition技术,提供个性化配置。 +- **安全可靠的包管理方式**,使用rpm-ostree进行包管理。 +- **友好可控的自动更新代理**,采用zincati实现无感升级。 +- **紧密配合的双系统分区**,双系统分区设计确保系统安全。 + ## 更多的第三方应用支持 - **KubeSphere**,KubeSphere 是在 Kubernetes 之上构建的以应用为中心的容器平台,完全开源,由青云科技发起,并由 openEuler 社区 SIG-KubeSphere 提供支持和维护。 - **OpenStack Wallaby**,OpenStack版本更新到Wallaby。Wallaby是2021年4月份发布的最新稳定版本,包含nova、kolla、cyborg、tacker等核心项目的重要更新。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cb3b360db..2f8d63396 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -216,3 +216,7 @@ headless: true - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) - [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) +- [NestOS用户指南]({{< relref "./docs/NestOS/overview.md" >}}) + - [安装与部署]({{< relref "./docs/NestOS/安装与部署.md" >}}) + - [使用方法]({{< relref "./docs/NestOS/使用方法.md" >}}) + - [功能特性描述]({{< relref "./docs/NestOS/功能特性描述.md" >}}) -- Gitee From ad8f2c0ea4c8ab7314bcc315062b815c3fc09c5e Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Mon, 28 Mar 2022 07:27:25 +0000 Subject: [PATCH 008/130] =?UTF-8?q?update=20docs/zh/docs/gazelle/gazelle.m?= =?UTF-8?q?d.=20=E5=8E=BB=E6=8E=89=E8=AF=A5=E6=96=87=E4=BB=B6=E6=9C=80?= =?UTF-8?q?=E5=BC=80=E5=A7=8B=E7=9A=84=E6=97=A0=E6=95=88=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/gazelle/gazelle.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/zh/docs/gazelle/gazelle.md b/docs/zh/docs/gazelle/gazelle.md index f2a933c70..8ea1f3e52 100644 --- a/docs/zh/docs/gazelle/gazelle.md +++ b/docs/zh/docs/gazelle/gazelle.md @@ -1,5 +1,3 @@ -gazelle - # gazelle ## Introduction -- Gitee From 2742bdab2bb1c192eb93d2ef6fa26c6acaaf9283 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Mon, 28 Mar 2022 07:56:11 +0000 Subject: [PATCH 009/130] =?UTF-8?q?update=20docs/zh/menu/index.md.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=96=B0=E6=96=87=E6=A1=A3=20gazelle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/menu/index.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 10868e4af..cb3b360db 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -215,3 +215,4 @@ headless: true - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) +- [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) -- Gitee From 9d1d96e958226981bdcf5cf8476d6841afc7a020 Mon Sep 17 00:00:00 2001 From: lujie42 Date: Tue, 29 Mar 2022 03:58:49 +0000 Subject: [PATCH 010/130] =?UTF-8?q?update=20docs/zh/docs/SecHarden/SELinux?= =?UTF-8?q?=E9=85=8D=E7=BD=AE.md.=20=E8=A1=A5=E5=85=85=E5=AE=8C=E5=96=84SE?= =?UTF-8?q?Linux=E6=8C=87=E5=AF=BC=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SELinux\351\205\215\347\275\256.md" | 113 +++++++++++++++++- 1 file changed, 112 insertions(+), 1 deletion(-) diff --git "a/docs/zh/docs/SecHarden/SELinux\351\205\215\347\275\256.md" "b/docs/zh/docs/SecHarden/SELinux\351\205\215\347\275\256.md" index 7bf0e2e97..20b3ac300 100644 --- "a/docs/zh/docs/SecHarden/SELinux\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/SecHarden/SELinux\351\205\215\347\275\256.md" @@ -103,6 +103,115 @@ openEuler默认使用SELinux提升系统安全性。SELinux分为三种模式: Max kernel policy version: 31 ``` +## 策略添加 +- 从audit日志中获取并添加缺失策略(需要audit服务开启且audit日志中已经存在SELinux访问拒绝日志)。 + 1. 查询audit日志中是否有SELinux访问拒绝日志,其中audit日志的路径视具体情况决定。 + ``` + # grep avc /var/log/audit/audit.log* + ``` + 2. 查询缺失规则。 + ``` + # audit2allow -a /var/log/audit/audit.log* + ``` + 3. 根据缺失规则生成一个策略模块,命名为demo。 + ``` + # audit2allow -a /var/log/audit/audit.log* -M demo + ******************** IMPORTANT *********************** + To make this policy package active, execute: + semodule -i demo.pp + ``` + 4. 加载demo策略模块。 + ``` + # semodule -i demo.pp + ``` + +- 编写并添加SELinux策略模块。 + 1. 编写FC文件(涉及新增文件安全上下文需要编写)。 + ``` + # cat demo.fc + /usr/bin/example -- system_u:object_r:example_exec_t:s0 + /resource -- system_u:object_r:resource_file_t:s0 + ``` + 2. 编写TE文件(仅供参考)。 + ``` + # cat demo.te + module demo 1.0; + require + { + role unconfined_r; + role system_r; + type user_devpts_t; + type root_t; + attribute file_type; + attribute domain; + class dir { getattr search add_name create open remove_name rmdir setattr write }; + class file { entrypoint execute getattr open read map setattr write create }; + class process { sigchld rlimitinh siginh transition setcap getcap }; + class unix_stream_socket { accept bind connect listen recvfrom sendto listen create lock read write getattr setattr getopt setopt append shutdown ioctl connectto }; + class capability { chown dac_override dac_read_search }; + class chr_file { append getattr ioctl read write }; + }; + role unconfined_r types example_t; + role system_r types example_t; + type example_exec_t, file_type; + type resource_file_t, file_type; + type example_t, domain; + allow example_t user_devpts_t : chr_file { append getattr ioctl read write }; + allow example_t file_type : dir { getattr search }; + allow example_t example_exec_t : file { entrypoint execute getattr map open read }; + allow domain example_exec_t : file { execute getattr map open read }; + allow example_t example_exec_t : process { sigchld }; + allow domain example_t : process { rlimitinh siginh transition }; + allow example_t resource_file_t : file { create getattr open read setattr write }; + allow example_t root_t : dir { add_name create getattr open remove_name rmdir search setattr write }; + allow example_t example_t : unix_stream_socket { accept append bind connect create getattr getopt ioctl listen listen lock read recvfrom sendto setattr setopt shutdown write }; + allow example_t domain : unix_stream_socket { connectto }; + allow example_t example_t : capability { chown dac_override dac_read_search }; + allow example_t example_t : process { getcap setcap }; + type_transition domain example_exec_t : process example_t; + type_transition example_t root_t : file resource_file_t "resource"; + ``` + 3. 编译demo.te为demo.mod。 + ``` + # checkmodule -Mmo demo.mod demo.te + ``` + 4. 打包demo.mod和demo.fc为策略模块文件。 + ``` + semodule_package -m demo.mod -f demo.fc -o demo.pp + ``` + 5. 加载策略模块。 + ``` + # semodule -i demo.pp + ``` + 6. 删除加载的策略模块。 + ``` + # semodule -r demo + libsemanage.semanage_direct_remove_key: Removing last demo module (no other demo module exists at another priority). + ``` + +## 功能验证 +- SELinux为白名单机制,未配置合理策略的模块可能会由于缺少权限无法正常运行。固对模块进行功能验证并适配合理的规则是很有必要的。 + 1. 查看audit服务是否开启。 + ``` + # systemctl status auditd + ``` + 2. 设置SELinux模式为permissive(仅打印告警而不强制执行,参考 配置说明 )。 + ``` + # getenforce + Permissive + ``` + 3. 全量跑测试模块的功能用例,查看audit日志中SELinux访问拒绝日志。 + ``` + # grep avc /var/log/audit/audit.log* + ``` + 4. 分析访问拒绝日志,并过滤出缺失的合理规则。 + ``` + type=AVC msg=audit(1596161643.271:1304): avc: denied { read } for pid=1782603 comm="smbd" name=".viminfo" dev="dm-0" ino=2488208 scontext=system_u:system_r:smbd_t:s0 tcontext=staff_u:object_r:user_home_t:s0 tclass=file permissive=1 + 表示进程smbd(安全上下文为system_u:system_r:smbd_t:s0)对文件.viminfo(安全上下文为staff_u:object_r:user_home_t:s0)执行文件读操作被权限拒绝。 + permissive=1表示当前运行的是permissive模式,该日志只记录未执行禁止。 + ``` + 4. 参考 策略添加,将缺少的合理规则补全。 + ## 注意事项 - 如用户需使能SELinux功能,建议通过dnf升级方式将selinux-policy更新为最新版本,否则应用程序有可能无法正常运行。升级命令示例: @@ -110,5 +219,7 @@ openEuler默认使用SELinux提升系统安全性。SELinux分为三种模式: ``` dnf update selinux-policy -y ``` - + - 如果用户由于SELinux配置不当(如误删策略或未配置合理的规则或安全上下文)导致系统无法启动,可以在启动参数中添加selinux=0,关闭SELinux功能,系统即可正常启动。 + +- 开启SELinux后,会对访问行为进行权限检查,对操作系统性能会有一定程度(与运行环境访问操作频率相关)的影响。 \ No newline at end of file -- Gitee From 906acf9fb79996c2989ce9ef0988ea0a7ff18d3a Mon Sep 17 00:00:00 2001 From: x30004928 Date: Wed, 30 Mar 2022 09:53:23 +0800 Subject: [PATCH 011/130] update imagetailor menu --- .../docs/TailorCustom/figures/flowchart.png | Bin 0 -> 21270 bytes ...77\347\224\250\346\214\207\345\215\227.md" | 935 ++++++++++++++++++ ...77\347\224\250\346\214\207\345\215\227.md" | 884 ----------------- .../public_sys-resources/delete.PNG | Bin 17428 -> 0 bytes .../public_sys-resources/drivers.png | Bin 7060 -> 0 bytes .../public_sys-resources/flowchart.png | Bin 29937 -> 0 bytes .../public_sys-resources/libs.png | Bin 4180 -> 0 bytes .../public_sys-resources/tools.png | Bin 2992 -> 0 bytes docs/zh/menu/index.md | 2 +- 9 files changed, 936 insertions(+), 885 deletions(-) create mode 100644 docs/zh/docs/TailorCustom/figures/flowchart.png create mode 100644 "docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" delete mode 100644 "docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/drivers.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/flowchart.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/libs.png delete mode 100644 docs/zh/docs/TailorCustom/public_sys-resources/tools.png diff --git a/docs/zh/docs/TailorCustom/figures/flowchart.png b/docs/zh/docs/TailorCustom/figures/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..e4fecb8b310f204d6cfd07449ccc3c93d1badd51 GIT binary patch literal 21270 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 X@4L`5c?#MHM8+U%jJ;)U5F_Tf22 literal 0 HcmV?d00001 diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" new file mode 100644 index 000000000..f7b29e358 --- /dev/null +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -0,0 +1,935 @@ +# imageTailor 使用指南 + +- [简介](#简介) +- [安装工具](# 安装工具) + - [软硬件要求](#软硬件要求) + - [获取安装包](#获取安装包) + - [安装 imageTailor](#安装 imageTailor) + - [目录介绍](#目录介绍) +- [定制系统](#定制系统) + - [总体流程](#总体流程) + - [定制业务包](#定制业务包) + - [配置本地 repo 源](#配置本地 repo 源) + - [添加文件](#添加文件) + - [添加 RPM 包](#添加 RPM 包) + - [添加 hook 脚本](#添加 hook 脚本) + - [配置系统参数](#配置系统参数) + - [配置主机参数](#配置主机参数) + - [配置初始密码](#配置初始密码) + - [配置分区](#配置分区) + - [配置网络](#配置网络) + - [配置内核参数](#配置内核参数) + - [制作系统](#制作系统) + - [命令介绍](#命令介绍) + - [制作指导](#制作指导) + - [裁剪时区](#裁剪时区) + - [定制示例](#定制示例) + + + +## 简介 + +操作系统除内核外,还包含各种功能的外围包。通用操作系统包含较多外围包,提供了丰富的功能,但是这也带来了一些影响: + +- 占用资源(内存、磁盘、CPU 等)多,导致系统运行效率低 +- 很多功能用户不需要,增加了开发和维护成本 + +因此,openEuler 提供了 imageTailor 镜像裁剪定制工具。用户可以根据需求裁剪操作系统镜像中不需要的外围包,或者添加所需的业务包或文件。该工具主要提供了以下功能: + +- 系统包裁剪:根据需要选择安装的 RPM 包列表,裁剪系统命令、库、驱动。 +- 系统配置修改:配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、内核版本号。 +- 软件包增加:将用户的 RPM 包安装到系统中或者将用户文件添加到系统中。 + + + +## 安装工具 + +本节以 openEuler 22.03 LTS 版本 AArch64 架构为例,说明安装方法。 + +### 软硬件要求 + +安装和运行 imageTailor 需要满足以下软硬件要求: + +- 机器架构为 x86_64 或者 AArch64 + +- 操作系统为 openEuler 22.03 LTS(该版本内核版本为 5.10,python 版本为 3.9,满足工具要求) + +- 运行工具的机器根目录 '/' 需要 40 GB 以上空间 + +- python 版本 3.9 及以上 + +- kernel 内核版本 5.10 及以上 + +- 关闭 SElinux 服务 + + ```shell + $ sudo setenforce 0 + $ getenforce + Permissive + ``` + + + +### 获取安装包 + +安装和使用 imageTailor 工具,首先需要下载 openEuler 发布件。 + +1. 获取 ISO 镜像文件和对应的校验文件。 + + 镜像必须为 everything 版本,此处假设存放在 root 目录,参考命令如下: + + ```shell + $ cd /root/temp + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +3. 获取 sha256sum 校验文件中的校验值。 + + ```shell + $ cat openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +4. 计算 ISO 镜像文件的校验值。 + + ```shell + $ sha256sum openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +5. 对比上述 sha256sum 文件的检验值和 ISO 镜像的校验值,如果两者相同,说明文件完整性检验成功。否则说明文件完整性被破坏,需要重新获取文件。 + +### 安装 imageTailor + +此处以 openEuler 22.03 LTS 版本的 AArch64 架构为例,介绍如何安装 imageTailor 工具。 + +1. 确认机器已经安装操作系统 openEuler 22.03 LTS( imageTailor 工具的运行环境)。 + + ```shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. 创建文件 /etc/yum.repos.d/local.repo,配置对应 yum 源。配置内容参考如下,其中 baseurl 是用于挂载 ISO 镜像的目录: + + ```shell + [local] + name=local + baseurl=file:///root/imageTailor_mount + gpgcheck=0 + enabled=1 + ``` + +3. 使用 root 权限,挂载光盘镜像到 /root/imageTailor_mount 目录(请与上述 repo 文件中配置的 baseurl 保持一致,且建议该目录的磁盘空间大于 20 GB)作为 yum 源,参考命令如下: + + ```shell + $ mkdir /root/imageTailor_mount + $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-aarch64-dvd.iso /root/imageTailor_mount/ + ``` + +4. 使 yum 源生效: + + ```shell + $ yum clean all + $ yum makecache + ``` + +5. 使用 root 权限,安装 imageTailor 裁剪工具: + + ```shell + $ sudo yum install -y imageTailor + ``` + +6. 使用 root 权限,确认工具已安装成功。 + + ```shell + $ cd /opt/imageTailor/ + $ sudo ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] + Options: + -p,--product Specify the product to make, check custom/cfg_yourProduct. + -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx + --minios Make minios: yes|no|force + --sec Perform security hardening + -h,--help Display help information + + Example: + command: + ./mkdliso -p openEuler -c custom/cfg_openEuler --sec + + help: + ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + ``` + +### 目录介绍 + +imageTailor 工具安装完成后,工具包的目录结构如下: + +```shell +[imageTailor] + |-[custom] + |-[cfg_openEuler] + |-[usr_file] // 存放用户添加的文件 + |-[usr_install] // 存放用户的 hook 脚本 + |-[all] + |-[conf] + |-[hook] + |-[cmd.conf] // 配置 ISO 镜像默认使用的命令和库 + |-[rpm.conf] // 配置 ISO 镜像默认安装的 RPM 包和驱动列表 + |-[security_s.conf] // 配置安全加固策略 + |-[sys.conf] // 配置 ISO 镜像系统参数 + |-[kiwi] // imageTailor 基础配置 + |-[repos] // RPM 源,制作 ISO 镜像需要的 RPM 包 + |-[security-tool] // 安全加固工具 + |-mkdliso // 制作 ISO 镜像的可执行脚本 +``` + +## 定制系统 + +本章介绍使用 imageTailor 工具将业务 RPM 包、自定义文件、驱动、命令和文件打包至目标 ISO 镜像。 + +### 总体流程 + +使用 imageTailor 工具定制系统的流程请参见下图: + +![](./figures/flowchart.png) + +各流程含义如下: + +- 检查软硬件环境:确认制作 ISO 镜像的机器满足软硬件要求。 + +- 定制业务包:包括添加 RPM 包(包括业务 RPM 包、命令、驱动、库文件)和添加文件(包括自定义文件、命令、驱动、库文件) + + - 添加业务 RPM 包:用户可以根据需要,添加 RPM 包到 ISO 镜像。具体要求请参见 [安装工具](# 安装工具) 章节。 + - 添加自定义文件:若用户希望在目标 ISO 系统安装或启动时,能够进行自定义的硬件检查、系统配置检查、驱动安装等操作,可编写自定义文件,并打包到 ISO 镜像。 + - 添加驱动、命令、库文件:当 openEuler 的 RPM 包源未包含用户需要的驱动、命令或库文件时,可以使用 imageTailor 工具将对应驱动、命令或库文件打包至 ISO 镜像。 + +- 配置系统参数 + + - 配置主机参数:为了确保 ISO 镜像安装和启动成功,需要配置主机参数。 + - 配置分区:用户可以根据业务规划配置业务分区,同时可以调整系统分区。 + - 配置网络:用户可以根据需要配置系统网络参数,例如:网卡名称、IP 地址、子网掩码。 + - 配置初始密码:为了确保 ISO 镜像安装和启动成功,需要配置 root 初始密码和 grub 初始密码。 + - 配置内核参数:用户可以根据需求配置内核的命令行参数。 + +- 配置安全加固策略 + + imageTailor 提供了默认地安全加固策略。用户可以根据业务需要,通过编辑 security_s.conf 对系统进行二次加固(仅在系统 ISO 镜像定制阶段),具体的操作方法请参见 《 [安全加固指南](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/SecHarden/secHarden.html) 》。 + +- 制作操作系统 ISO 镜像 + + 使用 imageTailor 工具制作操作系统 ISO 镜像。 + +### 定制业务包 + +用户可以根据业务需要,将业务 RPM 包、自定义文件、驱动、命令和库文件打包至目标 ISO 镜像。 + +#### 配置本地 repo 源 + +定制 ISO 操作系统镜像,必须在 /opt/imageTailor/repos/euler_base/ 目录配置 repo 源。本节主要介绍配置本地 repo 源的方法。 + +以 openEuler 发布 ISO 的 RPM 包为例。 + +1. 下载 openEuler 发布的 ISO 。 + ```shell + $ cd /opt + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + ``` + +2. 创建挂载目录 /opt/openEuler_repo ,并挂载 ISO 到该目录 。 + ```shell + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + ``` + +3. 拷贝 ISO 中的 RPM 包到 /opt/imageTailor/repos/euler_base/ 目录下。 + ```shell + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +#### 添加文件 + +用户可以根据需要添加文件到 ISO 镜像,此处的文件类型可以是用户自定义文件、驱动、命令、库文件。用户只需要将文件放至 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下即可。 + +##### 注意事项 + +- 命令必须具有可执行权限,否则 imageTailor 工具无法将该命令打包至 ISO 中。 + +- 存放在 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下的文件,会生成在 ISO 根目录下,所以文件的目录结构必须是从根目录开始的完整路径,以便 imageTailor 工具能够将该文件放至正确的目录下。 + + 例如:假设希望文件 file1 在 ISO 的 /opt 目录下,则需要在 usr_file 目录下新建 opt 目录,再将 file1 文件拷贝至 opt 目录。如下: + + ```shell + $ pwd + /opt/imageTailor/custom/cfg_openEuler/usr_file + + $ tree + . + ├── etc + │   ├── default + │   │   └── grub + │   └── profile.d + │   └── csh.precmd + └── opt + └── file1 + + 4 directories, 3 files + ``` + +- 存放在 /opt/imageTailor/custom/cfg_openEuler/usr_file 目录下的目录必须是真实路径(例如路径中不包含软连接。可在系统中使用 `realpath` 或 `readlink -f` 命令查询真实路径)。 + +- 如果需要在系统启动或者安装阶段调用用户提供的脚本,即 hook 脚本,则需要将该文件放在 hook 目录下。 + +#### 添加 RPM 包 + +##### 操作流程 + +用户可以添加 RPM 包(驱动、命令或库文件)到 ISO 镜像,操作步骤如下: + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 下述 rpm.conf 和 cmd.conf 均在 /opt/imageTailor/custom/cfg_openEuler/ 目录下。 +>- 下述 RPM 包裁剪粒度是指 sys_cut='no' 。裁剪粒度详情请参见 [配置主机参数](#配置主机参数) 。 +>- 若没有配置本地 repo 源,请参见 [配置本地 repo 源 ](#配置本地 repo 源)进行配置。 +> + +1. 确认 /opt/imageTailor/repos/euler_base/ 目录中是否包含需要添加的 RPM 包。 + + - 是,请执行步骤 2 。 + - 否,请执行步骤 3 。 +2. 在 rpm.conf 的 \ 字段配置该 RPM 包信息。 + - 若为 RPM 包裁剪粒度,则操作完成。 + - 若为其他裁剪粒度,请执行步骤 4 。 +3. 用户自己提供 RPM 包,放至 /opt/imageTailor/custom/cfg_openEuler/usr_rpm 目录下。如果 RPM 包依赖于其他 RPM 包,也必须将依赖包放至该目录,因为新增 RPM 包需要和依赖 RPM 包同时打包至 ISO 镜像。 + - 若为用户 RPM 包文件裁剪,则执行 4 。 + - 其他裁剪粒度,则操作完成。 +4. 请在 rpm.conf 和 cmd.conf 中配置该 RPM 包中要保留的驱动、命令和库文件。如果有要裁剪的普通文件,需要在 cmd.conf 文件中的 \\ 区域配置。 + + +##### 配置文件说明 + +| 对象 | 对应配置文件 | 填写区域 | +| :----------- | :----------- | :----------------------------------------------------------- | +| 添加驱动 | rpm.conf | \
\
\

说明:其中驱动名称所在路径为 " /lib/modules/{内核版本号}/kernel/ " 的相对路径 | +| 添加命令 | cmd.conf | \
\
\
| +| 添加库文件 | cmd.conf | \
\
\
| +| 删除其他文件 | cmd.conf | \
\
\

说明:普通文件名称必须包含绝对路径 | + +**示例** + +- 添加驱动 + + ```shell + + + + + ...... + + ``` + +- 添加命令 + + ```shell + + + + + ...... + + ``` + +- 添加库文件 + + ```shell + + + + + + ``` + +- 删除其他文件 + + ```shell + + + + + + ``` + +#### 添加 hook 脚本 + +hook 脚本由 OS 在启动和安装过程中调用,执行脚本中定义的动作。imageTailor 工具存放 hook 脚本的目录为 custom/cfg_openEuler/usr_install/hook,且其下有不同子目录,每个子目录代表 OS 启动或安装的不同阶段,用户根据脚本需要被调用的阶段存放,OS 会在对应阶段调用该脚本。用户可以根据需要存放自定义脚本到指定目录。 + +##### **脚本命名规则** + +用户可自定义脚本名称,必须 "S+数字(至少两位,个位数以0开头)" 开头,数字代表 hook 脚本的执行顺序。脚本名称示例:S01xxx.sh + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>hook 目录下的脚本是通过 source 方式调用,所以脚本中需要谨慎使用 exit 命令,因为调用 exit 命令之后,整个安装的脚本程序也同步退出了。 + + + +##### hook 子目录说明 + +| hook 子目录 | hook 脚本举例 | hook 执行点 | 说明 | +| :-------------------- | :---------------------| :------------------------------- | :----------------------------------------------------------- | +| insmod_drv_hook | 无 | 加载 OS 驱动之后 | 无 | +| custom_install_hook | S01custom_install.sh | 驱动加载完成后(即 insmod_drv_hook 执行后) | 用户可以自定义安装过程,不需要使用 OS 默认安装流程。 | +| env_check_hook | S01check_hw.sh | 安装初始化之前 | 初始化之前检查硬件配置规格、获取硬件类型。 | +| set_install_ip_hook | S01set_install_ip.sh | 安装初始化过程中,配置网络时 | 用户根据自身组网,自定义网络配置。 | +| before_partition_hook | S01checkpart.sh | 在分区前调用 | 用户可以在分区之前检查分区配置文件是否正确。 | +| before_setup_os_hook | 无 | 解压repo之前 | 用户可以进行自定义分区挂载操作。
如果安装包解压的路径不是分区配置中指定的根分区。则需要用户自定义分区挂载,并将解压路径赋值给传入的全局变量。 | +| before_mkinitrd_hook | S01install_drv.sh | 执行 mkinitrd 操作之前 | initrd 放在硬盘的场景下,执行 mkinitrd 操作之前的 hook。用户可以进行添加、更新驱动文件等自定义操作。 | +| after_setup_os_hook | 无 | 安装完系统之后 | 用户可以在安装完成之后进行系统文件的自定义操作,包括修改 grub.cfg 等 | +| install_succ_hook | 无 | 系统安装流程成功结束 | 用户执行解析安装信息,回传安装是否成功等操作。install_succ_hook 不可以设置为 install_break。 | +| install_fail_hook | 无 | 系统安装失败 | 用户执行解析安装信息,回传安装是否成功等操作。install_fail_hook 不可以设置为 install_break。 | + +### 配置系统参数 + +开始制作操作系统 ISO 镜像之前,需要配置系统参数,包括主机参数、初始密码、分区、网络、编译参数和系统命令行参数。 + +#### 配置主机参数 + + /opt/imageTailor/custom/cfg_openEuler/sys.conf 文件的 \ \ 区域用于配置系统的常用参数,例如主机名、内核启动参数等。 + +openEuler 提供的默认配置如下,用户可以需要进行修改: + +```shell + + sys_service_enable='ipcc' + sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' + sys_utc='yes' + sys_timezone='' + sys_cut='no' + sys_usrrpm_cut='no' + sys_hostname='Euler' + sys_usermodules_autoload='' + sys_gconv='GBK' + +``` + +配置中的各参数含义如下: + +- sys_service_enable + + 可选配置。OS 默认启用的服务,多个服务请以空格分开。如果用户不需要新增系统服务,请保持默认值,默认值为 ipcc 。配置时请注意: + + - 只能在默认配置的基础上增加系统服务,不能删减系统服务。 + - 可以配置业务相关的服务,但是需要 repo 源中包含业务 RPM 包。 + - 默认只开启该参数中配置的服务,如果服务依赖其他服务,需要将被依赖的服务也配置在该参数中。 + +- sys_service_disable + + 可选配置。禁止服务开机自启动的服务,多个服务请以空格分开。如果用户没有需要禁用的系统服务,请修改该参数为空。 + +- sys_utc + + 必选配置。是否采用 UTC 时间。yes 表示采用,no 表示不采用,默认值为 yes 。 + +- sys_timezone + + 可选配置。设置时区,即该单板所处的时区。可配置的范围为 openEuler 支持的时区,可通过 /usr/share/zoneinfo/zone.tab 文件查询。 + +- sys_cut + + 必选配置。是否裁剪 RPM 包。可配置为 yes、no 或者 debug 。yes 表示裁剪,no 表示不裁剪(仅安装 rpm.conf 中的 RPM 包),debug 表示裁剪但会保留 `rpm` 命令方便安装后定制。默认值为 no 。 + + > ![](.\public_sys-resources\icon-note.gif)说明: + > + > - imageTailor 工具会先安装用户添加的 RPM 包,再删除 cmd.conf + > 中 \ 区域的文件,最后删除 + > cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。 + > - sys_cut='yes' 时,imageTailor 工具不支持 `rpm` 命令的安装,即使在 rpm.conf 中配置了也不生效。 + +- sys_usrrpm_cut + + 必选配置。是否裁剪用户添加到 /opt/imageTailor/custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。yes 表示裁剪,no 表示不裁剪。默认值为 no 。 + + - sys_usrrpm_cut='yes' :imageTailor 工具会先安装用户添加的 RPM 包,然后删除 cmd.conf 中 \ 区域配置的文件,最后删除 cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。 + + - sys_usrrpm_cut='no' :imageTailor 工具会安装用户添加的 RPM 包,不删除用户 RPM 包中的文件。 + +- sys_hostname + + 必选配置。主机名。大批量部署 OS 时,部署成功后,建议修改每个节点的主机名,确保各个节点的主机名不重复。 + + 主机名要求:字母、数字、"-" 的组合,首字母必须是字母或数字。字母支持大小写。字符个数不超过 63 。默认值为 Euler 。 + +- sys_usermodules_autoload + + 可选配置。系统启动阶段加载的驱动,配置该参数时,不需要填写后缀 .ko 。如果有多个驱动,请以空格分开。默认为空,不加载额外驱动。 + +- sys_gconv + + 可选配置。该参数用于定制 /usr/lib/gconv, /usr/lib64/gconv ,配置取值为: + + - null/NULL:表示不配置。如果裁剪系统(sys_cut=“yes”),则/usr/lib/gconv 和 /usr/lib64/gconv 会被删除。 + - all/ALL:不裁剪 /usr/lib/gconv 和 /usr/lib64/gconv 。 + - xxx,xxx: 保留 /usr/lib/gconv 和 /usr/lib64/gconv 目录下对应的文件。若需要保留多个文件,可用 "," 分隔。 + +- sys_man_cut + + 可选配置。配置是否裁剪 man 文档。yes 表示裁剪,no 表示不裁剪。默认值为 yes 。 + + + +> ![](.\public_sys-resources\icon-note.gif)说明: +> +> sys_cut 和 sys_usrrpm_cut 同时配置时,sys_cut 优先级更高,即遵循如下原则: +> +> - sys_cut='no' +> +> 无论 sys_usrrpm_cut='no' 还是 sys_usrrpm_cut='yes' ,都为系统 RPM 包裁剪粒度,即imageTailor 会安装 repo 源中的 RPM 包和 usr_rpm 目录下的 RPM 包,但不会裁剪 RPM 包中的文件。即使用户不需要这些 RPM 包中的部分文件,imageTailor 也不会进行裁剪。 +> +> - sys_cut='yes' +> +> - sys_usrrpm_cut='no' +> +> 系统 RPM 包文件裁剪粒度:imageTailor 会根据用户配置,裁剪 repo 源中 RPM 包的文件。 +> +> - sys_usrrpm_cut='yes' +> +> 系统和用户 RPM 包文件裁剪粒度:imageTailor 会根据用户的配置,裁剪 repo 源和 usr_rpm 目录中 RPM 包的文件。 +> + + + +#### 配置初始密码 + +操作系统安装时,必须具有 root 初始密码和 grub 初始密码,否则裁剪得到的 ISO 在安装后无法使用 root 账号进行登录。本节介绍配置初始密码的方法。 + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> root 初始密码和 grub2 初始密码,必须由用户自行配置。 + +##### 配置 root 初始密码 + +###### 简介 + +root 初始密码保存在 "/opt/imageTailor/custom/cfg_openEuler/rpm.conf" 中,用户通过修改该文件配置 root 初始密码。 + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 若使用 `mkdliso` 命令制作 ISO 镜像时需要使用 --minios yes/force 参数(制作在系统安装时进行系统引导的 initrd),则还需要在 /opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf 中填写相应信息。 + +/opt/imageTailor/custom/cfg_openEuler/rpm.conf 中 root 初始密码的默认配置如下,需要用户自行添加: + +``` + + + +``` + +各参数含义如下: + +- group:用户所属组。 +- pwd:用户初始密码的加密密文,加密算法为 SHA-512。${pwd} 需要替换成用户实际的加密密文。 +- home:用户的家目录。 +- name:需要配置用户的用户名。 + +###### 修改方法 + +用户在制作 ISO 镜像前需要修改 root 用户的初始密码,这里给出设置 root 初始密码的方法(需使用 root 权限): + +1. 添加用于生成密码的用户,此处假设 testUser。 + + ```shell + $ sudo useradd testUser + ``` + +2. 设置 testUser 用户的密码。参考命令如下,根据提示设置密码: + + ```shell + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. 查看 /etc/shadow 文件,testUser 后的内容(两个 : 间的字符串)即为加密后的密码。 + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: + ``` + +4. 拷贝上述加密密码替换 /opt/imageTailor/custom/cfg_openEuler/rpm.conf 中的 pwd 字段,如下所示: + ``` shell script + + + + ``` + +5. 若使用 `mkdliso` 命令制作 ISO 镜像时需要使用 --minios yes/force 参数,请修改 /opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf 中对应用户的 pwd 字段。 + + ``` shell script + + + + ``` + +##### 配置 grub2 初始密码 + +grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub2 初始密码。如果未配置 grub2 初始密码,制作 ISO 镜像会失败。 + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> - 配置 gurb2 初始密码需要使用 root 权限。 +> - grub2 密码对应的默认用户为 root 。 +> +> - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 + +1. 执行如下命令,根据提示设置 grub2 密码: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 + ``` + +3. 复制上述密文,并在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 文件中增加如下配置: + + ```shell + GRUB_PASSWORD="grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615" + ``` + + +#### 配置分区 + +若用户想调整系统分区或业务分区,可以通过修改 /opt/imageTailor/custom/cfg_openEuler/sys.conf 文件中的 \ 实现。 + +>![](./public_sys-resources/icon-note.gif) **说明:** +> +>- 系统分区:存放操作系统的分区 +>- 业务分区:存放业务数据的分区 +>- 差别:在于存放的内容,而每个分区的大小、挂载路径和文件系统类型都不是区分业务分区和系统分区的依据。 +>- 配置分区为可选项,用户也可以在安装 OS 之后,手动配置分区 + + \ 的配置格式为: + +hd 磁盘号 挂载路径 分区大小 分区类型 文件系统类型 [二次格式化标志位] + +其默认配置如下: + +``` shell script + +hd0 /boot 512M primary ext4 yes +hd0 /boot/efi 200M primary vfat yes +hd0 / 30G primary ext4 +hd0 - - extended - +hd0 /var 1536M logical ext4 +hd0 /home max logical ext4 + +``` + +各参数含义如下: + +- hd 磁盘号 + 磁盘的编号。请按照 hdx 的格式填写,x 指第 x 块盘。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >分区配置只在被安装机器的磁盘能被识别时才有效。 + +- 挂载路径 + 指定分区挂载的路径。用户既可以配置业务分区,也可以对默认配置中的系统分区进行调整。如果不挂载,则设置为 '-'。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >- 分区配置中必须有 '/' 挂载路径。其他的请用户自行调整。 + >- 采用 UEFI 引导时,在 x86_64 的分区配置中必须有 '/boot' 挂载路径,在 AArch64 的分区配置中必须有 '/boot/efi' 挂载路径。 + +- 分区大小 + 分区大小的取值有以下四种: + + - G/g:指定以 GB 为单位的分区大小,例如:2G。 + - M/m:指定以 MB 为单位的分区大小,例如:300M。 + - T/t:指定以 TB 为单位的分区大小,例如:1T。 + - MAX/max:指定将硬盘上剩余的空间全部用来创建一个分区。只能在最后一个分区配置该值。 + + >![](./public_sys-resources/icon-note.gif) **说明:** +> + >- 分区大小不支持小数,如果是小数,请换算成其他单位,调整为整数的数值。例如:不能填写 1.5G,应填写为 1536M。 + >- 分区大小取 MAX/max 值时,剩余分区大小不能超过支持文件系统类型的限制(默认文件系统类型 ext4,限制大小 16T)。 + +- 分区类型 + 分区有以下三种: + + - 主分区: primary + - 扩展分区:extended(该分区只需配置 hd 磁盘号即可) + - 逻辑分区:logical + +- 文件系统类型 + 目前支持的文件系统类型有:ext4、vfat + +- 二次格式化标志位 + 可选配置,表示二次安装时是否格式化: + + - 是:yes + - 否:no 。不配置默认为 no 。 + + >![](./public_sys-resources/icon-note.gif) **说明:** + > + >二次格式化是指本次安装之前,磁盘已安装过 openEuler 系统。当前一次安装跟本次安装的使用相同的分区表配置(分区大小,挂载点,文件类型)时,该标志位可以配置是否格式化之前的分区,'/boot' 和 '/' 分区除外,每次都会重新格式化。如果目标机器第一次安装,则该标志位不生效,所有指定了文件系统的分区都会进行格式化。 + +#### 配置网络 + +系统网络参数保存在 /opt/imageTailor/custom/cfg_openEuler/sys.conf 中,用户可以通过该文件的\\ 配置修改目标 ISO 镜像的网络参数,例如:网卡名称、IP地址、子网掩码。 + +sys.conf 中默认的网络配置如下,其中 netconfig-0 代表网卡 eth0。如果需要配置多块网卡,例如eth1,请在配置文件中增加 \\,并在其中填写网卡 eth1 的各项参数。 + +```shell + +BOOTPROTO="dhcp" +DEVICE="eth0" +IPADDR="" +NETMASK="" +STARTMODE="auto" + +``` + +各参数含义请参见下表: + +- | 参数名称 | 是否必配 | 参数值 | 说明 | + | :-------- | -------- | :------------------------------------------------ | :----------------------------------------------------------- | + | BOOTPROTO | 是 | none / static / dhcp | none:引导时不使用协议,不配地址
static:静态分配地址
dhcp:使用 DHCP 协议动态获取地址 | + | DEVICE | 是 | 如:eth1 | 网卡名称 | + | IPADDR | 是 | 如:192.168.11.100 | IP 地址
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | + | NETMASK | 是 | - | 子网掩码
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | + | STARTMODE | 是 | manual / auto / hotplug / ifplugd / nfsroot / off | 启用网卡的方法:
manual:用户在终端执行 ifup 命令启用网卡。
auto \ hotplug \ ifplug \ nfsroot:当 OS 识别到该网卡时,便启用该网卡。
off:任何情况下,网卡都无法被启用。
各参数更具体的说明请在制作 ISO 镜像的机器上执行 `man ifcfg` 命令查看。 | + + +#### 配置内核参数 + +为了系统能够更稳定高效地运行,用户可以根据需要修改内核命令行参数。imageTailor 工具制作的 OS 镜像,可以通过修改 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中的 GRUB_CMDLINE_LINUX 配置实现内核命令行参数修改。 GRUB_CMDLINE_LINUX 中内核命令行参数的默认配置如下: + +```shell +GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" +``` + +此处各配置含义如下(其余常见的内核命令行参数请查阅内核相关文档): + +- net.ifnames=0 biosdevname=0 + + 以传统方式命名网卡。 + +- crashkernel=512M + + 为 kdump 预留的内存空间大小为 512 MB。 + +- oops=panic panic=3 + + 内核 oops 时直接 panic,并且 3 秒后重启系统。 + +- softlockup_panic=1 + + 在检测到软死锁(soft-lockup)时让内核 panic。 + +- reserve_kbox_mem=16M + + 为 kbox 预留的内存空间大小为 16 MB。 + +- console=tty0 + + 指定第一个虚拟控制台的输出设备为 tty0。 + +- crash_kexec_post_notifiers + + 系统 crash 后,先调用注册到 panic 通知链上的函数,再执行 kdump。 + +### 制作系统 + +操作系统定制完成后,可以通过 mkdliso 脚本制作系统镜像文件。 imageTailor 制作的 OS 为 ISO 格式的镜像文件。 + +#### 命令介绍 + +##### 命令格式 + +**mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h]** + +##### 参数说明 + +| 参数名称 | 是否必选 | 参数含义 | 取值范围 | +| -------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| -p | 是 | 设置产品名称 | openEuler | +| c | 是 | 指定配置文件的相对路径 | custom/cfg_openEuler | +| --minios | 否 | 制作在系统安装时进行系统引导的 initrd | 默认为 yes
yes:第一次执行命令时会制作 initrd,之后执行命令会判断 'usr_install/boot'
目录下是否存在 initrd(sha256 校验)。如果存在,就不重新制作 initrd,否则制作 initrd 。
no:不制作 initrd,采用原有方式,系统引导和运行使用的 initrd 相同。
force:强制制作 initrd,不管 'usr_install/boot' 目录下是否存在 initrd。 | +| --sec | 否 | 是否对生成的 ISO 进行安全加固
如果用户不输入该参数,则由此造成的安全风险由用户承担 | 无 | +| -h | 否 | 获取帮助信息 | 无 | + +#### 制作指导 + +使用 mkdliso 制作 ISO 镜像的操作步骤如下: + +> ![](.\public_sys-resources\icon-note.gif)说明: +> +> - mkdliso 所在的绝对路径中不能有空格,否则会导致制作 ISO 失败。 +> - 制作 ISO 的环境中,umask 的值必须设置为 0022。 + +1. 使用 root 权限,执行 mkdliso 命令,生成 IOS 镜像文件。参考命令如下: + + ```shell + # sudo /opt/imageTailor/mkdliso -p openEuler -c custom/cfg_openEuler --sec + ``` + + 命令执行完成后,制作出的新文件在 /opt/imageTailor/result/{日期} 目录下,包括 openEuler-aarch64.iso 和 openEuler-aarch64.iso.sha256 。 + +2. 验证 ISO 镜像文件的完整性。此处假设日期为 2022-03-21-14-48 。 + + ```shell + $ cd /opt/imageTailor/result/2022-03-21-14-48/ + $ sha256sum -c openEuler-aarch64.iso.sha256 + ``` + + 回显如下,表示 ISO 镜像文件完整,ISO 制作完成。 + + ``` + openEuler-aarch64.iso: OK + ``` + + 若回显如下,表示镜像不完整,说明 ISO 镜像文件完整性被破坏,需要重新制作。 + + ```shell + openEuler-aarch64.iso: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + +3. 查看日志 + + 镜像制作完成后,可以根据需要(例如制作出错时)查看日志。第一次制作镜像时,对应的日志和安全加固日志被压缩为一个 tar 包(日志的命名格式为:sys_custom_log_{*日期* }.tar.gz),存放在 result/log 目录下。该目录只保留最近时间的 50 个日志压缩包,超过 50 个时会对旧文件进行覆盖。 + + + +### 裁剪时区 + +定制完成的 ISO 镜像安装后,用户可以根据需求裁剪 openEuler 系统支持的时区。本节介绍裁剪时区的方法。 + +openEuler 操作系统支持的时区信息存放在时区文件夹 /usr/shre/zoninfo 下,可通过如下命令查看: + +```shell +$ ls /usr/share/zoneinfo/ +Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ +Pacific/ zone.tab +``` + +其中每个子文件夹代表一个 Area ,当前 Area 包括:大陆、海洋以及 Etc 。每个 Area 文件夹内部则包含了隶属于其的 Location 。一个 Location 一般为一座城市或者一个岛屿。 + +所有时区均以 Area/Location 的形式来表示,比如中国大陆南部使用北京时间,其时区为 Asia/Shanghai(Location 并不一定会使用首都)。对应的,其时区文件为: + +``` +/usr/share/zoneinfo/Asia/Shanghai +``` + +若用户希望裁剪某些时区,则只需将对应的时区文件删除即可。 + +### 定制示例 + +本节给出使用 imageTailor 工具定制一个 ISO 操作系统镜像的简易方案,方便用户了解制作的整体流程。 + +1. 检查制作 ISO 所在环境是否满足要求。 + + ``` shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. 确保根目录有 40 GB 以上空间。 + + ```shell + $ df -h + Filesystem Size Used Avail Use% Mounted on + ...... + /dev/vdb 196G 28K 186G 1% / + ``` + +3. 安装 imageTailor 裁剪工具。具体安装方法请参见 [安装工具](#安装工具) 章节。 + + ```shell +$ sudo yum install -y imageTailor + $ ll /opt/imageTailor/ + total 88K + drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom + drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi + -r-x------. 1 root root 69K Mar 3 08:00 mkdliso + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool + ``` + +4. 配置本地 repo 源。 + + ```shell +$ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +5. 修改 grub/root 密码 + + 以下 ${pwd} 的实际内容请参见 [配置初始密码](#配置初始密码) 章节生成并替换。 + + ```shell + $ cd /opt/imageTailor/ + $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub + GRUB_PASSWORD="${pwd1}" + $ + $ sudo vi kiwi/minios/cfg_minios/rpm.conf + + + + $ + $ sudo vi custom/cfg_openEuler/rpm.conf + + + + ``` + +6. 执行裁剪命令。 + + ```shell + $ sudo rm -rf /opt/imageTailor/result + $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force + ...... + Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso + move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz + $ ll result/2022-03-09-15-31/ + total 889M + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 + ``` + + diff --git "a/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" deleted file mode 100644 index c918c59d2..000000000 --- "a/docs/zh/docs/TailorCustom/imageTailor\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ /dev/null @@ -1,884 +0,0 @@ -# imageTailor 使用指南 - -- [1. 概述](#1、概述) - - [1.1 背景介绍](#1.1、背景介绍) - - [1.2 功能介绍](#1.2、功能介绍) -- [2. 发布包介绍](#2、发布包介绍) - - [2.1 获取发布包](#2.1、获取发布包) - - [2.2 安装 imageTailor 工具](#2.2、安装imageTailor工具) - - [2.3 imageTailor 包目录介绍](#2.3、imageTailor包目录介绍) -- [3. 定制 OS](#3、定制OS) - - [3.1 使用流程](#3.1、使用流程) - - [3.2 检查软硬件环境](#3.2、检查软硬件环境) - - [3.3 定制业务包](#3.3、定制业务包) - - [3.4 配置系统参数](#3.4、配置系统参数) - - [3.5 制作 OS](#3.5、制作OS) - - [3.6 时区裁剪](#3.6、时区裁剪) - - [3.7 裁剪流程使用实例](#3.7、裁剪流程使用实例) - -## 1、概述 -介绍 imageTailor 是操作系统镜像文件级裁剪定制工具,该工具是基于开源软件 kiwi 进行功能增强开发,实现了多种裁剪定制功能, -包括系统包裁剪定制、系统配置裁剪定制、用户文件定制等,最后通过 cdrkit 生成 iso 格式的镜像文件。 - -### 1.1、背景介绍 -操作系统除内核外,还包含大量提供各种功能的外围包。因此,通用的操作系统功能较多,占用资源多,这带来了两方面的影响: - -- 大量占用有限的内存、磁盘、CPU 等资源,导致系统运行低效。 -- 很多功能客户不会使用,增加开发和维护成本。 - -OS 定制特性正是基于这样的现状提出。openEuler 提供 imageTailor 定制工具,根据客户的需求量身打造操作系统。用户可裁剪不需要的外围包,还可以添加自己的业务包。 - -### 1.2、功能介绍 - -#### 1.2.1、基本功能 -imageTailor 裁剪定制工具为用户提供以下功能: - -- 系统包裁剪定制:用户可选择默认安装的 RPM,定制裁剪系统命令、库、驱动。 -- 系统配置定制:可以配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、版本号。 -- 用户软件包定制:将用户的 RPM 包安装到系统中,将用户文件定制到系统中。 - -#### 1.2.2、基本概念 - -- 驱动:硬件驱动,为内核模块(后缀名为 ko)。一般是硬件部门将自己开发的驱动添加进 OS 中。驱动存放于 /lib/modules/{内核版本号}/kernel/ 目录下。 -- 命令:可执行文件,用户定制的命令可以是标准 openEuler 自带的,也可以是用户自己开发的。只有当可执行文件位于 /bin、/sbin、/usr/bin 或 /usr/sbin 时,才会被 imageTailor 工具识别为命令,如果是放在其他目录下,则被视为普通的文件。 -- 库:库是一种可执行程序的二进制形式,可以被操作系统载入内存执行。它是别人已写好的、可复用的代码。库文件一般存放在 /lib、/lib64、/usr/lib/、/usr/lib64、/usr/X11R6/lib 或 /usr/X11R6/lib64 目录下,统一以 lib 开头,格式为 libxxx。 -- 自定义文件:这里可以是安装脚本、配置脚本或其他文件。imageTailor 工具对自定义文件不做任何限制,只要是用户自己提供的文件,imageTailor 都默认打包至 OS 中。 -- RPM:RPM 包可以简单的理解为 linux 环境中的软件包。具体说来,一个 RPM 包就是能够让应用软件运行的全部文件的集合,它记录了二进制软件的内容、安装的位置、软件包的描述信息、软件包之间的依赖关系等信息。linux 中安装和卸载 RPM 包都有对应的命令。 - - -## 2、发布包介绍 - -### 2.1、获取发布包 -用户需下载 openEuler 发布包。 - -1. 获取 openEuler 发布包 - - AArch64 架构的镜像下载链接为: - ``` - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso - - eg: - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso - ``` - - > **说明:** - > x86_64 架构的镜像下载链接为: - > - > http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - -2. 校验发布包完整性 - - 1. 以 openEuler-22.03-LTS-aarch64-dvd.iso 为例。 - - 2. 下载 iso 到制作 OS 的机器上,并下载与 iso 同名的 sha256sum 文件(此处为 openEuler-22.03-LTS-x86_64-dvd.iso.sha256sum) - ``` - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso.sha256sum - ``` - - 3. 获取 sha256 文件中的校验值;计算 openEuler-22.03-LTS-aarch64-dvd.iso 的 sha256 值。 - ``` - $ cat openEuler-22.03-LTS-aarch64-dvd.iso.sha256sum - d22787ac209e544bb43c08f7c44f54373cafb79430e7fcae3d488d197f73793a openEuler-22.03-LTS-aarch64-dvd.iso - $ sha256sum openEuler-22.03-LTS-aarch64-dvd.iso - d22787ac209e544bb43c08f7c44f54373cafb79430e7fcae3d488d197f73793a openEuler-22.03-LTS-aarch64-dvd.iso - ``` - - 4. 对比以上两个计算的校验值是否一致。不一致说明文件完整性已被破坏,需要重新获取。 - - -### 2.2、安装imageTailor工具 - -此处以 openEuler 22.03 LTS 版本的 x86_64 架构为例,介绍 imageTailor 裁剪工具的安装操作 - -1. 确认机器已经安装操作系统 openEuler 22.03 LTS(imageTailor 裁剪工具的运行环境) - - ``` - $ cat /etc/openEuler-release - openEuler release 22.03 LTS - ``` - -2. 下载对应架构的 ISO 镜像(必须是 everything 版本),并存放在任一目录(建议该目录磁盘空间大于 20 GB),此处假设存放在 /root/imageTailor_mount 目录。 - - x86_64 架构的镜像下载链接为: - ``` - http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-{时间版本}/ISO/x86_64/openEuler-22.03-LTS-everything-x86_64-dvd.iso - ``` - 其他详细下载链接参考 2.1、获取发布包 - -3. 创建文件 /etc/yum.repos.d/local.repo,配置对应 yum 源。配置内容参考如下,其中 baseurl 是用于挂载 ISO 镜像的目录: - - ``` - [local] - name=local - baseurl=file:///root/imageTailor_mount - gpgcheck=0 - enabled=1 - ``` - -4. 使用 root 权限,挂载光盘镜像到 /root/imageTailor_mount 目录(请与上述 repo 文件中配置的 baseurl 保持一致)作为 yum 源,参考命令如下: - - ``` - $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-x86_64-dvd.iso /root/imageTailor_mount/ - mount: /root/imageTailor_mount: WARNING: source write-protected, mounted read-only. - ``` - -5. 使 yum 源生效: - - ``` - yum clean all - yum makecache - ``` - -6. 使用 root 权限,安装 imageTailor 裁剪工具: - - ```shell - sudo yum install -y imageTailor - ``` - -7. 使用 root 权限,确认工具已安装成功。 - - ``` - $ cd /opt/imageTailor/ - $ sudo ./mkdliso -h - ------------------------------------------------------------------------------------------------------------- - Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] - Options: - -p,--product Specify the product to make, check custom/cfg_yourProduct. - -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx - --minios Make minios: yes|no|force - --sec Perform security hardening - -h,--help Display help information - - Example: - command: - ./mkdliso -p openEuler -c custom/cfg_openEuler --sec - - help: - ./mkdliso -h - ------------------------------------------------------------------------------------------------------------- - $ - ``` - -### 2.3、imageTailor包目录介绍 -imageTailor 工具包含用户需要的 RPM 包源、imageTailor 定制工具和用户的配置文件。工具包部分目录结构如下: - - ``` - [imageTailor] - |-[custom] - |-[cfg_openEuler] - |-[usr_file] // 存放用户添加的文件 - |-[usr_install] // 存放用户的 hook 脚本 - |-[all] - |-[conf] - |-[hook] - |-[cmd.conf] // 配置 OS 默认使用的命令和库 - |-[rpm.conf] // 配置 OS 默认安装的 RPM 包和驱动列表 - |-[security_s.conf] // 配置安全加固策略 - |-[sys.conf] // 配置 OS 系统参数 - |-[kiwi] // imageTailor 基础配置 - |-[repos] // RPM 源,制作 OS 需要的 RPM 包 - |-[security-tool] // 安全加固工具 - |-mkdliso // 制作 OS 的可执行脚本 - ``` - -## 3、定制OS -使用 imageTailor 工具将业务 RPM 包、自定义文件、驱动、命令和文件打包至 OS 中,制作出 OS。 - -### 3.1、使用流程 - -定制工具的使用流程为:获取发布包、检查软硬件环境、定制业务包、配置系统参数和制作 OS。 - -使用定制工具进行 OS 定制的流程请参见 图1 -- 图1 定制工具使用流程图 - - ![](./public_sys-resources/flowchart.png) - -步骤说明如 表1 -- 表1 定制步骤说明 - - | 步骤 | | 说明 | - | :--- | :--- | :--- | - | 检查软硬件环境 | |了解制作 OS 的机器需要满足的软硬件要求。 | - | 定制业务包 | 添加业务 RPM 包 | 当用户希望同时部署业务和 OS,可以将业务 RPM 包打包至 OS 中。如果是用户自己提供的 RPM 包,请放在 custom/cfg_openEuler/usr_rpm 目录下。 | - | | 添加自定义文件 | 当用户希望 OS 在安装或启动时,能够进行硬件检查、系统配置检查、安装驱动或其他操作,可编写自定义文件,并将该文件打包至 OS 中。 | - | | 添加驱动 | 当 openEuler 的 RPM 包源未包含用户需要的驱动时,可以使用 imageTailor 工具将该驱动打包至 OS 中。 | - | | 添加命令 | 当 openEuler 的 RPM 包源未包含用户需要的命令时,可以使用 imageTailor 工具将该命令打包至 OS 中。 | - | 定制业务包 | 添加库文件 | 当 openEuler 的 RPM 包源未包含用户需要的库文件时,可以使用 imageTailor 工具将该库文件打包至 OS 中。 | - | 配置系统参数 | 配置主机参数 | 为了确保 OS 安装和启动成功,需要配置主机参数。 | - | | 配置分区 | 用户可以根据业务规划配置业务分区,同时可以调整系统分区。 | - | | 配置网络 | 根据产品的组网情况,配置网络参数,例如:网卡名称、IP 地址、子网掩码。 | - | 配置系统参数 | 配置编译参数 | 当用户希望 imageTailor 工具先编译代码,再将其添加至 OS 中,则需要配置编译参数。 | - | 配置安全加固策略 | | openEuler 发布给产品时已进行安全加固,满足公司安全规定。产品如果需要根据业务情况进行二次加固,只能在定制阶段进行,编辑 security_s.conf 进行安全加固。具体操作请参见安全加固操作指南。 | - | 制作OS | | 使用 imageTailor 工具提供的脚本制作 OS。 | - -### 3.2、检查软硬件环境 - -为了确保 OS 定制成功,用于制作 OS 的机器需要满足一定的软硬件要求 -- 机器架构为 x86_64 或者 AArch64 -- 操作系统为 openEuler 22.03 LTS - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- openEuler 22.03 满足 python 3.9 与 kernel 5.10 要求 - -- python 版本 3.9 以上 -- kernel 内核版本 5.10 以上 -- 用户裁剪机器根目录 '/' 需要 40 GB 以上空间 -- 关闭 SElinux 服务 - ``` - $ sudo setenforce 0 - $ getenforce - Permissive - ``` - -### 3.3、定制业务包 - -用户可以根据业务需要,将业务 RPM 包、自定义文件、驱动、命令和库文件打包至 OS 中。 - -#### 3.3.1、操作指导 - -用户要添加驱动、命令、库文件和脚本,可能是文件的形式,也可能是 RPM 包的形式。不同的形式有不同的定制方法。 - -1. 添加文件 - - 这里的文件可以是驱动、命令、库文件,也可以是脚本。用户只需将文件放至 custom/cfg_openEuler/usr_file 目录下即可。 - - **注意事项**: - - - 命令必须具有可执行权限,否则 imageTailor 工具无法将该命令打包至 OS 中。 - - - 在 custom/cfg_openEuler/usr_file 目录下放置文件时,文件的目录结构必须是从根目录开始的完整目录,以便 imageTailor 工具能够将该文件放至正确的目录下。 - - 例如:用户希望文件 file1 最终能放至 /opt 目录下,则需要在 usr_file 目录下新建 opt 目录,再将 file1 文件拷贝至 opt 目录。如下: - - ``` - $ tree - . - ├── etc - │   ├── default - │   │   └── grub - │   └── profile.d - │   └── csh.precmd - └── opt - └── file1 - - 4 directories, 3 files - & pwd - /opt/imageTailor/custom/cfg_openEuler/usr_file - ``` - - - 上述说的目录需要是系统中的真实路径(路径中不含软链接,可在系统中使用 realpath 或 readlink -f 命令查询真实路径)。 - - - 在 usr_file 新建目录时,若是系统中已有的目录,新建的目录权限需要和系统中目录权限保持一致,不然会导致 usr_file 下目录权限覆盖系统中目录的权限,可能导致系统问题。在添加目录之前请确定系统中目录的权限。 - - - 如果用户自己提供的脚本希望由 OS 在启动和安装阶段调用,即为 hook 脚本,需要将其放在 hook 目录下。 - -2. 添加 RPM 包 - - 1. 确认 repos 源中是否包含该 RPM 包。 - - 有,请执行 3 - - 无,请执行 2 - 2. 用户自己提供 RPM 包,放至 custom/cfg_openEuler/usr_rpm 目录下。如果 RPM 包依赖于其他 RPM 包,也必须将依赖包打包至 OS 中。 - 请用户根据采用哪种裁剪粒度,来执行后续的操作。 - - 用户 RPM 包文件裁剪,则执行 4 - - 其他裁剪粒度,则操作完成。 - 3. 在 rpm.conf 的 \ 字段配置该 RPM 包信息。请用户根据采用哪种裁剪粒度,来执行后续的操作。 - - RPM 包裁剪粒度,则操作完成 - - 其他裁剪粒度,则执行 4 - 4. 在 cmd.conf 和 rpm.conf 中配置该 RPM 包中要保留的驱动、命令和库文件。如果有要裁剪的普通文件,也需要在 cmd.conf 文件中配置。 - -3. 表 配置文件填写说明 - -- 表 配置文件填写说明 - - | 对象 | 操作 | 需要填写的配置文件 | 填写的区域 | 填写方法 | 注意事项 | 填写示例 | - | :--- | :--- | :--- |:--- | :--- | :--- | :--- | - | 驱动 | 保留 | custom/cfg_openEuler/rpm.conf | \\ | 新增一行 \ | 填写驱动名称时请填写相对于 "/lib/modules/{内核版本号}/kernel/" 的相对路径。 | 如下 图1 | - | 命令 | 保留 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写命令名称。 | 如下 图2 | - | 库文件 | 保留 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写库文件名称。 | 如下 图3 | - | 其他文件 | 删除 | custom/cfg_openEuler/cmd.conf | \\ | 新增一行 \ | 填写普通文件名称,请填写绝对路径。 | 如下 图4 | - -- 图1 drivers 填写示例 - - ![](./public_sys-resources/drivers.png) - -- 图2 tools 填写示例 - - ![](./public_sys-resources/tools.png) - -- 图3 libs 填写示例 - - ![](./public_sys-resources/libs.png) - -- 图4 delete 填写示例 - - ![](./public_sys-resources/delete.PNG) - - -#### 3.3.2、定制示例:添加驱动 - -1. 用户场景 - - 当 imageTailor 默认配置中会裁剪部分驱动,而用户又希望添加 repos 源中的某款硬件驱动至 OS 中。 - -2. 操作步骤 - - 由于该硬件驱动已经在 repos 源中,因此用户只需将其填写配置在 rpm.conf 中即可,避免被 imageTailor 裁剪掉。 - - 1. 在 custom/cfg_openEuler/rpm.conf 中的 \\ 区域添加该驱动信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - - 2. (可选)当用户希望 OS 在启动时自动加载驱动,则需要配置 sys.conf 文件。 - - 具体操作请参见 表 《sysconfig 系统参数说明》 中的 sys_usermodules_autoload 参数。 - -#### 3.3.3、定制实例:添加命令 - -1. 用户场景 - - 用户由于业务需要,希望添加某个命令至 OS 中。但用户不知道该命令是否已包含在 repos 中。 - -2. 操作步骤 - - 1. 确认该命令属于的 RPM 包名称。如果命令中没有,则代表 repos 源中没有该命令,请用户自行获取该命令所属的 RPM 包。 - - 是,请执行 3 - - 否,请用户到标准 openEuler 的 ISO 文件中获取 RPM 包。获取后,执行 2。 - 2. 将包含命令的 RPM 包放至 usr_rpm 目录下。 - 3. 在 custom/cfg_openEuler/cmd.conf 文件的 \\ 区域添加命令信息区域添加该命令信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - -#### 3.3.4、定制实例:添加库文件 - -1. 用户场景 - - 用户在添加命令或驱动时,出现了缺少库文件的问题( imageTailor 会自动报错),则需要先添加库文件。 - -2. 操作步骤 - - 1. 确认该库文件属于的 RPM 包名称。如果库文件中没有,则代表 repos 源中没有该库文件,请用户自行获取该库文件。 - - 是,请执行 3 - - 否,请用户到标准 openEuler 的 ISO 文件中获取 RPM 包。获取后,执行 2。 - 2. 将包含库文件的 RPM 包放至 usr_rpm 目录下。 - 3. 在 custom/cfg_openEuler/cmd.conf 文件的 \\ 区域添加命令信息区域添加该库文件信息。 - - 具体操作请参见 表 《配置文件填写说明》,填写时关注表中的注意事项一列。 - -#### 3.3.5、参考:hook 目录说明 - -hook 在 linux 中指钩子函数,由 OS 在启动和安装过程中调用,执行钩子函数中定义的动作。 - -hook 目录为 custom/cfg_openEuler/usr_install/hook/,openEuler 在该目录下规划了子目录, -每个子目录代表 OS 启动和安装的不同阶段,用户将脚本放在子目录下,OS 则会在相应的阶段调用该脚本。 - -- 表 hook 目录说明 - - | hook 目录 | 脚本命名规则 | hook 脚本形式 | hook 执行点 | 说明 | - | :--- | :--- | :--- |:--- | :--- | - | insmod_drv_hook | 如下
脚本命名规则 | 无 | 加载OS驱动之后 | 无 | - | custom_install_hook | | eg:
S01custom_install.sh | 驱动加载完成后 | 用户可以自定义安装过程,不需要使用 OS 默认安装流程。如果用户不添加脚本,openEuler 采用自己默认的安装流程。 | - | env_check_hook | | eg:
S01check_hw.sh
S02get_hwtype.sh | 安装初始化之前 | 初始化之前检查硬件配置规格、获取硬件类型。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | set_install_ip_hook | | eg:
S01set_install_ip.sh | 安装初始化过程中,配置网络时 | 用户根据自身组网,自定义网络配置。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | before_partition_hook | | eg:
S01checkpart.sh $part_conf_file(分区配置文件路径) | 在分区前调用 | 用户可以在分区之前检查分区配置文件是否正确。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | before_setup_os_hook | | 无 | 解压repo之前 | 用户可以进行自定义分区挂载操作。
如果安装包解压的路径不是分区配置中指定的根分区。则需要用户自定义分区挂载,并将解压路径赋值给传入的全局变量。
使用方法:eval $1=待解压的路径 | - | before_mkinitrd_hook | | eg:
S01install_drv.sh | 执行 mkinitrd 操作之前 | initrd 放在硬盘的场景下,执行 mkinitrd 操作之前的 hook。用户可以进行添加、更新驱动文件等自定义操作。如果用户不添加脚本,则 openEuler 不做任何动作。 | - | after_setup_os_hook | | 无 | 安装完系统之后 | OS 包解压到硬盘之后的 hook,用户可以进行系统文件的自定义操作,包括修改 grub.cfg 等 | - | install_succ_hook | | 无 | 系统安装流程成功结束 | 用户执行解析安装信息,回传安装是否成功等操作。install_succ_hook 不可以设置为 install_break。 | - | install_fail_hook | | 无 | 系统安装失败 | 用户执行解析安装信息,回传安装是否成功等操作。install_fail_hook 不可以设置为 install_break。 | - -- 脚本命名规则:用户可自定义脚本名称(支持多个),必须以 S+ 数字开头,一位数前面补 0,代表 hook 脚本执行顺序。脚本名称格式示例:S01xxx.sh - ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->- hook 目录下的钩子脚本是通过 source 方式调用,所以脚本中需要谨慎使用 exit 命令,因为调用 exit 命令之后,整个安装的脚本程序也同步退出了。 - -### 3.4、配置系统参数 - -配置系统参数包含:主机参数、分区、网络和编译参数。 - -系统参数都在 custom/cfg_openEuler/sys.conf 文件中。 - -#### 3.4.1、配置主机参数 - -为了确保 OS 安装成功,需要配置主机参数,例如:主机名、内核启动参数。 - -在 sys.conf 文件的 \\ 区域配置系统常用参数。 - -- openEuler 提供的默认配置如下: - - ``` - - sys_service_enable='ipcc' - sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' - sys_utc='yes' - sys_timezone='' - sys_cut='no' - sys_usrrpm_cut='no' - sys_hostname='Euler' - sys_usermodules_autoload='' - sys_gconv='GBK' - - ``` - 参数说明请参见下表1 - -- 表1 sysconfig 系统参数说明 - - | 参数 | 说明 | 取值范围 | 默认值 | 是否必配 | - | :--- | :--- | :--- |:--- | :--- | - | sys_service_enable | OS 默认启用的服务,如果有多个服务请以空格分开。请注意
以下几点:

- 只能在默认配置的基础上增加系统服务,不能删减系统
服务。

- 可以配置业务相关的服务。需要先按照 3.3-定制业务包 中描述的方法将业务 RPM 包打包至 OS 中 sys_usrrpm_cut,然后才能在此处配置。

- 默认只开启该配置文件中的服务,如果服务需要依赖
其他服务,需要将依赖的服务也配置在该参数中。

| 无 | "ipcc" | 选配。如果用户没有新增的系
统服务,请保持默认值。 | - | sys_service_disable | 禁止服务开机自启动,用法参考 sys_service_enable。 | 无 | 无 | 选配。如果用户没有禁用的系
统服务,请保持默认值 | - | sys_utc | 是否采用 UTC 时间。 | yes: 是
no: 否 | yes | 必配 | - | sys_timezone | 设置时区,即该单板所处的时区。 | 查询 openEuler 支持的时区,请在制作 OS 的机器上查看 /usr/share/zoneinfo/zone.tab 文件。 | RPC: 中国 | 选配 | - | sys_cut | 是否裁剪。

- 裁剪版的 OS 会先安装 rpm.conf 中的 RPM 包,然后卸载掉 cmd.conf 中不包含的命令和库文件,
最后卸载掉 rpm.conf中
\\ 区域的 RPM 包。

**说明:** imageTailor 工具不支持 RPM 管理包本身的安装,
即使用户在 rpm.conf 中配置了 RPM 包本身,imageTailor 工具也不会安装。

- 不裁剪版的 OS 仅安装 rpm.conf 中的 RPM 包,不再做其他操作。
用户根据业务需要决定是否裁剪。

| - yes:裁剪
- no: 不裁剪
- debug: 裁剪但是会保留 RPM 命令本身
该参数和 sys_usrrpm_cut 参数的具体含义请参见表后的
sys_cut 和 sys_usrrpm_cut 参数说明。
| 'no' | 必配 | - | sys_usrrpm_cut | 是否裁剪用户添加的 RPM 包中的指定文件。

- 裁剪:imageTailor 工具会先安装用户添加的 RPM 包,再删除掉 cmd.conf
中 \ 区域的文件。最后会删除掉
cmd.conf 和 rpm.conf 中未配置的命令、库和驱动。

- 不裁剪:imageTailor 工具会安装用户添加的 RPM 包,不删除用户 RPM 包中的文件。

**须知:** 在不裁剪的情况下,当用户自己制作的 RPM 包中有安装过程中生成的文件,需要在 cmd.conf 或 rpm.conf 中配置,避免 imageTailor 将其删除。

用户根据业务需要决定是否裁剪 | - yes:裁剪
- no: 不裁剪
该参数和 sys_usrrpm_cut 参数的具体含义请参见表后的
sys_cut 和 sys_usrrpm_cut 参数说明。
| 'no' | 必配 | - | sys_hostname | 主机名。当用户大批量部署 OS 时,建议部署成功
后,修改每个节点的主机名,确保不重复。 | 主机名请按照以下要求输入:可以是字母、数字、
"-" 的组合。字符支持大小写。字符个数小于等于 63。
首字符必须是字母或数字。 | 'Euler' | 必配 | - | sys_usermodules_autoload | 系统启动阶段加载的驱动,输入该参数的值时,请去
掉后缀名 .ko。如果有多个驱动,请以空格分开。 | 无 | 无 | 选配 | - | sys_gconv | 该参数用于定制 /usr/lib/gconv, /usr/lib64/gconv。 | - null/NULL:表示不配置,为空,如果系统裁
剪,/usr/lib/gconv, /usr/lib64/gconv 就会被删除。

- all/ALL:/usr/lib/gconv, /usr/lib64/gconv 不裁剪。

- xxx,xxx: 保留 /usr/lib/gconv, /usr/lib64/gconv 目录下对应的文件,如果多个,可用逗号 "," 分隔。
| 默认不配置,会被裁剪。 | 选配 | - | sys_man_cut | 该参数用来指定是否裁剪 man 文档。 | yes:裁剪 man 文档
no:不裁剪man文档 | yes | 选配 | - -- sys_cut 和 sys_usrrpm_cut 参数说明 - - 1. sys_cut="no": - - sys_usrrpm_cut="no" 或 sys_usrrpm_cut="yes" - - 系统 RPM 包裁剪粒度:imageTailor 会安装 repo 源中的 RPM 包和 usr_rpm 目录下的 RPM 包,但不会裁剪 RPM 包中的文件。 - 即使这些 RPM 包中的部分文件,用户不想要,imageTailor 也不会进行裁剪。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 默认值为 no,请不要修改此参数,可能会导致裁剪出来的 ISO 安装失败。若需要配置成 yes/debug ,请与 openEuler 联系。 - - 2. sys_cut="yes": - - 1. sys_usrrpm_cut="no" - - 系统 RPM 包文件裁剪粒度:imageTailor 会根据用户配置,裁剪 repo 源中 RPM 包的文件。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 区域内容,裁剪掉未配置的驱动。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的命令。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的库文件。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉配置的文件。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 即使用户 RPM 包中的驱动、命令和库文件没有配置在配置文件中,imageTailor 也不会裁剪,会保留 usr_rpm 目录中所有 RPM 包的完整性。 - - 2. sys_usrrpm_cut="yes" - - 系统和用户 RPM 包文件裁剪粒度:imageTailor 会根据用户的配置,裁剪 repo 源和 usr_rpm 目录中 RPM 包的文件。 - - **具体流程为:** - - 安装 custom/cfg_openEuler/rpm.conf 中 bootstrap 字段的 RPM 包。 - - 安装 custom/cfg_openEuler/usr_rpm 目录下的 RPM 包。 - - 拷贝 custom/cfg_openEuler/usr_file 目录下的文件至相应目录。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 区域内容,裁剪掉未配置的驱动。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的命令。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉未配置的库文件。 - - 读取 custom/cfg_openEuler/cmd.conf 中的 \ 内容,裁剪掉配置的文件。 - - 读取 custom/cfg_openEuler/rpm.conf 中的 \ 内容,卸载掉配置的 RPM 包。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 如果用户 RPM 包中的驱动、命令和库文件没有配置在配置文件中,则 imageTailor 会进行裁剪。 - - -#### 3.4.2、配置初始密码 - -##### 3.4.2.1、配置 root 初始密码 - -配置 root 初始密码需要在 "custom/cfg_openEuler/rpm.conf" 中填写相应信息: - -用户需要在该文件中配置 root 初始密码,否则,裁剪得到的 ISO 在安装后无法使用 root 账号进行登录。 - -1. 默认配置 - - 在 rpm.conf 中有以下配置项: - ``` - - - - ``` - 参数说明: - - group 为用户所属组。 - - pwd 为用户初始密码的加密密文,加密算法为 SHA-512。${pwd} 需要替换成用户实际的加密密文,生成方式参见下文 修改初始密码 部分。 - - home 为用户的家目录。 - - name 为要配置用户的用户名。 - -2. 修改初始密码 - - 如果用户在做包时想修改 root 用户的初始密码,请按照如下步骤操作(需使用 root 权限): - 1. 选择一台安装有 openEuler 的环境上。 - 2. 添加用户 user。 - 3. 通过 passwd 命令设置 user 密码。 - 4. 查看 /etc/shadow 文件,拷贝其中的内容,替换 rpm.conf 中的 pwd 字段。 - 5. 脚本如下: - ``` shell script - $ sudo useradd testx - $ - $ sudo passwd testx - Changing password for user testx. - New password: - Retype new password: - passwd: all authentication tokens updated successfully. - $ - $ sudo cat /etc/shadow | grep testx - testx:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: - ``` - -##### 3.4.2.2、配置 grub2 初始密码 - -配置grub2初始密码需要在 custom/cfg_openEuler/usr_file/etc/default/grub 中填写相应信息: - -1. 配置初始密码 - - 在 usr_file/etc/default/grub 文件中增加以下配置项 - ``` - GRUB_PASSWORD=${pwd} - ``` - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 密码默认用户为 root。 - >- ${pwd} 需要替换成用户实际的加密密文,密文的首尾请勿使用引号,否则会造成系统安装后无法修改 grub2 密码。 - >- 若用户未配置 grub2 初始密码,会导致:裁剪后的 ISO 安装失败。 - -2. 修改初始密码 - - 如果用户在做包时想设置 grub2 的初始密码,请按照如下步骤操作(需使用 root 权限): - 1. 选择一台安装有 grub2-set-password 命令的环境上。 - 2. 执行 "grub2-set-password -o ./" 命令,设置密码。 - 3. 查看当前目录下的 user.cfg 文件中,复制文件内以 grub.pbkdf2.sha512 开头的密文,替换 grub 文件中的 ${pwd} 字段。 - 4. 脚本如下: - ``` shell script - $ sudo grub2-set-password -o ./ - Enter password: - Confirm password: - grep: .//grub.cfg: No such file or directory - WARNING: The current configuration lacks password support! - Update your configuration with grub2-mkconfig to support this feature. - $ - $ ll - total 4.0K - -rw-------. 1 root root 298 Mar 1 20:54 user.cfg - $ - $ sudo cat user.cfg - GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 - B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 - 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 - ``` - -#### 3.4.3、配置分区 - -用户可以根据业务规划配置业务分区,同时可以调整系统分区。 - ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->- 系统分区:存放操作系统的分区 ->- 业务分区:存放业务数据的分区 ->- 差别:在于存放的内容,而每个分区的大小、挂载路径和文件系统类型都不是区分业务分区和系统分区的依据。 ->- 配置分区为可选项,用户也可以在安装 OS 之后,手动配置分区 - -1. 用户可以在 "custom/cfg_openEuler/sys.conf" 文件中的 \ 中配置分区 - -2. 分区配置 - - 配置格式: - hd磁盘号 挂载路径 分区大小 分区类型 文件系统类型 - - eg: - ``` shell script - - hd0 /boot 512M primary ext4 yes - hd0 /boot/efi 200M primary vfat yes - hd0 / 30G primary ext4 - hd0 - - extended - - hd0 /var 1536M logical ext4 - hd0 /home max logical ext4 - - ``` - -3. 参数说明 - - 磁盘号: - 磁盘的编号。请按照 hdx 的格式填写,x 指第 x 块盘 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区配置只在被安装机器的磁盘能被识别时才有效。 - - - 挂载路径: - 指定分区挂载的路径。用户既可以配置业务分区,也可以对默认配置中的系统分区进行调整。如果不挂载,则设置为 '-'。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区配置中必须有 '/' 挂载路径。其他的请用户自行调整。 - >- 采用 UEFI 引导时,在 X86_64 的分区配置中必须有 '/boot' 挂载路径,在 AArch64 的分区配置中必须有 '/boot/efi' 挂载路径。 - - - 分区大小: - 分区大小的取值有以下四种: - - G/g:指定以 G 为单位的分区大小,例如:2G。 - - M/m:指定以 M 为单位的分区大小,例如:300M。 - - T/t:指定以 T 为单位的分区大小,例如:1T。 - - MAX/max:指定将硬盘上剩余的空间全部用来创建一个分区。只能在最后一个分区配置该值。 - - extended 分区无需配置,其他分区类型必选。 - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 分区大小不支持小数,如果是小数,请换算成其他单位,调整为整数的数值。例如:不能填写 1.5G,应填写为 1536M。 - >- 分区大小取 MAX/max 值时,剩余分区大小不能超过支持文件系统类型的限制(默认文件系统类型 ext3、ext4,限制大小 16T)。 - - - 分区类型: - 分区有以下三种: - - 主分区: primary - - 扩展分区:extended - - 逻辑分区:logical - - - 文件系统类型: - 目前支持的文件系统类型有: - - ext4、vfat - - - 二次格式化标志位: - 二次安装时是否格式化。 - - 是:yes - - 否:no - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- 二次格式化是指本次安装之前,磁盘已安装过 openEuler 系统。当先前一次安装跟本次安装的使用相同的分区表配置(分区大小,挂载点,文件类型)时,该标志位可以配置是否格式化之前的分区,'/boot' 和 '/' 分区除外,每次都会重新格式化。如果目标板第一次安装,则该标志位不生效,所有指定了文件系统的分区都会进行格式化。 - -#### 3.4.4、配置网络 -根据产品的组网情况,配置网络参数,例如:网卡名称、IP地址、子网掩码。 - -1. 网络参数简介: - - 在 sys.conf 文件的 \\ 中配置网络参数,netconfig-0 代表网卡 eth0。 - 如果您需要配置多块网卡,例如eth1,请在配置文件中增加 \\,并在其中填写网卡 eth1 的各项参数。 - - 参数如下: - - ``` - - BOOTPROTO="dhcp" - DEVICE="eth0" //网卡名称 - IPADDR="" //IP地址 - NETMASK="" //子网掩码 - STARTMODE="auto" //启用网卡的方法 - - ``` - -2. 网络参数说明: - - | 参数名称 | 参数值 | 说明 | 是否匹配 | - | :----- | :---- | :---- | :----| - | BOOTPROTO | none / static / dhcp | none:引导时不使用协议,不配地址
static:静态分配地址
dhcp:使用 DHCP 协议动态获取地址 | 必配 | - | DEVICE | 如 eth1 | 网卡名称 | 必配 | - | IPADDR | 如:192.168.11.100 | IP 地址
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | 必配 | - | NETMASK | 如:255.255.255.0 | 子网掩码
当 BOOTPROTO 参数为 static 时,该参数必配;其他情况下,该参数不用配置 | 必配 | - | STARTMODE | manual / auto / hotplug / ifplugd / nfsroot / off | 启用网卡的方法:
- manual:用户在终端执行 ifup 命令启用网卡。
- auto \ hotplug \ ifplug \ nfsroot:当 OS 识别到该网卡时,便启用该网卡。
- off:任何情况下,网卡都无法被启用。
各参数更具体的说明请在制作 OS 的机器上执行 man ifcfg 命令查看。 | 必配 | - -#### 3.4.5、配置系统命令行参数 - -根据服务器规格( CPU 个数,内存大小等),用户需要修改系统命令行参数,使主机能够更加稳定、高效的运行。 - -1. 配置说明 - - 在 custom/cfg_openEuler/usr_file/etc/default/grub 中的 "GRUB_CMDLINE_LINUX" 中配置内核命令行参数。 - - ``` - GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" - ``` - -2. 参数介绍 - - - net.ifnames=0 biosdevname=0,以传统方式命名网卡,比如 eth0、eth1。 - - crashkernel=512M,为 kdump 预留的内存空间大小。 - - oops=panic panic=3,内核 oops 时直接 panic,并且 3 秒后重启系统。 - - softlockup_panic=1,在检测到软死锁(soft-lockup)的时候让内核 panic。 - - reserve_kbox_mem=16M,为 kbox 预留的内存空间大小。 - - console=tty0,指定第一个虚拟控制台 tty0 为输出设备。 - - crash_kexec_post_notifiers,系统 crash 后,先调用注册到 panic 通知链上的函数,再执行 kdump。 - - 其余常见的系统命令行参数请查阅内核相关文档。 - - -### 3.5、制作OS - -当确认已完成定制后,执行 mkdliso 脚本制作 OS。imageTailor 制作出的 OS 为 ISO 镜像文件(iso 格式)。 - -请在 mkdliso 所在的目录下执行该脚本(需使用 root 权限): - -``` -$ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h] -``` - -> **须知:** -> ->- mkdliso 所在的绝对路径中不能有空格,否则会导致制作 OS 失败。 ->- 制作 OS 的环境上,umask 的值必须设置为 0022。 - -1. 参数说明 - - | 参数名称 | 是否必选 | 参数含义 | 取值范围 | - | :----- | :---- | :---- | :---- | - | -p | Y | 设置产品名称 | openEuler | - | -c | Y | 指定配置文件的相对路径 | custom/cfg_openEuler | - | --minios | N | 制作在系统安装时进行系统引导的 initrd | 默认为 yes
- yes:第一次执行命令时会制作 initrd,之后执行命令会判断 'usr_install/boot'
目录下是否存在 initrd(sha256 校验)。如果存在,就不重新制作 initrd。
- no:不制作 initrd,采用原有方式,系统引导和运行使用的 initrd 相同。
- force:强制制作 initrd,不管 'usr_install/boot' 目录下是否存在 initrd。 | - | --sec | N | 表示是否进行安全加固
如果用户不输入该参数,则由此造成的安全风险由用户去承担 | 无 | - | -h | N | 获取帮助信息 | 无 | - -2. 示例 - - ``` - sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --sec - ``` - -3. 获取和验证 OS - - 制作出的 ISO 文件在 result/{日期} 目录下获取, - 目录下有两个新生成的文件:openEuler-aarch64.iso 和 openEuler-aarch64.iso.sha256。 - - sha256 文件用于验证 iso 文件是否完整。操作如下 - ``` - $ sha256sum -c openEuler-aarch64.iso.sha256 - openEuler-aarch64.iso: OK # 表示OS完整 - ``` - 当有如下显示时,表示 ISO 不完整: - ``` - $ sha256sum -c openEuler-aarch64.iso.sha256 - openEuler-aarch64.iso: FAILED - sha256sum: WARNING: 1 computed checksum did NOT match - ``` - - >![](./public_sys-resources/icon-note.gif) **说明:** - > - >- sha256 文件只能验证 ISO 文件的完整性,如果校验成功说明文件完整性没有破坏,可以使用;如果校验失败则可以确认文件完整性已被破坏,需要重新获取。 - -4. 查看日志 - -每一次制作 OS 时,制作 OS 的日志和安全加固日志被压缩为一个 tar 包,存放在 result/log 目录下。 - -日志命名格式为:sys_custom_log_{日期}.tar.gz。 -log 目录下的日志只保留 50 个,若超过 50 个则覆盖最旧的压缩包。 - -### 3.6、时区裁剪 - -openEuler 的用户可以根据自己的需求来对系统支持的时区进行裁剪。本节内容主要包括时区裁剪的方法以及当前 openEuler 支持的时区列表。 - -#### 3.6.1、裁剪方法 - -1. 系统中所有的时区信息均存放于时区文件夹: - - ``` - $ ls /usr/share/zoneinfo/ - Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ - Pacific/ zone.tab - ``` - 其中每一个子文件夹代表了一个 "Area"。当前 "Area" 包括了三类:大陆、海洋以及 "Etc"。 - 每个 "Area" 文件夹内部则包含了隶属于其的 "Location"。一个 "Location" 一般为一座城市或者一个岛屿。 - 所有时区均以 "Area/Location" 的形式来表示,比如中国大陆南部使用北京时间,其时区为 "Asia/Shanghai"(Location 并不一定会使用首都),对应的,其时区文件为: - ``` - /usr/share/zoneinfo/Asia/Shanghai - ``` - 若用户希望裁剪某些时区,则只需将这些时区对应的时区文件删除即可。 - - -### 3.7、裁剪流程使用实例 - -以 openEuler 22.03 LTS, x86_64 机器为例。sudo 部分即为需要 root 权限 - -1. 检查当前环境 - - ``` - $ cat /etc/openEuler-release - openEuler release 22.03 LTS - ``` - -2. 配置 yum 源,使 yum 源生效 - - yum 源要求使用 everything 的源 - ``` - $ yum clean all && yum makecache - ``` - -3. 添加磁盘,保证 '/opt' 或 '/' 有 40 GB 以上空间 - - 此处以 /dev/vdb 挂载 /opt 为例 - ``` - $ sudo mkfs.ext4 /dev/vdb - $ mkdir -p /opt - $ sudo mount /dev/vdb /opt - $ - $ df -h - Filesystem Size Used Avail Use% Mounted on - ...... - /dev/vdb 196G 28K 186G 1% /opt - ``` - -4. 安装 imageTailor 裁剪工具(imageTailor) - - ``` - $ sudo yum install -y imageTailor - $ ll /opt/imageTailor/ - total 88K - drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom - drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi - -r-x------. 1 root root 69K Mar 3 08:00 mkdliso - drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos - drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool - $ - ``` - -5. 配置 RPM 包 - - 以 openEuler 发布 iso 的 RPM 包为例。如果用户需要添加或删除 RPM 包,请参考 3.3、定制业务包 。 - ``` - $ wget http://121.36.84.172/dailybuild/openEuler-22.03-LTS/openeuler-2022-03-05-12-01-45/ISO/x86_64/openEuler-22.03-LTS-x86_64-dvd.iso - $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-x86_64-dvd.iso /opt/openEuler_repo - mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. - $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base - $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base - $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base - $ sudo ls /opt/imageTailor/repos/euler_base|wc -l - 2577 - $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo && sudo rm -rf openEuler-22.03-LTS-x86_64-dvd.iso - $ cd /opt/imageTailor - ``` - -6. 修改 grub/root 密码 - - grub/root 密码配置与 3.4.2、配置初始密码 - ``` - $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub # 添加以下字符串在文末 - GRUB_PASSWORD="grub.pbkdf2.sha512.10000.D4D775602C4E9F76EF4A9A6E726486941C8AAFB4762227E6973690ED5A760D59247E7E6ECA72472FBEEBFD9DB60F8EE56A4078094542C790BF0967879BE2D60C.B2742F38995B4B716EA7B0E639D02BE6C4E649E30576E5F5505B85844172B831841DA80D264FD14B025F3C8804158E7FC082998664BD03A92663FB4CE293807B" - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' custom/cfg_openEuler/rpm.conf - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' kiwi/minios/cfg_minios/rpm.conf - # 以下命令仅 x86_64 需要修改 - $ sudo sed -i 's/user pwd=""/user pwd="$6$yJiM4Ips$eto\/4erJfqkYcAtYw87Ne5Gj1ERWG2iAQiiO4iLMaYgqZOTPn5k\/xM9EEdofQZXAuJxxuYE8G6Tmgl4LaSopq1"/g' kiwi/minios/cfg_minios_efi/rpm.conf - ``` - -7. 执行裁剪命令 - - ``` - $ sudo rm -rf /opt/imageTailor/result - $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force - ...... - Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso - move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz - $ ll result/2022-03-09-15-31/ - total 889M - -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso - -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 - ``` diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG b/docs/zh/docs/TailorCustom/public_sys-resources/delete.PNG deleted file mode 100644 index 2309b8f37bdbe58916f235f29422f7cb703789d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17428 zcmbunbyytRw(bp01C2NC(m-%0f=fdJ0fGkChTsYAZjDO_AwX~lf#5E|-8}?%ceh|) zXRWjMUT5!h&iCAV|A6YQr@Ca$S+mCb8}FzvWknerObSdSBqW@dveK$ZNB{uha{vep z@&B<^hA3iz?5HXOMJgVm+D3cp?F{zLAz&3l7{ zB=zm3wB&0ygZ;*9SIX|BL+^()8YD(EVce$#Ev-;v1`VzdU@Iz;WYI?!ZOW?HPkU2> zvDE$6dp#tgE?=g~AIUJtQ%rxc;p0zoTM&+`bKhKhqsW&u$Kpt6{z0LkXXsJ`IcN%r zLIMTADdgpIMMW?_F`=ZcIeA)CwCj7@X?TkY3ZMf8OnrV2Ml9$;Ik7R2|5(xX9{fHm zqiVG;Uc|?K1}&9NHW>0n1^DZ|VK~E{YDUd_=zSt73AuY-Y2tDOd8Q?AGu(##gFNei zh=>-W?-b4|lb6~429_jPn)$kd7{KOC>Vb{f>$p#6@y=~`pTp-@Db5UcY59SZ5DhS( zJ7Q0j2)Q0<*9mYfbwcIXt8&pgnhyql97&uQ;pNDVjmAWV%fW4&&C_J+uc2Vz=*xQ! zxF4N`-9?r5t-~mz`+a{~`YRz1y+l3Cc5@;liU^4KB13^@jy{C$MI6XQ0R)0R^YT>f z`QrRxQ#WVc3jzw*VoX*9fdT+SwY1Ng4rHW94RU0mMvf3I58fuCAYBHD1Y^!KeHW)V z@cVe~{CgAudn-~e!xIBY0NqpWWH}Iv6B>u;r>;Xy$E(q7Md=^A@${sig=L>Pt+b91 zU;e;{CLw=XQQB4pdz|k-*_0%=+O}Hp;(l19tN`&%G;B#-ybJB7%!4-~W^s6R$N{^%u}E{t zVH^TNOR0Yx@gVZfANnRPqjF{6)%;k=^XK?zxVKyc@vzvFVBu$GN4@7Sy^iuIc}FXz zKtQwRnem9VCV{U?Oz)@n{o_P!Ss^X`VZKa317(cmGUz;yVQ_;-@6xFtBOGFq%B_ti z-b4P0Z?x3$Npp#BK4)Iov@a*v7+<%!4@A|OVz3|vj>Z%b)GuZmtvm3lbpjyv{bL)U z{gc<~#A!=s%Z3^!SGk=A3YU~TpY4{GvtQocz1(d)c+EvJ;6hDr!*0;nL$$WrxaWJX zi=JD}CRRiNt3hAXPwmLb#+bWyp^AyQSOU}^c*4*7QiYKxb*N@Z_@m%0gB%BXvPfHo!5q?_aSgI)rDg!@* zi0*Y(Ju^QlD4EhptDM9PnD&p2V~yOTDiy5cxx6&qlFfes0?APa+^8katwT%H(6hUP zr|ubB=|EZfG__!5Z4S4Sw`jB_3ahly!r;7ot$vmCG1@5ZbY?jnYzQ z)46A4S|UgFeIvc_`iwa{_VPgygo?k2cGtLVWvCCNm^2xK(Oa@Ix312ic{;;-R<(8H zX6t84-$hl8&J@d{0=M!6exELzJN7vX2gYViMhzH)i`im3ESZ2hVM;?I5(O7k0W*S8 zjl+8FCzPaiMna{TZIN`LMeQi00REUa$Jg;hikF%$^O_8aiQ`Q|5lUQmtGb?^yrbFq zTeu~l*$?2vPFtEX5>Gm}ex-ul;7rA5Hfj(%hTwp$6r;=KkQ(#j`RNNCyYe7Eqqc$s z^W#;NN1KcwkA|}ij(bxBU3|r2Z_l9tByLZ3-Q|3mhMLdqHE~%c6qFvKVgd!*Rh4tz zoFJ>KO|_o&0pjkQ4bW6Y*yl1QNy`_;vE1zijkf%d5jii1px+k~p25>rbLZZ0G-SGW zw&?2xlmz4Hfr63(f7v~W@%5gI`q*UO`IRrpZcmoT*OxbBSN%|l-L6GmnVZ1Wd1BZ){WI$A&TpQgNC5?S;!UYtaiZ~0`^sYQ0y&y^unI|z zw26IhF_f;Feh0gMh2@oNdHq3Blo){H=%sFEbG zMR$|N5>%ab3J$kj=s4L`GU?GtX8L`%xi3NeG;Jt zb<6at_g$CCV7vW_4{#B`zkDb5VY_}iuE%oL^z8;MwUp)%eb_!1AMxV8=KoBD zs_;*SsLQ-X@tQCXIbb=Ej;jUhl?3yLPykxvb>np@Mk`T99hOFG)>!`_GOf!jd!w9GV(-S0`^h(IQxwK0;?V_hS32pl6YlU!j zey_)Y;`%R_%On{-NMhmc+tG2PQTy6Xv~Vr|UYk!ubkGvYIC&H@&~|3c_VSSxJC$X@F}VzV5A9B1cM*J{ zSZ3G{<9oO|X;J4S_WYD~O1%S44E2!4$7hH!r&zWfge0S!9~*7K{t4_dU3B$pwf(B5 zz}@Tnhi==F$kqDXMl#Yt8&ZZm9D(a8(EX|o4eerLmr@gc8}4!8<%uh>&-%<3&*Wtm zF~`>YRg=J6bLDOyvc6%+loC5SBMc zP9Q~NPi^|0ThkS_Kj5G#p|d$XVr3u$ZRaUflHS$TcUVirvJ}ReVh4}TmjCo{s#^|t ziRJ9Y*}7Dsz^6B`RoTNczOtX3g6(HeVyHay0Fg zk#)J$8Wrq(wSClN24Z{W<^8p~_z@`Jefw7;fZ+?d=xPV-`v_^}t>d;%zbZi6#Nrbq)kN#BSF&@%=w5Yi{1^GO}92|rs2?jz?G5m3lGpLG|Tvlzl-W+dN zsfdskJTw9b0EpiP5itUVf@Vxx(}Ic*_RgZ9JV|BBr4XC94bsPw(=uS756dTF}e8YX{B# z_^|nupAq;JNoF9#H6i!Nu*U2tq=4M3)TrRPsqtUopZ=gA>AglnbE`1yi{+hf|Ho?H z=)Z=6*FCP@XG4#8#j-eUwit;wBvs#~kGy;CzzR!KYwV%pJ?3FITsUb6|t ztiV_Z!kBqFw#f1D-IF?W=sB-5eb{z8J~j@e)msZQ+Oq5Z?S%M?-6)#1G~L$eJAdx^ z1v*3vVD3vWTDiPj5-a=65r1orl^ z4)ehBENg!eQi0`1-++bSOcQ(Ts6<$~CG1RV`NC;3*xHyDk~*BP{P3MlB&lVs6@*qH zTAK9J6X#=VlPBy8*cP1&WOcSL4~Z+DpJ||o9}GTtIC%zOr^ z6%M}5Dlt>z#pNFV?nn9Un(V7m`4w(REZGyu>_TjIC+p=t;Cr#QXY3|z_Cx3;YU&J; zz}CpAmG4?j2^t#WXS4Zj)!Mds^ts2kv)r(ODUm(1K*R`S_368uK`N)tZ@4|p{@nsw z_Am!lY+6s=S0;sHNr&IIy}!Kxe_xtQYv~ArspbDNyRamX)P`n|?_>I#T{z2VH(;ez z1JTM98@)E5bj?J5lWp)!5+w>M!2F9fK4H zxL-yEy)#GHC@W)VL^dt9>ctJ+zTIE*WU$K=v96T2)R2+=QxgZ?aOpl^ zoIbkz2z)u4<396z0naAcmCOH|;4{5W&gQ72Hw+43;BwJSd^HC!SXD@6MsR*BpM>-i8_)LP- ztXd9)%;nHfpQLO=58Zn`!K+cNom3fqFuKmu!m{HGCPKredI=FNY;-Mj^LhnhY(Kv= zVI5a&%sk>++FPHD-Tj80yCd#LnCsGNZgGoog^q*aPolhqt>wWHwOF!olr57QnrDqA z!w+fcjx8<;?|R@4;T_9(--{3Un`j?nc1?M2ROYS+KOe-L z_|ENkkHzPgA}(!nLbokf)Jm!#VIjRRya~zYUJ)qcz_3+we3v zVI`j1lzDsSw^DcN6LRU=9Au+`;$BOd##qQhGB4Q)X zXRX8Ry+rk5padNZsg8){z~hy&Shsg@{f4jp-lm^1{CBvs+qy){E__I?xzuMJ~`aThlV1{!*IYN)ZSD-!_@6<0QG zaaSqT%&^h+-P{H7^!8-5QgGq8!kD5g(%7x> z?4qt>DGI1|Nxs)-m>RRy3HX78#mg4aV z5Ier$-bNoc5urrAr_z_qv5Si>Vb4mH#K|OWc0NdZXm48X?yx1V610_Ov0m2)ytq$;1ggVDd8=c z$Z85|Mv_i~R)AYwik{895_-)}9XYqj&f*L@FpsuQz-m;aj-;V9=16B|+8vIv_&EFl z>KB&8c!>WVoR~@g2>iJyl^B_Gr#v7f z0KED)J!k~iV@sL&A~k2;vLM6c$IiQF@^HEclfMh0nM-f7g&6&pt|N5DcX{4kTfrBg zw(;xuXEqB^W6VwCbzaeI$W$5dLJk}Lae3Z7CM~%$Bt~m8#vWpqJPk7EJ zXsG#ea&sAlyyDCQ^ zU74mYp|;Efr31y}$yZDj_3L!Q%y%zX zA6sp4QV8&&?4=n9Og-GzXfW%$J5Wq_TYmC=#5|0pKjT_zaazK%Uh44=k{~pr>0LQxXH7XM*`p|tVRr-~rjCo0BxD0K z;)1P)jGb1`0zog~X%9(uOn*vVBI#pR=D3!9BHXa=>~*WO1L*eFf`P)5Cs$56e#4sP z$GwE2yRdMm5r|m}&IA%_u(Kzj-D6W1=yc+&&={NXUi&IFGBvUb17v+(=zICHh~A=5 zmO6%E<&%p-IovN;T_8j|;?f8yvlf*}>f247mw`f^!-`^1&F8DqfO1{b_@E^#GsC24 zO#l2dOgVY`q!ptH9+l%1g&UnD20A6skKyJI;H{9j8s$kUo#_i>u|dJ`cwSpr3{PuI zeMp1re-ZjSkgA7wPiRW$x}EH9WjdFl(dhC_He z4@CJ?4Y401?msycS0AKtYf;&8yz|z$6PQPA*jJ$_Udh3P6sB0kU26|W-!Q%5K!Wp5 zjxJXKBt|Wvcv(WvK%}AjUlLzFcU2M*CSbre$i(#qR}E=h877S0<`0mv0^M>dui7|D zpJGEcln@BQr`m_qLG(+IA5Ux^K47`gZPPW4)w>4ar41b;HhPWnfQ#B=a^Yl(;^x-`*;TXGy;QL%YV5M-`8j z)6t;~2XJSGnPquyh+03#am8+v6z{bGGc%$s{i?ncQIJ8!6u5BcrgRNcoS~p2Cjkfh zHJ5~w3MU1>r%T7A06-LCk5w*Fx3~gF(a13mVsw=%u+@jdHqA*T!%^z)czlQVCkDHf1O&aXj6zjnP5T^szdpq2RS10bo7TpX-b$G0>+6RV}qQBo!aPf!mw(%eq^} zsyVw20lhj{23)Xdl<3GmY(*J6$2=jFyznD^8n*mVHF2zBYi-0YgQl~sGg*LlVa^wW z0xvi^r8^?Qc4=VcX)i1t9RmY7>8LngUnbyV_8h3D30D7LZfNamA%U2famXk}Is$sA-^7~+3W6K@ z1$^gp%hlmLq|z1~U6EB@)#^d$x|{eqA8A;x&Z=&9J|+c-O-UEA z=PZU;hV|+cP1TUYksb!csp4q1TU(CD!2Z$m!ou@`E&k_RzZ|I4;=0Z~iMsD*2?11T z!*wP;0y|Ew5wUT@#*h}@)APID)t6tozcBARzW{yQFjP=ix_zC%#ERSbMYFXBAE0Mp zd8fD`9Y;2-ZME_I==5tV_$%Id=A@Q*`ZFj<%gnI#agm}~Y7mw2|^6j{*GYS%IklZ*S(_OrG(6K!LY zforgz;d9z`zhK@Pf{uz9?~dDfo3-Hs2#6;8UVR7*4=C&+-eY=JVc?|+b{Tbg*hJ%%vp*{N;ussV) zv0gbKH3%7@T3UM^Lq;9z?pnIRuK z)ln2R(8;LK&KN~xBa;g@aC-VTtspI<(t$l(xO7W-&L17%EpJ+ple@M2wIAQ;xA)1r z@P@mMVOONalhzQo>hoUQCT5eqQe7KPD8U@%!+v>zO>(o$b$?Lo)dVGV%%EYs?2Of2 zl7D>u1ez|6C&l6SZ50O865KRhqj{ljT4zWIsG=oOm71T|3YCZCq47Luvb#BTak)1| z+U#)*>DL8!tBu2)xPZ(^nEqQR*y4GI=M({ciG5sf2T)ej`rk3MR+pAH5$oK>28WJ=g9-@oikcN z_ukPAb*&Q&XfB##R|G;U8a|We~3qj}kP|?0-4^f+7 z$QYqqO2(w~PE=x)H#$)U_F`k{P7rGunETi^iWp`wjk0~THYB&nH7&(6@uHtS7U*&n zVuPF15C>-66fcSoNe_9{W`PsUhgg@pEsjr%cq55DVBh3q3ND@y1Nipi;(QTj(z?(3 zO2H%`N|>q%+v(#&F%8Z3SX-Q~?x`#cy1?02DM>Ka^vX#J zRA#y?DjW?#e@n1i@C@a@uo6h0i}7N>Bx6Sx)zIwkP}JW;tiQsl|JdSBdL^~mcuvcR zILx%wb>Rgb!`rxfD!x&%|AAgrfBz@F(x|AZ&2V0}?YzPNF&&&}pnia=s&2Wze~J*yz8sy1BZ%j$1jL>7NQtw6zqrWARt$VyUD2-1au$87zNVNE>(X zq@;e*e@l-@jrl{O7**>?X=Ycj*#&-bK?(R5F6^xktiaL$okpkBOmyLtY> z^f#Hor=sz);}7u_nF&;AM&5>zD&kH0FzAiU9Q~ZtzCDBK?u(sc5{p<16AY!0F+)a} z{*f0|o-?Z+{ZwsCq=?6)2wW;14Qxw`N{YcO@vRP-s79@5mGI7!ikK_ozHcK%{`~VXqgAge`8@BoF27k* zl`Wmq*HpL0UDXopHznlvSc*Jc$dmD_x^F#3a5n|}%O-1-9+$imwu3PlXa;8x4JlJX z+fi9~`(qL*pQhZempK$ov)PWG07AmxSJOKdW`_2fqU8Tcm4--F6tAB)e^MYK6xOr5 zKI0L>wu^@Ibf&oVs0&h!egIqSHa>>!4RAKti9D*?Ww-Z5FdY1Q2Z2?exvTHA_+fXQ z$?v4**brn(ru68YMWCHEa7(o?r=j1VBG>&%z(m+_Cr`uI!KB5(J*3=f-#bsW#G%h@?N#)^88>d?1=N(rTOkM0_~qAk=yoeVxUR6{XQ>H` z5YY`Pkr2u!8u``B0>RrY6=wRKnYLL4(2;%dZb8=Z10py3*bQS1gq+hEZXR)SHM|tJ z8+Wy&^30f^x;JwwyKGOYau{x#p4@V1vwplx8R+)iYS^arZF_{d%<;IZ!_`%zh>xQs z(cwUn5%DzZ8S2rgE4{#nh~>rN3b&z4leWW-dQ!)$)hgZwB2D#<>0YNwltbg1&6UKo zvLBT~U#Lth3oGz&?LQ|ezxMRNPo`{Hvu`rLLwZqNzwDxMz-_otA~wt>{okpJru*?{ zw2OE|h?9S5S~AJ0t7xkfgK~T=P|mEq>o|m!n{(gsSn%QrA;97H+!YWnn9@#j25gk2 zl{a#5muTMdL*7KkUmVkZE`=@{6*j7f*#>zVyD0^^y8h0F^{uKy{bns_ zaQG?Pwhrr>dn3IlH?FpK1uo-RE%L|yd)he}6B9~70N`7K3klG4;1!b`jph)gg%(&F zv`l5%dsXWg@i6;(y6isy?%ldnR9Zm+n8j7c5APxr9?#_>5+n**J{5k8O$1%gxuCOB z(#eIC){-XU0(Z-`{}+HVTKG2rW#X>@W#%XREyU=JJqHs{N_ETI@s_Q}txr~DtO^|p zb+--zK81Z-TS21VyY29y6*1t4-l)pLzpxLzK=c?F@S}3F+$lz($pGs!0syl~;@oaX zcXnW}sg#p1!Sx+ZiW|z!Ss?xzNu2c%v-+>}R^3m;fR|sr9ZpJE5IsfKKMk{=iZyC` z>(NYWP(w2$;^=`Yf4ngBCNGgo^u|z`LYoRjR!KX2xPYu%)labh15N-GN4IBSWxUO3 zqLt*r=uDc5*Ec6G{>BS62e9Eq!**|PKGE8+~m&N!xV#v29+k)NIc$&~>>iVIf|4s`q&Vl!8uO^@-CC1ID z*g6n1Ep;GP>BmnPLTkI`(blcrZ4tk^Lhz_q?Kdv+ud3g;^su6v9!xgzeQ&jU*+Gp1 z+1llrfrvG80f|O{iKSYR^dxzEsMhEv^*544+ zrnW&;TpzjK242(IaGKj~>d>SY6CGXeaEQ5QnTsl@fUuW=1tUPo5K^w8l|cQRCoO+q zj-LO9ISl%}ov|<}*j2k%Lu+%WjV}^2y>FNvp%WO@-Ki`D5%XoSmlOf$HtjosN9_)~3;ZA`oTq2RQ_bkWfwwUWo6Q5iv1zJ7wMIzp|Nm*7LX*xF+ za>-)U;|fvYiMblk5-3itdggT`;N)HcBDQ~SBQ zS?u6NxH^$4tivl7>eqZ0!94)5ZU-CRJ9&~En(w+oCZ*&+Ai^*T2zWs_SV<%Is1cRa zMLJ6Mmx9}YmnYPSVQdt0PK7dYFbU%U$f=Oy@-!;$1CksNLQoms&6D#U1tP22pqz2$Lr zVY?G;Mx(9G^<~*b*6A5Rj>5ETu%XX21J93^Y%gaohWUfz6JGH(4CP47FReyk@4 zrSn_jsekB22Bt=#W>Q@>{ug!l?5coCWAIn|!^|y377)Xq>8Q;##_jlk(tWN`D8O-b z#&{h<{OPn46B+eFR2#_vhrZ$|5u~fY`tJFA2B6!s2S?Jxaq(GCZthxs!(T7zp%Okq zPmL}7O0;9BU(w;`iARoygIU_gbNG_MpUvZi9fh7OM!aVSzM0ZAlY;w&E2YRo$crnp z5%eY(yhOXPysg?^!S0V71BliGwA>4QUNsu4zFn{iSefQg4nARhwi>iwd zGz2@G^28bb-lU}u8yyd?^5VtA(5H4O~5JC{M_()XK$=7et%g> zFkUeBbunXe|)jOqv^Cizo6zE-kjqVr&3om3^%)Oz`tO1)+c7itt~Bm)g2MX-q}d7 z3-w#CQbnO9d|iiPFm=!l(fu!Okj1BkW9yelh;F|#LEPYQPfnCIRv;eQ^*b~)NyoBn z{M5dwX)?7ibRr4IG&s)pKa?)B-LH|N7kmCV(y&BvsV|be*N6Winv9K2Mbf0ThKu-U znH`cs^%%zTwzKt`MMLqtm`pj?p z9ONWK?XX-?Efu0l7XH(auM>ZdOM!=(Y-io%9y3p0@h1Sr>5Tww-BIl@g}sxOaoeEY ze0WX?dT)DSe07DxdHb)zcN-}LI$HztWB))0CLg8+!DCXkDu z8tn@24oGnBh~O=%1cVhF57at|w<6Rp-?&b(F@3B0|0f4OJ-%F>K8cZuH7}YMOQ%5# z!T*CCB$}j{2RvUJFcn|q5{2SDiYP!!Da7Rwz}|Z4_MYsS<{+g-+Hh*Mk}}^cE}#F$ zL&+F5-O3_YM!&F5vK4<-u>~x40zl^?1p^u`Bd_QrO5j#q?{j4wqx%w#qpe8&6EE_A zSx4l4rU!{2@Q#1RYX<63x#D;mHsG0!mtjMUMA9t6{87{xtkl;}qp-}3z~5^cBoFpO zhJ-bJHtnaK=a;B+-rNzs;-sBPl2L`)ofAE&3@wxF;uq4EgAX#ksjWM_!VNCyT>50K z+Dfc?>`=e)UZ&|nRKl@J~S!IQPkJP*AvlIU95LqScjPB-b8dqVZsxKlVns>ds zw`X$r*-i{^5kc@D@fR_rwFtY3#uhw>jk;)N@-?WZQc3Y1AuE72=;ItsB7|?}kWWoB zvTt3_k7N@_(&lD9KQQ1kzEDu!eHA)@&ZZIG!BnM| zPtC0Z_80_oIn&`>qy(NDyha%g=Lo>-_uCd+&BF-%?JhCKlKQ_}!KgeFSxRx>%RUkH z`zRlWeHZ@lpRm>3Er4V}Z;_%C@ea9^mYZz`m+&z|Rp9WBCXPLA^|};5^}woHj4F|_)SY4MlBwK#7)&^vxHvvMW$s*zN+`qO zT^w^+QU)YNsyNgsOeEfA0ilZwI_++%p^D_Hb3 z)#2Bs#Lc-fp2Kj_(%yYb@L>)jbI=aL#S^PdY8R*3m;AcucUFp(8)Dsz&-G6;bCFBB z2OKl4iW>ddvXG$h{5kqXFv>)y9ms8A8&U?M3 z@oa%ck8A&@)IZg_jTcQUc#EfV{-zj*ZZ;EOFqab(B%uou>yKNc0uequ`7W(TMR}Bch`@d^-GrWM&RAI7Y;L#it*!7ewUS3 z7hm4L++`fDk@Gx%k6~hNvkYHl?bWvt{%ufL_Vf|{-vv5qdA~tfcRkVnB+$!}`dLdD zh~*xA$I+R}QUtbFiDv1_fhtw-SR1eeJg=SCJlNX5{lZ)7_@;kEE;O#I5*#Ff_3s|+ zD!hs$@Y1T-q~`P0hlF-AOJ$b-6M63Oj`or-U^@baP8>W)BSd1jAbE-zm=_A zZ3}B@^HAE3k+i*8-~2e`usdim%$0lNsN34ajkP#Gv?6ZX0)4^Ra=4RM)a0AWvTAhM zcd0gg4j!H!RH4J&v7)^? z>5c{hoafA65n);q_`NkEJx*9y2oT$oR2qpmD+4mQUbeldqN|RXc4G|k$^9^|8F9%&Tlv;A=3@>}AzlFWqmcNsUf#igq+i3i!(A`|kz_ z2qFQ_x5RB=ClX4l$GMa(&nkkiIoaS>CbfF?wyMQQ@&00O<^lEgI5ImcU>QDG_4K~^ zU2ItJ4G{pEfYEPDax|;irWKm}p5|g@CYk?gLi6ntxGe5-$k73#&;15Z6R&BP(MWVc z!f8vVPf+K!@>Xf~NFcPsPdXiA);#;_*i%q%xDYEi3#`?<%BOx;K5Pt4Rg@71p`iyW;nEqEsLvuYtg)SCi7j?BfQnZr+2g>;P}*;0ePuS8 z^;kMgUq3{kgqEHX-gqCm4T2CRFyarzvJ}&rU+cii(06Q6<2v1mYBr2O#V($@NxT>t z^tk@ut$W6k8%lv=w2N(Yh8|9)$rO|PGjS6k>wF^FKlpJcX0m8RSqe2t2sH-Nz}L&0 zW#`@H0sdUQQli76SHa=iV-*jmIkBC*erF$Zt{TGaIZzY%xu@w^ew4xoIK()yHK^ah z@Lni&;Gb%S>(mWvD(`^j5Iz+yQjb(2GSR0UT4G8HKhr5kV;$H|n;gaqPTY9P$ez<{ zf4+g?e&@Ya7H=5hVtM4DnEYw{=}8X0!&qylLPA=CC`!Pd;Hy%;mVSuLJZB$a(t18s zlR9vg#_RlKc4|U1mqvL8Kgkn!xam$T&F2;=V584`6qgbBIip%pj>toXVAs zjty-5gNb@Y4CO+M4_Pk^MthU~fUCPB{$=U@%o__?7Y1^*#aT|wizsEM=t_;pPvNUE zAd5g4v7^kN!$-b*hf>QMm2_a~2ghiOdDxK9iW%#RcfniUnT7bP=LOJkH}OXJF6izs z{g3j#K0P5u-?~>?d$$v}N?N3xU5nNhBX~I>_A=)uw_|8`V)p2%$cp}lmmOYJlTRy3 z6xj8PXI|HafkAByI{~k2MHAl?t(I0e-w;teIU~WLNmt&`=OpyeAN~xB9rh z`2*o5r-P4TpwEU@FyW(29jE(x>gT$sB?(moccrHf?g_%y>#r(A9+xd*E|iO}_}3NV zu(`SLg*;Kw4e51nn$PrEi@wa(e7vkQy8FT`cAE3a^oQxuFo&5P?|#{w1Yu>Fw6KoU z3uoByy$*uqc_vqVz4RL|OsTd`*P{@x>5@Wm=vO~?c35&jjW%e#&UJb09WpUwx#zt> z@oBNv4`tl{#)>BvY|%ErpzY=J2tIxnufKY3VHz#L9MqD=&)?EtXiS_+`dZY@_DP5> zvo1H;zw7)Os{dW*d)lM^OXrvUjh*4Q&X2?RH=Y0Rw>lr+R`Li_eYz+>4r=!V(IYZ& z33U(DoSfQQ>r$)4JU7L!-bDlW@0o!+n}*-o4npF>TqTteO8=zqPo-Zd;*RARq`qgc zQ5Zjf{0~cm(-RDhGED&i;(y3|#`nV7JL`y=g3CQNhRth|kVpAlk*GQ3Vb7c93ZKrW zvgJA)vNJa}cwG+gK}zR!M%Ao_I%3lg<5S2c3sd^4N`%{h?K+35j~>BX4`)85B_nET z8uZi+nbBL{cYl+gw4>uXoJ9_311(-`9=8c6l#MSghzcU^5wKbGar=bG{ki=!)xxaz zm<$^cM1Tf6?%&k}I8ve4$jodTm(kc8VInV5EJ+a-zK6#f(XZT{uD z(|rv8C|McyqwoP9D#_y3w+3~@Z;xwVge<_gRd0+7%U{w}w4>H{5M-2R%K|BLm7@R1 zvx8npD}CYllwbHor_7ciNTTsJjuWW$9WA;O?10G=)6Mglulz*YLEuvu85936&p+)7 zt$%A*2$9QAC3DOlc-e^(Kk1yGQte<^x4nOGX|nSM2y3Qb%K^;eqN~az@ej(DSXsPQ z)GbrWJm9+Em>AQC$mw|6;JpCZWo~_L4qYe3`|*QS_2}qV3m1piDbpuIUka(8KM%DL zVF00<+3a6E2-V9{_y2A|n5Z(~L4*PegAa448)w583;kFJ0|`x|#o+hp(NSa+OV&S4 zWC&$}J9w*=^uWF&r*8vHK^xkSy4XTKA3pCvWb*zra&$5e<*+d+635gSEp8A2Zrepf z^sU@n9`P)xw8Y9A2^9NVcmI0QKshCz4y{)HEUql{H7G)`=pqQI8PCziQ8AG*B`J7X zAHPXz{q=#j?n`cQo8<6?WW5A)fPj8!`w#V`V7@50g!T1URpgWEOQ5Qk0u;W7c@0gC^cVoyjY$gpT&$z180$MSj|=Id5(A1-@TMG12h|~mV{OIbZ_?GhbrOYtWFjX z*7BLWC|`_hWC#wIdp)9cR3wk;btMO4Mt?bd71+2u?Pn+f<3Min*mk{ zajXtM$4aa$$wS%`r`G**7eR6ASn`H=A40UP-O7Q%W5jM`kPYjlD}l+ypXO2(l;!9>MBH{_*ip{J60I`Q#2a*KuZ$CG>oSQ7FT>DD);ps zZeQfFlx*I;yNLx6FfiqvGf8it5VJpD6Elp4+DaRW1!0hwA4pSeryBg!%DX*~&h2NF z8S*yGO_)%NRsbihW<5@iG@)%txBE?vSlhPV+Yn~ zWTjPGc`zP=Q2aInctb33wzz}dFPq#)yj0+p=KbD|m99B|eEc@+^l$2x|14x4_zM30 zW1yr6*?-s&n$Dmt;8Iw1$j@&Ch;5{Wy}tdfCO%#(K)u~dv>z{2C$4nStNYN+tvLJn zU{LXQFj-Iu$b!q3w0+ zL*x3%MBt!^Dvjr?&i))qldezMS)eBL+4hff1tlYVi1P&jtCF`%R>-vaa?4@06!~b; zN?XUvA?$H(f?C4W+ydTL3GpKLmSv>lcW9AJRBl%m1irpw9>YlvWk%JzV0+!;olfoB z&3~2#pELz%M3v449u_OEjEw>hyo95>WjyWt^)DL(tVF2@nTx9gsyWRN^@+*ab9L`q zG=pD}$-5sN=%U_k4}yd9JtTnfXtQ{@D+!0BN2lh$Vk=y1xKMr%61)E_&fO~JMiQ6{ zGgnetjb&~&a6$ZuW{x zzs`3K!gj|{WY>qj7zy=;K zYe!-B_0hP?n(X{n(`sT0pRH1}Y;A~KlLD#Le!2z+K#@)3QKG47&@~9A)EI!@k0&(E zj(5jDA?jd^YtKMhODafxk$Bl=ekIi^?o@DX_ zj^w~b%0<$UdQvfj|893#UJB)9$~<*D9{1+aaS?~li2~Af{xBmJo9I~U!K;c80AlDK zZ}xsA0!)A~MGb1TT4M0X8Hat7-hXEJJqEyd;oKqMtufdkOx)#`+{>nB9NLnvx>7i; zb<2L9{JWtkj&r~OUqvTX5U{>JT(No7@Z0WhzMO@P;m=K0)gK^=p)b>f%VKjqxl0ZX zVg7yXR{t@J|6|35@9nzbJ)%YvvFpEmk;NZ<``0&H{GYBUzkPI1tFE=-m?_({hj^0* O(#z+H(#24tfd3EsF-oKW diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/drivers.png b/docs/zh/docs/TailorCustom/public_sys-resources/drivers.png deleted file mode 100644 index 1bb43150cde548a5d6cf227aed5c354cbb31ec89..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7060 zcmbW6bzGC*|Mv$7NJ>fyA|)W9l2XzFG893iL!@)0(o#|m0qGElkt3u=jcy5PiHUTK z-hgeuJwCtR_ZQ#${_Fl@=ei!(&e{81=e_sy@p_#T{Q{^#Mb1hN005{opQ-8r0E7_y zedJ9-eCxJZyM@1yxj!@V1OTYJuRjD|g{av805)|^RV97DEM&H9%7S!FWH36t@c#T* zI%C!A7c$tV8G;(-nMb{O!_VCooCau}h|PpHxmCu@{itFd0BCQ9oCo0$n)!m70D`;G zfP3wLr#HF6X_Wt~so@NII%95p6aQp&6?yFuHQra+NgAx( z(4Zf#wi1ezb*p1Hwu%K#8hn>XS|`&U-ZC^OwGPBKesfRMPll-rhKZH&RAdo6cs;HL zZrkCse|E_y@W{ePcvV@{&$&5}pcwd3&H4eV?HxG?8Ru;V9&^HE6vab<& z!Bq;nH?aKd_T z$p97fMZgBUTS_q$#B5((l1Q!?Fsg5D75#(tB?^`7V!i z|3o!Thz^>5IN@C}zQWRH7%T&opAk=DSa(Q%lFUEGFd%{emG&7Y+`hDX9RTMLTa4V4 zHu2qO(!uH#a1$w(>0VquHD|0`@bxDfr%2`64FebqO<<`rjBck~;wyDqZqC)i8Ndv%TIKqG!Hxu+k6%!tGRXs&YKSmamZgTP83-I@=mEz0w zUE>ysXuh#q_Uzu3y&Fw&cqW`aGl1Wfx#*8T*t1#P%h5_Y=RDA2L%* z!?(s$X&+s4`m0LkQi%!fbLZB_!))L>eWzsr9vdPf!j5Am$?4bp6jS3qX9UGQqW^br z{Db-axdS=T)tDC+$%@*wTohQ;#beLI=_*)h{k^^-j5LX|h$h2J4V;a4g@rHm{+)5+ z4inI!6;NkS?L2842GyUNXl-*#m9`-~S~ceO6+D!Y2{u{0&A*+Gu3}QTEr+FCdJ3gx z5hzDelaIUQ_WNoy3M_DTJ5)uzlIhJ3PM-zVNvhZ6Ya2MnzuWlR&CEqGBE}}|dCUCA z&#phJR&3~zADB5Nia-mGZ2=iT@3IsN(+MIs`IURnz>7_uHBP{*v9nmpB2to71o-MJ z^(E|+{+po95efH_`g^2$*xjKO=GUpxsN@91v>yv)3o`i)=D+wtyj@w(I~;1P%;tL5 z&Qrgr0NjL>_;K2N4F?+%b?9f+&Xc6`O0L4#MOU>-4U+q-RMx3~7z%&)^e?8pG#L*! z7Yc+HRZpktW!FlyG;Y_e_KuZ9xntK@A8|vA#-kl?VFL2hM|`fPC-3*|il-;_1I2Ab z&_VaznX=NpEaaoVEmEkp@P!x)plC=@bKruZ4=0N?RtX7Vn^B$5e;~;rVY89}D967G zpotDRWnG8(q9vj2s>n?GpEv4j9 z~G?Aa$L;)u(*8LWVC6V~VMv1u~K&kWm zvE#*J(?FGi-+UTaEk_ZBGx)8SszTj2063*OqXe8$mWS;ltY2D$#xqx*CT$-~ODjTl zIu6q*kCS5-zRkiRe`wMR1D50hloXq#xEOgmYd!JJ$ZqfMYC-ru`15VZ>aoJJPuj~O1X#hue#PHxHw2gY7Q6Wn z(QJ{HWgdy{ODqe$FmI0|?h>4;IxI=<{qa+316cN~*hL4>hRt>fs4X;qZ+qD6B_4#C zNYCpMvw4>^BMqvsvJg&j>MvhsxAs3tYC8K?g3NNl%oM+TnIqEAemEklvTnWK{HCDF zBPLKEw{};=j8F9i(~1<##!^fk^GJc5E1a2~ZV;)O2W$s;YD=4$WJ7~T2Y&YP+lnbD z_kVTgG!9*D1YfS5e4$bP{B*oZ*EJ(^4l#L_~kGw zkuTt|hNn-x@B1nD=hLfA(h@~MQ9C2ct=vs_14tVK2u_Fi86Iy_-y`ACD(J2~0Pc=CD1OZHw$To7k9RNivuRa}>hHbSyYn57=>zI;JCB zWWE9bdQ+OhHt+ZSZGTJnNe5X8jQnU}_P0exx!?QG$+I&TNcXQ`i^iF`15c-m`!9m) zgsrF*e%TVf=Q*rNy1N@>OoLK-t$F4rpYq|nU{SLFImgHs8}=9y+E=_RQC--nnW8SH z^0m??Fa?UyVPkr*$6;TMu97TrSozAzgu5@zB=gHc@t2D-|4OCl{QVU9knn^|2q*dR zMZHkgEvxy1sj}$Uanw+6w$b5RRy1fWYUKl4T*i-wlf-X5Ap*JF<4f;=qGwC zvKHIcy5bZF+4P$cJ$S_Tp?#w+h|THZeE&T$t00REuvtEGmJlQ|9vf;tn3x&r^&2E9 z*EU>*`R!m3aVKUw{C2XA!O5ngz7zAAKvw~SN$Hc)hCP3mN)fIG$_vaxH&J_$<#{JX z!qJiyOKjX!A94EbQL6IJ0Rp8LT}xC&{2EaD04E`BNg;liDr707mD1v9aY=@wvA{fK zV`2TChE8q7(5J~dkhYLCA?Xv?Z<+rSje#Y^Zk$!EWN&R+~E4CJpNoGu5=Y}_Gb0` zl}fRn?dy&Ld+(>eZ~b-r9^M8R1%yza3A$ctV?pcV#`*muv!C8;zAUAq&J7XmMN)T# z2#<;T<#qC}<}sfhXq#LJ;4o0#T`Fur%qlGTr zeiiz*9@*a)iKBArCx7)CwcFcbc#gnml2EP2R@v$S-@lPodZO35$iH#^A6?WUbwF}R zcI?_?P}f`9(<~gld#W`LOtG2&m2-cDWj_DPzJhkzcrjdYV_j{lhjr~CzN8)!&AZMmP6O(lYDC5VRlNVyGK@@a z6xqlkQa6CRlx+CHJKB}L;V`k!xzN=4Ipt&{bg@AzjMU)8iG(Az5Bj!UAH z_TaPWhStm8SB2lHJpJt6VPbL_mv3-!x6W&hN97maY~JQBsM6i}PRVEu+hrr22t56Un{E4{WlQUG3>yZ#3%ev`!??0*eOjtwl5*v)zvZ3DK4v6cjiU+r~f3^HQ} z;4s{%k?T>c4m&4Ww0?HPDn};PV?@S+?SC-2#;WsWhqyU={tV%o5yLDqU+5!bQs}|T* zIIf)R3O}<(22bkzESXk#{bF^gg;pF`pT`8V5Ek(j^`QCtX@EWB_KA&B3Z(yCe z4`&H^IoQsd3nlLt35vz2TQ~e@X*x+wqTg?yPIDWQ&ph%>235kCC_$t9dgl`Vu+8`V zFy~NAn?K$SinpT|auU(p2U$<3>qp-NnkEd01PcU+TtQQ{3hsmmR}sE=x7?sEuc)!HFqF~I2e1;(nMl$Bhtdcp(Y zXazYEc&VgKH`%Ts=FAuP}_Fy1@NHVnxk&+DcbVkoYIF=8SAoH8Km_|p4lG{pm;__A8+wL{j>65>|;>pj=QG9m0B!7hifHoNdNwu_rp4MGfP!1aHogsp@s7H!)g!iCC-M~q z1@@K|A1%v%$!Fv}Z`seJOYJlxL>usY39gm8sjqy?#5!ren@Xi>?t!MXf_dP}_#Cw>5Q=Y=F5*nR(X@@12?eu+pB2Bracb==`Z%ohi!bIKAl6piZw+x=N-SRdYom z>%jDz3{O9m@riOYZ4vFXG*s$6aemoeM^cJV=Dqh^y=OhFNXo+mUeU#vY# zq9D6gniQyOXRfD^0$iKqHIgq|s8bg+aV%-g%znp*xT8UeQ z#*JfeZO7nIP#(Og8{ad5S6ZGfXkMWD1i`fDEs4W#N|H}nxM-(wYxOgqz~4!Ry~aAs z{US9QAd*j(UR+D^nZNsZE1zoZ$hv})T!j$_IpKev^;$JA@N}(iVqVCh zS`th*!3FV1WvZls!a<$1U?WYYGPSbpiN+@uS|eJ;Gmy7AdCq151{WNKh~x0(ao-^h z7v=tRyb&$OG1%?#9;TSVoxRc+6^l9q41+|i1ERY4iymSd^s9|MwR?k-c$ylwXMC*> zbTB*{3<;3opI;MR{w(Yi8`PP^eRH_TXy0;Fd7YsG%62aS85mm;8BP@-rw7cC-R!Qk zc$Ybn`j5-B{&RA8qq6VdkQRixwwa`R|FW3@q0xIs?<;b%cCB)2g-G>Rn1^^zGN1-{ zhvGr#404CO6j2pWhe?0)>v`ZW-|r% zP1vX1(6V`dK%D5{!LMs^==;GXBdySO=dyA7>N4E6N9S@C_hQGXoK2j~d2}<>A4|~k z-QgE_L9LOLsEQzC>sViuG34$tj-~F>b7|Pm4kV^o_4fQtNQ!jfZ zZzbqJa7l4iTDYxdT*BZvSYq;hi6GB4CHZgP7&`y&zL6?kBPQ#Jc$Va<{tzDZc)F3P6RM_!+DILe4US=p z6FxzFgky)BWEP&%q`ZURBdc|m|9;0hX}vo!>c_(koU@M%qi zMdEcjYLjH_z#O%ed~jFJPyD=wQp=-8KOI^dt}Dgx0CId^KX1f*nvEu^p?-zH@N;nVJkP^DTEFN0SZgY-S*d+mf%V&()?va&?|17paGOi25IKpk zCK+=wMvN$KF#NCMk%fp#uCwK{O5y7lV#;rvHe|wl;iKM5Hip})jm=Di`rLXPy?cBf z<`fS~TJiEMdk;n77id8sl3%t#8fw0?UxI=x{Mw3m4b7-`)X15zl{?wNFDcA_QXbbk zeX*LDfupHF_+VURXCOjYo2by2(DKjVeRih~c^rO*93MBcQHe|~V3*zeLH4B6B3g5E z17GHobP3XojrcxlR*)-2YFr`W&Z7lKb{b{G?KHc5nLM$?(Xhx!5tcR3GUW-qk%?3aGB2g%+&W) z&HU=RM|bUe?mBy~UOPffMIIB46b%jz4)ddej0PMWLJ}Mty!RUfSPOYjs-U3^2j|HM2j?FQ2loJL@;`!ubLEDEJ28cW z6H14JBXZ1cR~LbUb8+}6BdO(KeAb12!7$`{u!6-)13|asV8*!I9`@j*;yfJ{VpAwyZIG?1IffDF1qM+P* z{Ng^Z`ZuYx;~4e&@!5BF(swcpYgNzn_d!={1$3<4WGKc@XL<71uLl+Lm#gfFibvks zo|gwcI}Hgm1$Y)}z=_Xy+-S4UeSR|W6`c`MHXbCeE-o6c)AlpYwhg>c}mcqDdB-n;uitf zRYo2B?HI8uEta#i&@f>EbiEWp=r6WfcJt9>VnFgibP)4rE$(8#H`-}5Z@Ga4yY&_t z9^il;a~Z)qu`ckX=IKozwr+YeYO;OY4u1H=Zj3+n4y8( z!xSmT$@>cX}2p=&I1QVsd%B#lotiLV@V<*NI@94^+#4L^?OC$eBt&utEz5TM4l& z4l=_*zetm(ha&_WecyFJQYYurof93xjY!fk*w?J=Hq=^n@x^h=L{A>H2+or2P`$-4NBNpM=9$R1ps=%Jl(=>5!LZ1;EX4xwDz-q=wJ zf`~YW%R*exK;gSFpRq~W%Xg_9Y0I*e(~*q_vx{9>dizNTtE|*O3mYMVP7-8)swtuQ z^dx%;8r_0nKwi27MPkRD2EMn=etm!A(@uFH=(4nb%<2h{ zjqt_-{A1%HQUSK@Fzt|&H1Cai4a^TmUHcV?8u=RVC|#14>-~3bwJg@zfo-0H=H20# z21jT_T=q#zHw57Ch6^p+iE+=|9#ag!mf2}6iyY}}UOzQ(;E8%bLi%P)%HY!@Gea!m z$*fkObt(*UFj=VcI%v#N&SaR?vVmAM7LT*<&(W;rs7m`w*lLWU9wOW=maW@Gn!(BM z6A&oWBp^_KTvzn}(2H9VcIffG*=|()2VO1`FsCBQEpYsYY`sXZ*QXj^?^^la@ELey z87LO9dh7p2HoRj0QBld^rE10hfDjcQ2PAANvk~~;YMHuIn{XdqNy}C(WOlgM=-H@$3$vsh*fYiv3BpX7U z%gT%S{_~t#HLTYdGb1xo$oI*^Yk5B9zpEkt|Lpwnzssb(5;o3g{bcI@>W0+%YnSgk zNN-4L!i-gBF_^erv#DL=Vs2t;tw{#K{B?k0TYJZ(nxofrqqdaSTuV-&P^$%W0Q+XQ zi`)fOQ`}AHw_xACFV{t6G5A!~yibR=5-_j6uXcG*Efnuc=V`rZe}i(wlf|p}2r=in z9SHGiY{5bkcb=NMd2Btfma>|%RBW5a-fY~>X=Oj1JDhT;k$+rszR+sU^%;$+@P6H^ z)yQ%8`EofqZ*n?u*yYYKpuBVL6K5}{x+c|Z6AK!<=9)}0aT-Zjb9J}fL4aPa;P4<^_Y%G4Xb*}6Sqyde7wzs0XlVZ#IApUTDYxxp(dwyM$5k8gk}*MC z57;daIFkPTK@S}w#})R1+4XH@e8)7z)wf~C@p7HvH&!j!qxf2&h8V9W8CEkDKkd-xP2N&%#KLz@~Z4x*l@ueZHK}~3^zP? zaj*T3*rJWqT4O-qfNKyEw_x&#wOT*9J<9V8yd_PdIEI|vREZSJW?92KX-Yo)UewySWZG{*;{ED}!V_b^y_Cvs)dA};0*xV_A1cG+5V?|BN}n-0D%_<^0tey@FiGk@$^pn;ypXZwjO4 z`DEMlaI{cP(wlze&*O=%ctIupru=L!LFI+Al|v9YYijryoFe{R8k@K8&{e}8W4ug8 zyc`PUmSpX(xd@dcF-zBTJjz~@G6s~1d-=-4l+%l5Mbyo)3VCqgC$`-lb$pNB&FzHd z!hA-NgLM#LGut8vETRf_4$^LX+Na~j*|7J1+3x;K&5$l1OR6ksf`|GxKAOcT-elD; z<229L2|1SRuN{tmPB=gzV%$vEzt%H>EMt$YxDTYwojrOjAj+OaVIg==U^((a?)vU? zz2IRnVMm&I;7djz|J};tlQfsXIZ-0n<3-)EMOKdz7kCbF;Et>JKIPnA&RubCFUUEj z^ph>;ho`I2KXULMZy}-BVF)+N3UNqnX!38_<3f-MZJdM5XEO;LC{(YdkT6i+Kd19J+zltFs39?#15Qw22p5v&B)(ItW3x8*oxWgRdLyNyPVsQX`T}B zmvbufm)x$OeyX#@wDC}`Zym)f+7&KNC+8~A63$Pc)6{|{N2cVKUU%*Hytbxog8ud> z1^|ReJ@SZs90Rs)(dLy7h0@XF63InvBSm$(Zs%F2o4u=t&3zdVS5K-p-HqeEi-qJ$S_QTyCGkmGTSWk~r=#m&G1?;NRx0J>2r= zWLH>Hdg#NM2T2Ff#;mlOy9*)EaHBdB4@I4vDOWhtfgbzGmL!`cr^BrlPF-p$dmW>3 z76-pcX5Dyh#cg8!2H&3`6I{Gl6>XZVg)1oE)kbF|flD&CJ%|wx`P_KEACb^aJJJ(X z>-~16fs9E84GsJ#7(G0|jf&xIHHHl996@Fm<9K32-Vlyrdii+%c~!%7(4tSpd#b7Q zJxGs>Fts~T2JXFHyl2roj#-`iW!!3%kiXn8MuU%0JJ+hfa(~N8w#I(~@Z2f=st6GG zV@OcjIHrE*-#%`p^UKGT9aF;6u1(o=y*V0Ox8S$tYEb*W_ft9l9;uP+pUmsCDn_l= zv}?J@WFNdD@q#XW;>S6{<=2fNTlv@N19Y!GxIQ_#1w|c~xkGaga&F2T@WIcZ`JGRK z90-_EH9vSrc;8ao&W>Sr^a>rRu9549C=ZVs*>PnD!a06OmpeX+RC*Yo!F4t#ZK6mo zb!et4;r5ws<{$bo;0zhQqFQ@z_>rlN7j9`Oq;#PFE3~GbGMT zO>&Ax@5{Gw*L0D0#yr1fQiB~))7}i|74#8nvsTEN7v=ovE0(`8d5r1O`Rr#-`E-Ph z?Nk5or++qVDKDGASFGg@Gq2;_<~4*C@ozJqFx0w|K&OfJlrSgoK`}_K(Zvj&m2gD= zea+HG7B?$WF(HhoUh?>QtwV)%(pO>UKQ6qQTpn~Xwu_}6=j^VfUq2B{ z21ga#0c>R^vL&@bKMEd_g7ml*SL9eJRRfJY>=U2@{l~_P`M6O=#+SawOf<#_UVrU` zQ@5vYjqOsOr+%%!^l_Q!&gPp_W!N)zo6X9a=WBQr3HI*TS;;j>MSSW_$ zkTQGYMD5;Qfk+-oQB686j~_0$Nn(_=q}}!ue@v+~J;aW`PA-k#-Or`^d9SlMxOpCOwjLiUp&D?L=%_3}9i4xg5}#0~&;h0W zZsHA-EK7NU8@~ic5m=VuKDHa@(68ZZp91Uq1%Y4tgRsX!n1Ue(m@-`=Xd@}4r-t#^ z9mF^9PoGzLc-n%oty#M2%jQ$ScsUNpRO;b9egTHn5*|$P`P|wo8mapPkyTgP~<+2O^WMO4YpAv zBfaK960 z%R10$0?^XqAb_~&vBU&;dH&K9Mu{zL*3@9kNLDBgVIlXrtd;#R5!PgD7mLX97M&kp z<0L?&JQg2Je)n0n*Zk=Ho=mi9{#)~+O?tph-S*~^C{J_{Z9|)kKo?*NQFhrJWTz*8 z$B|?7dtRCSz~MH|+CqW)1$J9ok4y?Ok}+c%Xz3Q?$d0xU`xLH*~o=ffMp%EPFv&YC=!D|BY#Wo;A0`uqC|?uAQi4KuQA?C@VV0#Ewngs#_3rV{M( zR+ZZ-x)e?R;d}tAF=m^^oN(jXgqnNRTh@Ib(GNIFyZKJ{!5ycpZu(2cYW8KCvH=C9(#+5o8^#rerP9!GgtV}04o@5obAy0OR zwIKTQ=1bDyCYmXk1Tqnx*sVmD%+?^GHa)w*qjd8CXKXAcJMzy}A6d^i_x=5qhc}Fr zKP^dplvdc_6()UArf&J7JL9qZ2GV3NRCM(Q=ITC&ef6HhJ$A~D5-!|fviC=H`xZj+ zlD3+OI=s#w=D(p_O!tU21<-x%&*5%YVp?B_9-XYLv-nm!qK^Cr0ym@;Bw-l!y3+Z* zS!+@TxTjw}xUSL-YM`j`Yp%t~04*djnpEc|Eb%{>*+rdjR8ZI2T0|Z*RI-y3>(4Y)Iw!B(!*F10MS%Q-@JfmU4fG>`Arbg`I*| zK^Mt&IoofJrXeAfcN=-h{Oe*}st{TgZLA zIE~al`7Q)<6095~_dvk#iLrjGi(8~Rs`V9de^+OyT?tG$W>*t*nVZJHOwY=?jslVu zZdhi^EPbFPL6*!E*T1~AsaN30cp4fOp3&g$eHhizk=Im_r6}j^Vvfzm=t?F2y!@pY z{8oNC6~n~o;VspaTv*y3J?@CLoE|yNK}Mo>9W?YqAHv;|loQ%~IYF;{zSP*%uU5H$AYvXiqY)7-%*GkcXmLg09!Bs_wyrtE60YZd@#Qh ze+WcQlqS*EbZ{zWvP^)gPY$#3s)~C_qqaJN9>cO!lC;gGYIP?Jxmj*XJF@4LdZxhO zm}77dw=1U~tbmKiD%u~PKp4KAKm0<==H@(#B<%8A@Xs{m2prChUZ}I>h?9T72y|-H zPPRE+k{%)SLq4NWzW&LP1ccwi`3B!qp%xxzb@)+zAs}PhS6%O{hDOV(^Nn>934UbG z2a4b2+!!41y?=4$n$z+Z_OVCtA%RHP`$2%}&N{-Vg_O73F&=P)ecIS{0)Yh`j2bWclC?=&$fl^(Pi+VT{c!k#jbRR1w&oPGFWbcJ1}} zu!NWJ>EhmG<$0M481k?7{8tj<*obL z;{6&me5#{nhVb$(3u3-vpw3h z=-O-!&1E5uFw4l;r$!iIKg0bgzW+R`<7;D`h(zNQ1J6%Nt->Dr4chU8Lq>&}tq6+0 zOg^ts(5F;oAs1}dR>LG@qXx_iy8ZR~w%siF!;$li%aEl28u8!8XgM|br=eEaJTi-n zTsix1#Byh&whw;Svw~LrW_kB^eDI4{Bk;$c30ZJs%^ia-Nr-8MdF+CDQ0%dy2? z&l7j%kol&201YXYQ0D9NS8+;}!}d|18j8thWiUGH^tbNdN*%T!YVL*bSJ3(J2Mp9n$l zOwrQEzgEH!f85k%lVLrAxxe$hix8soM6tc6M?L2TB1t=B8N0H)(6!0Eejm(D5cQ-q zGb?AIz(R-P*0%D|tY_*UByRs&)m2*(i=_z7GI?0-S$_ev)jB?#7T(iPGqtbyG*)7U zNglf{?=lz53i!z#=DG&G2j+b(sw)?nqFX80i@mzei9zQrNb^s)ie3d^SVWgtq%>ziPjF)V5arpi2OAM z;oMe_+|F?(G-pm%MN8@$WGT7qZQkcNS;h$*2s7yVV;JUdT=M~_sf*UXXuZe*AU|Mi zxtvWZ_)zfYH7&~by8z+`r={vF--8HczbRR3UC$6#j;Ebpp5jZ7^^Ji6E1&x9BmZ_P z*kc7=a##fDag$x?ho!!6qS!4J*hBPt1d9NSGL8tSma6N5w!sGVFHYMIT^KjgM{`L< zc%d4=9SmeN7O8gKjqkZb9Tkl3Jl;CjRvtvDyyMa)!9|frg>QUmksi{-Hw~32D8j*m z{HO0_n#kSzYN&*}JasEO2zN|#VD}9^FUjR+bz046T;NM9ac_771BT*<+VV-UqWxa} zLr_$G<&m+Jfv#wa38iuJ~T7VG*x8z!$YU!@{C(D0i3{$ z;XY&9q}gVVC4V>17sq9!uSC)H^3$r-?(|iQxaRLpio+MO6pwIux|QR3p%T%m7(x;Z z?1*RlKy#;jgE1~z2Ju4^-Q5zWTh11~$^*9;2GJW<(>3Xd@(h_iEl z)~{ZqrSC+@O_vO!Ru#%|8I*z_=sQ7iwG(IjVYze%b$a!p`kfU`9TEM<5J1@4;s%}w zBKvIHUjv73ftFM`J~hTryHIP>B1T5#C<5XoGkl~634>wWBJJUAsz;yU$`#zdf2Zcx zm0T6^BUH0}Z8Ok;dt>W3>)a%AzK+=n<&0vulBQM6x}z0SN?{k)h1@JZu2Ada-+i5N zcK8x79ph@Pu7w={M`f(m?^5o(`)0t0x%|uEt4`* z`%Xe%2QOftvS3b)mzSyA=yfLXJQN-ga8|Z7*%ZLkF0Nuh-+jA)Ldy*Lq0X;L5_2@r zKJNO+UyJ+TUGm7s!zIbf(6rPTkWkFV`} zV;x+;{*5xM=K!g3SlhcTm7Cl|uJ6q9=p(Da4|cyO%(*cM#*(C^>lO~w(k8H4x-}8u zB-s%iOZbiocD-Fa+d^J4Coq}s`r8WM8{4dkZ5ftFAuLe1HJU-T9C-<`&-6ZT zs-<#k^^-}MX4`P1{~2nU-=vTz^kP5PZptZH%zasBZ0Q|$_|UCFE*+q>2*n3l-rNv- zDOI()4cI*NH=*@h)|~I37B>*7K0oXPJe72fGW7FT4a_2<=tV%K>d&!+p$gMqp2|Fm z*N}!HP7V+fiG7@Z_Mig&j?Q0*2Ka?Z!2*F^#8xr&a}S^e);{AyE3!aB-4hCimyhNSAZG=#9TM)cPo z3n0wPt;#&I-b`*Ag=Y=hdAB#m1CBv8(-c~f>~nuG_r1?HvLJFZ*<17i~o+?WmI8J3ku)6GiyN3rmJ;#P5Sx;_7 zO2`f=JcW)pD74DfCObUtS@m379QwS($#XqyFmbUxKh0abIIS!j{sHuKzTUlz%1XRy zTm})Ue6y`4eww6IDaBg$uDN?4AnJS$oRj-D85VP7D6Ic?DJW3ZmX~?%pjO4HAs+u%HBc$KBJ@ zr|JXzdY<1)OF7G`-;UT%<=O6Z{(Y{_fGvkavR4U;2?fmS_BfgfCAqTv;ft^jEb|L& znq~xsjgR1SW{h?tue0X$);upK)wbszuAX}Xvz{K)wbs;UJ*(UsO~M^7==*n#sfGRI zGIaD0FPZ0IJ~BwN@W8HEikF9&tZ{-Yl(4MHXaD566&kb>HpE zkokBHWc3i-tWQ4!x~iUrYrp0^$_}n=1sPTC@MC|k%t%NwXiD(-SWQjWA|Kliv(>Xk#~FU zJ)easM-~{&NI<$D_nqVTpObp-y@;Fsw(qL?dAPhvoPQv#VMzcR3iR)XnQ@EIw^k1` ztZ5RSVe8Nfqwg$TzL;}j$k=YZ?1`Tkh^i%UPX@$)JmbXRx<)F2yzJ@J4&%=P2%kT?ijnIFfbj%kA_MT( zIJQM=^6)~f6rk?nFK$mwjv*y&nJ7DKe058d6!z7qA3JfRWXQktt13EB3?(BbJfdfD zA-CY#|LmsC#OCfbDO2gp*-3PI7T4K!cJggoNu32gl8N~&xbK`f?$bubK31W#<+hMhis*;16#+g!V|_ZD4;eP86}l>tMan?E6$+uKU1ONP|Lq3oz;I;A+vMG=+0WM@7ku z;`)+6N|hFJrtrOcWZ1m34&&R0)c9ks*hqPUn;cyhv{p)i(4}oVFIf;6q zzcKwif3+tMf`N&=p6@XHW=rxVW#PA5N9}U3L_z^lC%8v*}`q>y6qB^5ipcXLO6n=~W$-yzm4?eY&i|)Xp2XaK*ccP&7wIvXy%ET;xD^EQ# zxO~KE)5Iwx^sAu(4s=_}TMCo^{3^3zDSUMi&Yd1c7~C;DL*D{<9QS1ig|h&WpynG6P@ zT}ITH&1xncAZoBl2SY3e61@_X9#i{ogCHlk=z5--W42{81)`kN8N+%k9%gHvDx zSD$H1F`6~%s;D$WcH+!_idOkBS}y!1kSw4!$cft?6A->WIBC8SJL9#>Dc~1C!A&+9 z*4I_aPz~@C0!Pd3%2iR+f7pNNJL{!AqTLR?{J#9R0#E~9sp4k$En2D`z%0a`-q1bm z;)#XaQ7$$J&8#GW>(J=l8Cu7l&OAyKO?h*ZerJbwC9Sm5*L~*u@WJ)TBgcp=I;KP7 zuk5(UZRXgB$=I4ufh>;M)P`W4ZwwZ|kAxJ@_0$IV>c8}jQp}}eWHBzz*N7U^6&ny( zz)fUyXivd@&>xd;AdxZ4A}BQV@z*fni42I4WEL z?_u`iklhCIsJIzRS=sPV#m1@fU4mZzh(| z?YiBgx(9IaxxdZN?2=sSw$S6fO zgd_?9>o-)_Wpuaj!_@dUrykZ~d`m6(u&%t(jq;(6B+x+nI)&5k?j-y8j$;CA*UFkF zp-TUOO;w0}ZA(gbYiHMZoEt-!t9ujK$<->Yds=m+myOYX^Nl%1+r?dV-Paop?R9>& zmu9S7ft)Mdb2w`M_x$f0c|uhkXL_8iY~PLMWuV{+gWK`nb+>q+^-4Fr+cK=*_Fk#u zXNr2udCri&)LZ{C#1wjSH!~6)P7e!4V^ zcu7DxK;eGU7mkfGFJ$r?-^kRC+7DuAM|IE#oZ+u5GWK!W>KP56d(F<7fREM6^JS{9 zUshZEUVYhIY^>DW{dS0acN+7aZR=&evS8zHckQjxU^70w-1a#961kp{)~3g=T?of4 z0o@;DZ9PNX>GXZq?OJ~@V~^u3;b0GIkQ7TqBIu^~qdo0l`wfXD9w;;p;av}M&;3c(T^?~|L%GGdz#S=SRv=_5u6tG328wRoG7pgTP#%`8G`Kp zHvyB($Z3ecj3|h5IQJYXQu{M%5I6kM~!S_R&wM1g&6lG%V^uyqT7#Hx@MQgW1u=ip!JB2{tdX`}ac zK-LU=X3gFwLRf#oy2EEzStz$D)J!%V(D>s5G~f@)Qv(5%eu`+Asv%D}T;j13flxnu z@jC8;MZ38>7xo`gsOqwW_QS(Ps6(L~!0A}s= z2UV(p463!bS>kKpo(Oed8w$gOdOz$#KvMftzu~phz0gy>itIp+{SI3+FTt#EJwu<% z4Iyp@pG62U6fOu^-5aDPY9(Ibzb%=O1T1_ z{MsDPTSS>OCW_1YHMD>^C=MtBE=Mz)2dz26?)-iU&N{tk*+QVbg!kyv(>I<>xk7j>|y#K6n^Dx*gAQkeW}jTX}f zlUc&%bTTF__8Xp%(F8-=h1P7v_yhzvvN|7_G$wySUL{-1@mdQY#-y6J>U^;v-`!67 z(mI->9^zeD&H_PM=eJwqvzW@h|8wY$0v=D}$`f{ncK-MScb>$gs!cX64%*48G3oKW zIbB63;yg`{xsb|*Nj?9@#0u1_r*`?HZAb^ebSy@G=d9i!+xb3_&8^#UqwCh?J{Q%G zX$mD7D0`(J8VHxvsL66x)%Oa|C7)tlBII+WHcfxFFv$IEt=Y5>0YhHMoEkj!XIdP4 zy2HUz1~S!vcx7bSR&4TcGb}x#;vTWunZ`hdE#WmdQOVRvz~QbhtvMRgtZ<>cTy3x{ z%F3?SfJAu`fOyF2G;|P*MlcIZN1+MEB;y~IQ!&VlOesL12hc(`=xz(sZlk~?+GBZy zf+1jKwVn3gHA-d^6B)c|oJNt!E5|96dYGaWI3Ud`?oGZQtIT`d60%&()WGpWw>5Ta zCV)WX1*6)-#Q^peaGc|I(~HZ^d?G!dhX$?&bdZTpxqa9_dTLyZx|~4p{?P4yKMh;v zva=i}mMbJU?%G%BNY9R90K&e{-wtPxgF*VA#8J#)XKD=oX&k|h}&AER#hxaH3(az(ya?p`W2HhXnv&(@Trvy zgK<_Gm^6aovCf0qr2w6&lzR`PpcJfGiGmW~tJ1gP?L~l9FbckW3P+$zeC!bS-dQa% zC=|SM@HrpZNvIXMNP9Xb>b{Z4YCO(7g!)pbA0}}kCsJGA zTZd;ig(H*aX0{6x`j;GRUj+!%5R>#bCZ-JXc9QW25z}~r7XS`=oV(zDcR)R z4`L3kDK|O;lrbj)dO3txN{o}m(_;(*l!gRU%CaY4&+^sok0 zBQRl4%{sHlm>A&*?PWTs;^#L_i52KN)5s&s*!EDcm)ou$DRWkBrDOqdW1>2ty<{Ev zF=_O@o|FaHCaWl8v*6i5AY-CoXF9T^`T+%FnE8PXrmSt~RqxGXgK$BU)5AI?SVHgO zZ=ZT4QI|>d0qt}FqoPd_9o}Dr2ztM&CB4)LZW;bn4t7TD&wxoUp7`lo1GcW}l`aZb zxWANp_*RV;OsUaq$WfY#sF4VLE#kbzrRZwi8C5PLp_elSyTQTay9y}p=v3_O-H}Y` z?@Ijc*a~i=lcQ_sD!JP!A9j7Z>=@&xbKG;P-9t#pO|p7R2V!EJ&K)UXfj7^C(TQ`T zGXSU~B8#F$wvZq;yKesSL)|Q&z?%G5Fb&#znBon24hIdpQ3iI9Hv95nwnFfZ@xv`z z@b$VD>8#N8UF$5tns>^F}s>S6oxI36u;Bk-=~Pm zt9|-JmT+`uKyFmuBoLd(Eh%s?IxhFa9hKEb8G;fd$Qz@^Z&3sz4o87=O~f1{2^zpG zo7l=;mblbT23kYNR7bXO`5hMQ_^h5S=gKV4n)cAdKy0szW z^dR#7$N)`Uj2cb|7T3s7C=6=Op%Nvv5#Ug3HNrevP|VU!B(L=QE=Owd$W%J`xRn8O zg}3e4^_)ik83wgRZ9R5C_4Fb|Pa-0CNPN`Hd%#aa1x83P!wxJNHtxF1uX-x=jJt1{ zIFO0dag2L{t#9(;Vx2WPvLhQWQBsM&Cc=V5q=meG?kUbu1xed79Sl2_7V zqsy*+7^C~~!iVgy+x*_z!dDC(%e!!-*;IZw!qE8e)cPpRk&@z<)-umdWc>}C3MSmU>Q__}FB)_S1tcc=-1)758MY{9Jb=`n^py;xNubY4>7Z6}j zne63&EJuHfBVl)jpV0A0K$UX}1~~(4SJZ^C*RCXS3a@ucb|Pm)H$GU2!Abt-s0zU zNGBNd5TrVlP-cQ#2w4iHoMPVb;JDqM_T8s8UCcJ@ayepO&o#YK$teg-fO+-arXpJe zYwPDbQCDRk(cd_*Wp|($a6~X{GH4V@&q=UdFJ4$g*Bh6zdZHOeV@b!v zOG?t}Owa|ZN8tckfZ0PC0nETLhO~UZAzkN^&AO9{<2&M`+5`bwwr))I0P;5Q7{3A8 z=M%0Q(R2mm*UCK0B2+5x8T$-GQZGq%RMnZ7r1>uXC|h~ju)uXK04h?+z&>g^4&qu_B9N?ott)SVp>z_NPkSG6dEN7cK(_dUU$F=A zTlqMuDR;RZLGxZ>29He=Rt&qM?x3uCrlaVXcbS=qcN!89LXgj*0-JIX+k%u-SR8)X z$c_dXXooS>9-vacIPUU`B)SXd?evtb1fMY~f_8VD<)gbpD@)RIHH)Q-Xt`L!!35O`v%oT=Pg6sgf)^S4pP9 z9YhPb33O3BfJJ6=Ichxq$_tIkLS3qdQ{Hot3ECa9E~%l}f_+Jk&Ep6Dth@$3fhz7&ZdDyr^}yfqO2G2 zU2{s$>*`@vH`>+RTe>ueL%Htf9WSJUrzc<$o3%%_=;Jg8;dNHI)ZNy|ALG8JZ5(+R?LLssx9_Hb*chayJg{LF(xSTYLkCtD(DCIX)ouOPk=UOU4JFDWTw zgE)*k1&X%ND$B88^$U3bhfO7}E{No!=XjmvY+(wU4yA}kUHb=tjMu`72D)>xTRN1}w=`Eus{3q9d z)s<4!Jm1ytX--sGs2{Gi(oxxxlW7vbB6t+c-W{c_Tz>cCs^ZTs^E#3*EF#-67LxXa zf18($Z6w>*9eRBF0+Bfk%WEs`T-PFEvRj-9#_JJ?6I9u3RVYshK{?vl0izpJqF~1X z%yb?5L;VOHC#euv_12}a^~Zy{HCUFzamAYSQFA+zttNcs8J1^z;7CGlOheRtpl(n} z2(+Ye)JPps7V4H+Rx=lj03%0CWbA`yvf5_ye?)?VSeGLnP*YK z4@WqF<=r^)5H}6!-7n!_mQW`t7v{{4+QdvTGRb-(gAIcdVIV+ci3BNm&-)3S*j{9y6Aq> z`62LeB#uf|xMNid7G`I5eca!)`aik2u+fHfyI`kJ$(;}aQ;IGOeZL*ytRBJGA4e&B zrph-q)|kJ{-x2g4&Hqcea|iVWjzkgRh>ShV-k^x5=xXJEz(s(skS6>0cT5mzd%<;s zx^zFQ0kh-LicQoKrS;CAobzdi9o9CPLcPCQx`k?XOwJ$7B1oX|Xubzt*=l_QXdfoN z2lIQL){m^!G>Fz54$7%4sPUX=m`?X;woZ8*|0@?+IW)@CeVXB2f2g1b-lkZJyoHe* zX#e~=z^zig9RN1#1*?{W<6?&Aqg@w=@$W`;mc0+S_k0Jl5l z*cO*9uz_hB=3Z|*FBz@CjqHEykM{U46BX!8AmgS6{Wtk7h=kjnfc5t4|4>1siUBb8 z;;+)yrpNZtPiO*}J%An_)OsdJ1H}F;JnWeW0MeOa(YK+cJQf7v0eMZKtXf!P$75af zZuA?SZKE7{>sFIDa`q?_Mj^k{>0##%_D28bA*Y3tfXx|M#vXQS5x6PXQ}=y_`ELIy zo{S%Og+M62r2etJ?BDHuXjD0!E$Do)-6!gGWBdD8XkXuEmscFQU}CFT;M}}ihx<7+ zGNQ$GS}y0OEgq1L29#&iUh=#OJ>abP0fjD`QJWo3<=8CO7_~X>pi`_7av67;4WL|f zATkEWxSg)dijr{{wY$KOi>0>K{e97FKzp$PH?kD4=dsl{i~M=fq$BXnq2J{#8}`#a zg~=W3>&q0XxK_aW`O8JfZ-*y=2388BZ3AzpA7qTn`wX5@!hY*vGj3o|K`m1pYx8Mr zx+IQ624;w}2k`D^grM^QyGb{B`R`#E%hJxElsb_sN@gnHcBwC zdkz4M;0|swyVZvM!H5ciI$v#Ew;tj2VqqjuZO8L8)#LOQVoHF)(-10T*raz+7ppBX z^9~)l+w+Zkj+((LGUyI&UG59Lc__`OAeLz+EPIZ*CdQNzIhcXpx?&Z`(ZL{zbFkya z&7CrX@AkZyEyKy4U%TSeu@C@XH0f09FJ^F8ZM-RbBS8_$xOn4yh1DD>)xVRQnb{9l z>BXNZ?k9F)jB2~EFIHG|OZWhmQ=8$FVoCVqmlza&PLCPI)@0EKvNN!_IVY543do^i~xg{z%W4f?}G)NJBSP#X2a1W z5iBq^DZvr2dAy7hT9~MZi?v>?`girT#hnD2k)`X zrAht`2e(~wJr9_?osDICkNKXbkWN2#>_dX^a-=v8%;iuaf5JE3cROL{UAM+hLvAo= z{wjWY#MSe3HRwx4a)ZoU<1zVRS<52)yvO z;cqzsKG12u0{^Ip}ka& zfdi4K1n1pV^WAEXHqN5oD}Bc+%OdWZe?6&zK~V>^i0yKHqd5$g8FK=p2n5HMCIY{x zIj;sopSh*8E$I-kumlu)2^kt~1r2-kWJL@F6I7eHfK0LV!|Ci?WcwQw<=2O77fie+ z{UU(P0+cl#Yl??SQ+lE(*;(LjQo;Gm?U1Az;Rs1LXCj#nO_^X&EVfzn(?HdP1OFVa zjESUu=XE@#$lUhH_U#DtNd)>?%)REbSPnQ{jv=BxAfLKq7QfuQlhkt14HkiKb79RH z4eOXXAB88a;$ldRWHxcm6&`6AWM>zl8ZW3oN-l{=fZ-B1f2fHhSoFo@Sj!BBU{UFIYj_W5!e zyZNCbPu);sCs(DQ9BvRS{=c%}A*V4+cpousm0 zwgmw%yFNPzMjjaxu!QX0Ue710>Ik|~P=(0%-1Sggv-+N=bE?j(Uu?2a5w?ThwPi_J zs>j?ylW!dmnvckNjg6G;-wS+mM%sv}AGdz`>SBJnM=)h`c>REZOzuo(~-*HseLdj?}BE6{~og1v-=Q9XuT_cA)(T zrLP!f0WLweW#{*q-q2{9X9)-j9lTb59F1lBMs#+gAF7PBIrgD5FPmXFk0YJ?@q;7% zwr;@}8ZyNY;O_O#=oy5A>I%ebZ^h~viq?DhG7(hSCdJ_?Miy&(S;FR>yM8pv)L=_v z0Aurp!DX$Jnx_Sh5W*Tox;nwc{G#ce>$@|3W|W3VO4JcaO8K!JXPaE%0oMC@TG;!D zV9JHNQLv=Ofs{^9*0q4X8+w|PpUFbI#Q?y%pH9X^N3!-M7sIj%ZNv)LIkJWc1%Vf) zh2n>Uy|k@((&fZ>g>cKMT>q=Bua1kl+xnGm6ln)gK)OY8D5XK^P&yQmW{4q01f*jS zL8Ti>L278Eh6X`FW+-WpMq0Rge9n9BIq$vx+UVYNO(V-)}q^Q6U@o zLNKGu3rY14eA>e<(d>FUf8E~M_h>^{Cwv8YGw?t+hX$Xc7I}-Qi9FqWKb~FQC(GBx zENm!n(c_2|o!EzvXXa3`Ctiwg%cMv072j}9x)}K5gExm~-YhD<{z7{c2^|-TTcuaM zQ$C)D`#t#$hE9M88LTMClq(e7>K4bS##QW0a;o6iFK}h(<3^OPO9F#&VajlQ;F^I% zCZD2B66x8pFZ?y>+G4G8(6!i&-%d66j?Ls2m?XdS?BBX`X_n8fPGpud_me}JWd)-GzWBmT30-@MeUjx7q!+WM8CouRp%+)4xj$A=(|^&A zilWHVxJfG9prte2jx;eU5~&|FUQ(j0M5GGUFR8#h zGKnQxzQV7%o01pqUtcc0O2f51x!U)fKFj8}5f&|{*Iq^Vf1Sxz5n|*PgLRz99j!Mu zZpS4b&lA&&?Cb`k=9k&MZ;3=|Rf`V0)dW*e`h~5Q*ovA*MN4kt8t@|;>wvB}cE}3T zzJ*+q2&qcT+4{{C;E6H9O{}r*g!&x{rTrqF_G`4UGzll65r9v@A1G8}!7H>Cxi#54 z@!Ef{Z~t+B9g~dbFR>;?iXc9I9vHN28I+GFqQ8@dZV&K$O^QBtibgSa5BN9dP(F{r z#C+Y)4gmQNJj*7%qHW4Jt_4Ur{*)P0zH^;@#*|*mpS{rtb}p?;08KZx%?+JBz>iaR z6t{#K`d0=C*Jr~u(^BM(7i1)S%>s_hRt3Z5c|+7BZ5HxNa669BG#{P##(!ZfP7bQ9 zEW}|`Lx!c+w4nGFBER?T+rAO=BT!|XA}6}?%MVB^ZmMiYpA2nFS580?z9*A=Aw1_dg}JPLaTsGaX-9Ojm21Zx542NkQJ24%0$ z7U>oVl|RMDN;0D4HJ^#=FDr+c1Z<7qZRI-?|N1HCapi4p&z2^aq)Nb+JoGOMkxav& z0or+R{|HD6o%uWpx9PxJ@MxQ~R=pYKOtj?gciIHN7xRZ&-G;oH!e2450o8VI?~{@P z5=r*uqnSkUhXfa)B$+IBt*(oLEmk!a!eG2VL>F27AnGd<72o?_ZpgwjVhs8ZR4Bcm zu2vvOOwEAP2*g{|N$C{MO1QJpN*~VbwN%w>BmjnL8@Z2;F}%YgTn}0d%zZ#g<%+=| z!cEHkfAq5nAhBdCY;~y_3Iy*ZL5^I=iB%V89GR8-Qwx+W42qtHnT#cV&j|YGwes@_ zCxPnuVyD$(-bA*HfMd7I@SP~BgTC(qNRbnBC|(rfvN8dpG3WVld~}{Sjs_P22B=V( z&!V`7X4`C`pg~K(+{M{;Jb5_23~cGGv7kwHQOaYGGCNwbGVV2jHZHDByDE#3t@+QS zSS5^d!uEe0X1R^+&>>Ted=Ad{s}QMz#smmlF>ur)8Y**$k6BqI2XU{tXD*J9!i_e< zFML;STJ)13Rkvru`&or}Q7g&A=8Dfs`STR2z?Ex%d^u@BDKh+C%#qGFhGOxxYFxT1 zi*Md)5If)g5cNZLnD&%V9Jxd%^hEVwen4}SfbdIKM5!NcRuPvRf+3FY zn2!@@B0B4M)UYH3R4v;)SYN*K7Jq{eZPgpF(73**#iuAl20MTHQP5CH{ZlH+|A+$) zN`!{ep_V@LSS2z4;InW3V}KR<-tt{#k$E(|e%@La&=be3udff#Y_H~J($}F(`I}x9 z6|vGkT-OWo+I#?2;=itK*TE(D5C{H)$^KUeCgROLvF!8n2`wd~hY4qG!FWJ)%@BP? zd8;m45xuw6|7DZpJ&q``|djJKIZIjQ*q}C-`SOI%J=qoGq1@Y&QsNEfZT}W z<#`XfQFsC0#F4>u;qDNNW|VXPh!Z8mX{+Wm#uBkgoQhVNx$4|6`fR8zAFpZN7ydk? zBQ_H=2{hf2zGJCfz+Z&K3RkZu2D=G;q9SBtNI6EBa3FBsxx@RM2))IGl_~8b8k^p*uOiyUE2{Y*r4DE1O=u{Da+)sIf8w+&MRt}-_=Q`qk zcsG2VQUl2vLfR3|FTFpdZQot0oA0oljL#qzqG%P>4mbaVnl9mq!qBECp{DJxmJe|0 z;~>xFXgWbg#gGOwaA2o1`TSZYYV0T=iV31$nlCaFX4 z(I`y0Kipn`?dV$08VwJ&)5d1?>wghB%Kfwg+8;qGMX(NN;d0I1#DGr?Wi}Khzr(O6 zI}UR7?K2;L*KJ+%ad#`}Ef^^V3X5Bo)W6L60))vo22Ok!ET2ZT285fe(OrCjSAUYB zhlRv(OVyTCw49bVZvB+AzX!3E~`A9*6mw;0fyo}c7 zlM!(iJTl9CT$7Z<$rqKW!_NEjA}$ISBZ5Acdg95rbyAz>n}D*phJ=jyzl*u)|Em(E z0yvs%lx$3rv?}Q$wl~zQ#v!gpB7~f9Ai~<8wl@)&s$JgJ(`d1RV-FU01lBqS=K{u*~V(dYxsF1lwZ&c;g^-jq+$Um*Dy6LCK zzc|Qcr9E$IHrp1cTL(nY#A|Us;3_(s_+_Lg`B-_fuX&wKFN*_^su%ZD5*sJtBSAq` z5!2XwM9IoUi3T8V0J&uFX&v&Ho_LyjVIHHW7K{U?_8Hmt{*`62-jYBUEA-4O%8PuW zfo6g0wSPS$)Vwi)VK>&T8L+Gg+$Q&8(~KuiK@N<^KhB04E-j0ozT+Yy;vtM(jS{xs zit2e0n73^R94dcJDI+6)-7yZ2{zV;OshKX&>&cu?4_~Al z97VH}zXSb3{x93I)uX}_tMwe)!V8>IfEEG4akF~Y-|r5KaA=sYjvIy5UeKRCCv}yR z=nMOM#W#5+Stan6%K_`;lr(dYq(^!TI?8OhvRA#=`s{u~*S!?FplFkcJ{hJ^u2;P=~-lQ3$Flwlwzj8 zgF_#h?9ts}W>+**0vT9tnFnNSHO#35N;1e_*-rncQ@_ilzQX;__g(OY6hvMD6Q0QrO&L9nad5g&#q zhu2X!!G~4qc_xV!lXF$$mtEN3T9Q5igjITa?+ot_2q*OXk3KnkD~?mPafbr4ixNMM z$bQV=zRD<-p&fDd8}a+o8!uyF6}G&W_}I2hPM&R7hL{4zwsfs~6FF`j1>+GF4=#WO zvI=2T^c2%ov}yq!TeAsgwpq@rAYPQpg>%x#c#;w+RxCPvdX?{CAE}sbI|(hXQBkjo zmeXQ&ddVX_D{e5}v!6I#+(tk-OtwNv+2G0{ZZ^5gsioz&2&ONs&iOopS+b>a99Z> zXI8w)G^oeeCG@w$(O`r&tAV!#p(ta4!zVB$mJVP z!p58xFC6|%1?tEL8*!M!|nIvStam)*pZ(!F9;UHTWlu@L zf0{8+K2N|CjAAyUG?mQTfPP(%iEXNJe5*=&UA%ieYmF7hCR+U?-^7%fkFFOZ2B+ZkuG;;f9i4Y zEs8teemGMR|gF4{AtT+~3Vj_P(;BDt4NkmPKVph@&gd~&O6 z=t&YH>jLpFT(?15IT)(XRwoBL*w{lVZvnBDcDe*RF#E?_?hn%49TmupejNfxjZ_t5 z7UZ~$i>%z_@Hgj!Ne1Pf$CD%}lC0FP-F&65@1rfKezV=)V>?;}>=2FV5{Y8Au1=GweTtvI#?A;7TNS*RN{>%n z(^x~LsKMB|Bzf^h=w5}03Fjw;QID)0vqaT}>lhcpS?L)K%OWPvRs z#)^gUz*o8;IU!9&`0G34uY97&Kr_Dc;x`6G{VS9_EbGHRD9&mthMh+#-*v0l&96p1 z-bIfntdUWS~s{uUbLQ z%qp4MCDS|zAW_Fz%?0*`bP1lPL4-wMVKNf-go z4R#AQ1S$3L%pO%(+3tZ7gu-C+?IX|vlLjoDKp;*~S=2fy`y|3p@GG(A7$bJ4CcP9$ zu-~-1-YI}z#Kgu?`fXv55OF8_!a|pQUf^4BN^-~3AI*Ph41iljvO0H4QNpdS@7|zP zY{g#+3K3wttff~PDr0eQ(_n&%z=TFj^y+3IBV2^H;opCQ+RP-aLIgoL?uvmty#=hs zfj>Gla%mlS_{P(8?(vQDnjonE8`OS~R|iYAW8`y*l*pW=K{#H+D;jPP*}Y9ffy&Y- zwfa5r^MAc{W$-Coi+D=pe|@TtYW6?c3Iid_vZV<*<7*~0420dKzPChISxUv@-$;!| z`ECKLs^FtfR^N&Z7xb!-8^GvWX3=~)lCAi767?KvT$$IV14gc5@Aq?cU<;l6USTN@ z;-{Z{`VV2I_W-6O3z){;l+PfbhY9Tn+Po*&u2w08-A^;1RM|G^#`QUqf8lp#7Yi<@*h@oj8^j68T?2 z*T8FFJe6qVff!!ME7s!4c63}l@it$3|`#3W|yaM6$|zaJFMyXVMoP$-}uI-O05B6P%(Bkx?=8l z9}I)^8&lYCqcMurbO?XqQO_uvB0zw7n<#?uiiI8lTcoy9mAV>UdN+6yqOl93X5>GT zFbL&Z{|O{M?C&bNG-Z5v+4QTbf9CSy$Rh}(U1GC4IzJ*YNfZ^4`84#F0lVSy=hj<6 zmuIs#HO4<^!)$UtY-{{b53U4v9B+6rLw^Jg^2TxM1RX|iF?kgGa}%{5O3D(j#aCX> zcIVBTiDjUALuvJl5xAQG@YLn*w;6-;(){_VDMaz{WxfO6thOi@7RHDknI~=p9!=9v zVWr>6)}SCqGokb;5YaaO|B>@rKj&5-tUw z=^UDOI$%{_l{V$K9fOF~;~K)RVTI!XY~amxGNm$)cC=w2>vjw?p`$Ph8vuX^D&!wqR!xp| zg-4U>hPA!%7k&dA%~Uv3p9G>d%$m|IZ`dBy9$wS4M^*;6WSps z7!_Fc)_H$y3G>(~mDf+?$FCZ~agtHf0YO=OYQg*1doqfkf#r^MUiA%j zGry0!{dD(d7oSn7q}!ZAjW1wu&H;?@$#S_kKbihK+5mbZ52Z(+twV0OPj!QEl~9Jg zo3Z=^NIGZ3P@I&-vETWIlgC-oeUU1658tfWjVA`m54F#avSyF zY;dFDiDf5mu(J6H?4Yw|i4DHr99Ayuj!hIE3W9Y3u-M%n!EfCGRT_`Rl`WSSgjvF; zy&~IufOz?A;GJ$dL&bf~Vc`MZU0)Zj3ryB1tO;FXAklo$hdcL>>4(g`-|?|Lh8S#fk?`KAdoEg8 zHU0v4*|$0Ta$j72a4c89eYBKf8TX)=dLgH|NGH&y2leN7MG&*JqABmyhdY)o#}&ap zZbdyAA-e2(osQx@udsec8t#q%)S8(Ie*qz-dgYU{dtMkmq3z-|3Z6%@Zc+x2xVA5e z;D*mAX&rI@E{aHRSa@LIE#jw!qP8YF=6^PTJzJgP-so)F8YF zff*6N&zpZ=q=KuLY;+4AY3(9|n{?kd_fDLS1KLT4fbSOHXXSUVm+r|ibyI!KzUNLG z5EcSTLPQSP6+uojn{D&(C3dv113$0ylU480`KpkDy71Q3k890gi=2eyJBZ#@RW-`b zrkP?UAfvX;yj+T)P;OpK)Fk#{m&J(>BlbJ{IJTwOwcda|IT<+l%P~%+%HeWkQo*mE z6j$+!f1g>A*tchuJD&@EqQQOX_Qe>(TJATvtuomiMBTgD>BF;+$-C9T5RBmicCBxuBzu9JRnt_mX@j|_TQnqbH=no>7EI~4-Sm*+M^yt467Z+}F=6K|nRNaT;eG589lVokC( zgZ@*abJ8{T2Kr!U)jfbfneSvmzTEdFjLpq>RtABtp~Y9=KKO%X=KFp`#R(ygssgAJHS;YF+O!JK;L)aD8E zNT*UvUk>ok@8sutE;5);15zx zmDg!L%jDAg)dBV{%fKf=p96_yKbStTWQbT>L!?>`l~8}n6T2`;<3wPzGBExBxkjjQ zNlZjjRjQZ`<>idkWlVkNQjNb7wj-RG8lCKqfEeR5yz>y7&}80K%0$c4ezEtBcov9Z4e%zpiD|zBr^YX}`cpA$3X1s8~ zmp}w`p+!-7*bE!Oa5l`dffxB%PJh=imu=p!2z48>j-SMT1fVIsKG%d5j3%??nFqT} zTCcX<3OxOC7b+qID=gLFJH-?PNXB33(g<|%8$Ot-RGfq$rNntv`ac$)U^s=mSA)jx z3frvV;T}gtGt{>wDB_z!gaC4Y8kCZN4$IySi+;Valv6t|FC-2=mq|z@FkBg+uO=4o z_l0%^Y+WN6m1D1@CDCYIXF*EY{j}2@81UzWOR-XDiVzOPvbvwwWJ#B*4^Q%Ub-kYF zxNoT0J4j$}CP+UuuEj6tSa;*T50@P6vb^BWYBHV5JOx*5(p8gd0lP{%`)Onc=PKr!t5L){9 z$;>CsLJNUb{|zZ(08#}S)La42l!D9M$|0vmgwd%cpY14QwuA9|?^c4_aVv@d4!sIN zCg~psN6CdpC>A}=avcwwriGq(?S~KF(sj>t{=^zX!MgtO1s*M)l_?U&QS8|Kwq4PM zA*^kG23SfJUOoBnXmM!VZ6)g8F_7BuerVr3t<{rX!8N~==K*)7v~v?@UtPEeK%Tb% ztk0NQxNx#gX4~TeL1CA;mav2GNAW()5U2}Kq7U?uWuE^~jl5!mh zp@Aory0-rD#;+;%Xj5bcX%AV@^S%&1BTdHZE68*moY(b-Q;wRkVb7IIKfIR@dLd9% z-=`#Z#7z-kw(?zTtLU^xVg)iZ>oYEeRe`ryc3liU!u3x;L4LwRm&7F zY!l2~8@yh3*$K?4U44z;N{nwxdloflNwUJbK+_pXvM+-y~LXNKV&AQGB(139Pl-p-+C{iG3gb}j2Npv03BN>!bkU#X;;0FQAf#8p6n=Af}%Es zMas;MT9UO0Ol{SGnR7W|xb2{rV@whH)U6!S6V%bQ@__FC4bPr$xkdiJ^~AtvGb2p` ziCT$?S}=x|Ap%3i(>t1gi3#<14Sn#y0DWHlC#6@-J}sj3i$pcINrpw^0cDM68K-Q% zBJ3>4^(4>u!-VAoshF{s6%7opjywaB*TGdbZynM(`SRI$*L6`n#-MqH@Cs$TY!WXy zh#fNQ7+BQ2YN(LrVtf-}?rJW&?Ow6Ixo%YmK1i(E*1C^Zg=@5sG_&AM<^D3kNKE;M zZ>C}DzOKIgpmxHa#A0`5FWGr<2gX*%mm34BE8QC26)q#qzg3e6#AMbi0gv`w(vVFc z7Bw7v)kMaB8)qS32qiT!wa{fun?xyk{njBwphIX?ghB$gM#Y?N6Ui^WR>W#lKcj_Q z7Bh&3$4O{G8tuQ+2h9*w+S*;UI5Je;YM?FSk(XcWrpOj%ZLDm|D`;dAgK#Z&&n*K; zYIPSEVkiBpTe#yH==LAnUo?ctm$ra1bSTT#1A`kf+ZKi2-cAsc&ecr=$VJ=2 zng6g}+^;P2e32`fPGAZ|5aPWj9>oDJg$1y`Wzbv(l>H~Hbz=^BAlcuiZQJggn;_V2 zY-2uqZdFeWMA~klz4Q*Zyt>Fb$-Ntz_BM zCJ6pOb6DT+nLSR5@+QF7xcvn^!fRb$eo@*b?!2=bLjwgRwFQ5_XVZ#BP#LF8KwDS+ zIXKAbJ8bqFQqWY#RKi`E38LGWDz9$tzK{WqnjJ@70b&w=-eq(0c zPO4e5LW5WeqOPdxOcT9y^}HBWJ$oBuIKxPj8y2tA<%!)t0tq+`XpI>ua<}$YlW0-8 z<%r|Kl4{ogusE)fZ2MmaC{qW7d9~nOK>EaMpY`z-CP1_ug5Bn|$LaJ7#suHa$aU9!CPpwnr;4eJ>bZ@@d z^REJ6kS=*|2FT0lH?+Ycv7nXoT^}IYe(b&xlR{S}8yZ;A#Z+$wwl#o(0`H~`>S!)} zu=2GTb`F!U)!j5Lx~+GMjKFT_hwq=}lD1#Qhb*Qiec3|+-!~;;KgZt(9T}U-?bAc5 zggYa`XppKjZfS+l7(dq&$&JkN^laRtfM*Me!%nmC#c@oHKlJcN(-{LUNd)&3`{dwg ze%Mw1_nFj6E@c8o`VhlJewupU(`fC7n=`(1N@@0Z0B5|HCEiMEe zFkjN;diMH=R$#c*Z#jr4HzC!Bkf+@?i|P|T&#q;|bT;1u(5@6m?zSu{_JJGQoqI+x zbz_%tX}^W950Q6J`0mjxhPYP7$L5CX&6>->FAN{S=X8VTQ4|LjK?^*Sp*mghHb+EPR-}x6f%{)Rjs+qtVPh z1Ij7|38_~&;S|GE?S)K=>!F+*d{WN_TitMT4EykgRD7+AAq=Cy zKJ6&kGwCG7AUT*&`R>3i*&Na@2DDHrA3=I6pU8%g`GU7toVi_B;tKoJXt z!qIFDE*=8X#+gWwhUjqaK_q6t!-grg84c{J(}IFMa_?v@hP_j)ATzvWCI=TaR6$ba zv_&iu+C*-SwAb`H;U?Nkd^bu!7qlVA_&NtUoJQx`%ELad`l^oZ>B-9>Fw8!#QU_~> zLf^~H&rs~~`4_VLqzC>#n5j^(0Pn10f=h+V(M5EnvT zydWf}P{Gj=6zs6rU9rQOp*UchNf}5ZEYxrum7H7fJnX~RvN$R7o{kMeQ2|^tWg@;u|5 zV9OUOrk*<5Bm2;9%Ih6j5;HyvL~=VgX<)tQhmPL4hr1ZC0)Zs5ioi>+0Gg3fC>-{B zhs9nYA^JIISsET96~~#q?xbDPW^DMiwI<`~D%~H#ImC5Flks#`_lDog75lBnR&;6n zJw230Jp)S~+9ppAeOlRD>e4{5D5H1}VcLQa$^pkgk%!uYN3uoi6xNcaiGFwWPURor z^&wqc<4oF=!qL{uC$Mla@@m3+eCteBz4)MDI}YB22P*MR35?q9ZoRjcP{Tua-MJMU z%j@K14TZJK9@5|?^Q2?4cyu3LUl0nkcN?b*UT9@Sb{wcYu3uBTDR_@4=ETx(J^7Aj zJFP&4cxk{E4qr>*;;oI^EOqs?MQQf= zK3}x6vdhSl6rxh;SIlf2cdWyY9EE9rR}&yJD2og3P%en4)U(N)!?%wvB}mjS*QmHL z!GS!XpAnb+Eo`a?Z6THL*-^`c3FNz%D@Y>;#|S<%a&g(@a&^XF+C;|^4kTGlmqH~b z>f1A4lMStcJ*wC#s6%z(Cm5qfC6^V7vSOcR)Wf92S60t-ZOCpUSNY(Go><{bWbcD{%iudJx$Mp0 zF0fuiKh52^+Hh53A;W!R-F|ee*ZCd3Qb%D)u9YO-R92|~r>YE->X)UZG&JWB*jr;x zS8lYrF2Lmk!|eR3qSfNw7K&_mt2I&%4qO^UF&*kI33tdfJnW`GMZ%ph3=ei+jrwch z#I%dcN|IdDHC~Fr!KlITsw<92fVF4wy z4ub}aOVSazxut-kCDLu!tTuaKq2a~`J57apYw zg|pohZtXQqO`Gd_N58-JPNyWzT#vwb8PhFEU~QdIw0x9Ik~(E(bfbGabPTy$Aal!? z?R$HFE64OE3lB%#!{^~A^c7E4?+(lQupj!oMs1GrhNP&E?zM|KE|DV|-z;**v%~1Q z66dF;61Niy=Jlsgd6K$=4U8GM@-xXv9^q0Q&2}!<Qo8)elb=6Qr5z}-;tObA15 zwh=!CevU>}myoBR>G8P;u>)e?LUgd!ujz}f${=n=?9u2x=3Td)Pa5qtV}9xHkykUM zoRxWv?g6z0^7cN6k*bJB%|%Z3O#$wJv=5G*pMv99@9Y{LTh_1D{*3uNlvg^KgchBx zeI*;PZz9Pr41;_^h;nvGX+#iSGZHTpQ0fBpW55x7*JG%BI$X;qHJ_zf=EDk0vC3+m z36NO;=h5Zg-=SJv7Pr&Pjrl@UUwN}!U(s)e!G6WAnsU^_?3bM)ei}54^-8X6{~^V3)|&JZy7Fm z)Rn;Zz5#6v#?}83yPsQ{zSY9vf^ne3TItiX${Wj{=~PgKRT9<=7ddrwCnc;ZY5g> z2h!{zjFdV5<|cj`9Y2F zkLJjy+|UiMSsg)Mn=e)j;8OzFQTKqFOY5bZIjr7S$p7${RN$$nB{~AsG3()C-E_dO zv^ieD82yVBr;ed|CHiM~%;sD!1VlA@|i=p>t@DTo?8;gO(sPwu&24E{O zg4ZCGXVIu#)&|VgT{>VD0&3$e0_g(m0khcPQGn8+d7GpHQsp?1DnrEp0c68~fGTqU z-=kiZE%pK_cwvPMoY8=Q!bE)iyIb2=Feb)o9K`Zb)5VyEcOX0dyE&RmVXcO*D{?Fc z7@Gd>SUHjhLLSVo>QhiP*~=5y8@hgtSO~a(39iwny`PfMrYXVf~oEwaLp93$BS7n5(=UKnIBb z|KVm#Gydy%f0}2{nje3*t8|;APVcwx@K-B6nECo^wzai-0Q4-YyEE~&`y+`VKlYXt zM8WeLT$P5E`?w-ac?)B%ujjxt|-fAne2=#H7UC>#K@P7G?q$;j2fAuRQ9oCh7pDg zvZTS-m$H_|SW?FNPv8H4*Y}_6de8G*?|IJqoaefq`+mGIIm~ zjs>=l_P2fVJ6q=bO(MyOeF>b8KBb#jV1>m1F-5YxG9kj%I(&N>%}HG(cFR=!0_Dk-lC9C`hIMM zpn(ZH$G@XR^8pQf;pOnl&NDI9a_XFWKQ&Ja;c8)yvv8eyBwo#G;LAtXwut5)T~|m`V(3 zlPYk>GU6F_pFBRy?)lAMZik2OT$_8pjZocQx5Rc_@R~4yG(z^ytL)KSOBxM0rFWW) z8>?1+-!Dwh7P9eZM1T*4bV@f4!BgCq4)&G%8lMBVIlgK=qT=32?oLP%!xM!d4O@30 z?OVrY{S0kpKfPFu8N0fndwHg^%>A*F(U8{Sp-eC|GyF6Tl`>*d^ilX@jwUuQyvW_3 z_;gGH>ouvBIq|CaWd(&#B|5tFFNwZ-GJ_|&=uFFGlgcxrE9-A89Ri1yb41UeQx?fN zfgA%0@eGiAv|dR>U!8_xV{-mai)>R!#8_5p&ClHH733U|$C;roq}J`NC$6KxlZNG* znvR4+^}lD6zHbu>ca(;zW0@X>anC2)SPxourDI387AI-7%yL$kM{w4rMpu5p$oFfzP9IeF>ji9x?eovB~O*U)GFqz}jSc zf?dFqpVOO;*I_d(Yc1W+-KRlE5mR*V3Ystf7DTV5W z*#5b;TW`*_kC5OH2i&QS$QMn7#8p$THN5IW-`2}>tL-f?jYpm9y_hSKLS@QYfrNV| zERkYjh+@lvHl0|Rch^m-k(wChgC#hE_rn5K(Dz2RrGeN6@f;k5! zLZ2eXuL+;Dsmg^#T7h`bAO9+kG%bV{^(5x~@OlfYJ%~6{R$Ti?|*k}D7?Ft<9UsQI95>ioT2Q!%v@8mQwYRFvW?$u^(5-E=jJ*pj}*DRe!IF%M}4TaE@k@u>VFuYKot!?yp#eOwS-BrVI(9!rjuOV;k)(BIu=lu7R>}WfSof>EGz$QUbfc+Ji2mAXWIXJ zSbx3%bueRWbx9CT@mf~}!=eX$CVBJI1AVyNPm!XBxIs&0&*7B2Bv6=OLWy__$6orB zZx6{s8oc4k4WdpN$dR6=k|mnsFDy#wXtZ^5G!a~#23h4)j3MzNaNnKs=LR(8$N zIn#@*LWh3ySaCO@MC+E1BgX`^a!9Urv3}zUY@qQc!8e8Al!E(7*4TnVO&&PnVDwf< zABOLpx(Kc7rdc76r#Nr5uDlArUQ28Vy()z1N|s^B2U=*^JTyh#Fg`2_mKPQ+(S51> z%bto#pB&JD4mpE-WF7{iTx-)#V`<@huT6W#!XWx_5mH27VLGJge#?|^qD=%h2n&@4 z>&85F3p}i5BZH_zDI(r_;RyF?(-RM7k1|RcnU-kQU*q4I>+4WDnLI6%on+Pj@FmQs zy`fXSOz#HG&1XX+H1b>Pb>vwoB0rqc!=sl>m>N!-dM#PEKZX?1!)U zG0WAA&Asnu_b)}*;x*n}bj=q$cFm!?CuhUPeA$%ya6?yu?sZ8oS(_ZBV|@Qm4k!dAr6q(q;DIylUGu7kpE6UpZ@4{wwkQ-jVyu*HwRQ)$27Y z43zT;w^6zy#%j1h^rMzALXjw(wn0pyLveNPG9gi}+mqTS%>MG)Z2R4)LhtR6`YPR( zliZj_Nn2olBJ=_AJ$I~`+Kuke!lONRbH0&sWWb~z-RAh|y_!4Q9(uNwUdZ5Zli-;b zg%B|s%1=t0*~TiDbKjf=?Mp>PZQuSm*!Un*f5r~mh~0Z;{_RqK6q@lwdnIdgaozLB zId zS@(}D-pqB3zCGN4YJPo6Mf*&qLR)p6N8*$(ApQhy^bi2#AF%!Z8&_he*{~50O)cs} zj|r)hU{bMB0vB;I2c?W&PL=;EDi}|=BDN_k8Z+(veFd^9bC`%sV9PN#s3B_t!>AucES+uw}XCcoq8P zKwSNk0xtc8nY#8bD&;RXl^-R0q)5UkS2f@i>bi1HX>~+fy5~W?`Xa{>xdA1;6jFjR zZ`OjKC^+XFj4)hWgkKr;?impA!i|{oGi_Zyw#fTO@{<3AMU3fVxFE_i(#`SR%?f+` z*%!!5OMX!W5t3mbw*^u+Hwb0lejdY>(>iH6uQz9|iu(Pg%27Y{@2&sz!P9WqshFo? zRS{%lZ$^@1*>#T|S;Q9}wtiu_1|`^y@)<51d^gv#+x_uUd`OF$p_f(JU2KY2@lK3e zjOp6bL9?-|AGkrsonVB3P^F^N=mf~2j#7k4Y}LB_N0$JSS~7_%?vBh?QQ$yAvd90S z0RV4J;~C?<{o*=^=qNTp%GiVru8O2#?u^QUN#qU;m!#pYl{A#}Np~7?hcM;AZaHHs z;ia?sOTOG7)l$E3I3*i5&!;G$_?Vt|Itjtygd^00{Ib?hQFL#vj84YL0hVbU;~9QG_5xQw}Ay zq%6cGmp5yTV@qHfhMATpB-I>$9mADPuPUN8h>ubnOj|>5=_Q{Rad8^{IRCp4ml`D+ z&@6DSt<)4os4_{F1H;I8;pv|63Z3cJUpKq2-12hG59A$)K$$&~-xiD*^JSx_IAhfu z5A9-11&1PbpV`&5T=O!#OLy*@J#3C!_UR29Jqd;dDZwf7R1|X1em-+))vP}AqbvS- z&p?DL`{XAQ{#M&XTRHGh`w%~hui%1k!_fBd)?ykva%@F$rh3YNwlVe|GUEQ~kPnF) zgm;7?zgcY51s)xxic<$P-Ha8XO$}fa}V2UKM9%2SVy4~ghEoo)M zaOnK`V;I9JhL#!34`I}CPB?`~%OOlP$aX}1UHDr^s_~x_xZI9YT%yylf(1BvhxH06 zD%VkGIXl3${<+-crZ~csHHJ&9ExtvrlcwnsF+xKt88@YX#6>(Vug9{J7&gbZUTcmI zx|qwyaNT$w#sT6lm&=%e*!-7ClITBr$L7(llSKB7q5at{Eu^@IP~^u;MUp)g78y+4 z&tZ##qCZN~Tlhddx{Cp-83ah8GWS9tUhfdA{y5=8CzLLn=C?pLol z#Y=B!dNFFl#=oI%&jqX)9h^0zch(PX?~boQl-!f&6YdvO-F_=bfdUrPBN@t=w^HNU ze)tjIEYA~IRCKl1yG$)ii|Bk7wDzEx~lsDfmaQ>!-{flC#=59tvMfF9+`c= z{)NCk;DYgZi4Zy6^M>>{^U43}lIq!Rj+p+oyEpt}v z6>qrX@eMk^v74%r(v9UKXYFh{VYfM8pOjA9##P`n_5ssyZn<~e1}e4-Sct>AZRmgj zGh@-_Vs1mdd|dz_tQ~ib*1$Um#GT!%Mh879X{AqV90$hSl2Rewy+Qi`PbL0GXRG=C dAqCrBVeSpgHTe}-4Ws|OwKl(KR%UV~{y&d;0Mq~g diff --git a/docs/zh/docs/TailorCustom/public_sys-resources/tools.png b/docs/zh/docs/TailorCustom/public_sys-resources/tools.png deleted file mode 100644 index b7bf100e26359588985a8703275832254cdb33e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2992 zcmYLL2T)U47Y?ql2pe=)0~(4Qks`7LM1vp*k){HYV5mw9fdC>!X+gjSkrsMrt4YWL zhA2c@C?W!)0vkf;G13Hq(DD;jLiwN0?(CU4=e;@a+;i_e-}lYDMB6Kuz%o!75C{ae zv@o*=fh0)4J6?JR5Q*&<_5qJww=B>hAduYK?=F$0A*Toe$$D6tnK;}n5b(}Nk{h7y z!QWh}_QB07&=P2q@h^0rUA3X4P+GwPjKXALuQgtNCo>NDn04f?cEOHViybPRkG1o+ z86=&ZD);G!;uh8PpqAMfOIRobRKbmXchh@?YMpCp*)6Mg;y|Gy;%Pmc@O^_RaVu_lG{ofE5>Vf_C1%*O7&a%fV!*EH`L;r# zN434;sln5x!K49~Oi1CV38{ouvly{2q$Fsp)-d^1SdT`ZTzrxw`nRu9A{DhxBsR?K z3!D0~2j4~aKR8*&bJ8#$UVU=bbH>k7teFYD=oaZh4Ua=T564fD=tpT+TMZsBb{KFK z+DaQs{2zyIP*jYigK+}dil_W>bhh{UrS(dwJ=MW<)j9HlzSr z=-`zioTRpYDTg2Zx)FJ9Lw_<`PRe1!C;L-#uzIs~Oug>1&~BhG>l9?7Z#zL1g^b>~ zy3G}<1veulUF)iW;?Llps+{RhyCwWneyuIMAfc;d zoE0JR=4lSacnevBjeVsLgynr>OF4_XtK=5uK)+9*UW>4*tJp_y&j-lrt$7T|3%|yR zemWa6@|S3BZfp6toz-z|!T=u;J2MD<=cwfC+^@Qw?XC<`iv=&{b<$XlsI*+A04wey zzPmpC#;rBN5vE?mAj~UFZ4QHbXEQuZyZZ5)Ip;>|LX)CnF)pI$Bd5_ht^_@v`M3IK zk2ZJs4x~Pn-S4u&e-#-cUD&?^l&E9m7v<3ojUGx(536m~! z=IPuXPGplX{&pb4&Q*W$q?6z0_4TP@2c_fMsRy?wG;aC2w{bSIQujsWcUN^xtI;Rc zB(4%lIMOFf{WDRp;gVG)&x-C63oAv@_WSkwuAW7=?if0gqp|&wDLTBNzPH$-*i(EA zYQdb{8dEVX4CC7B`Wm3~N9R^OvCqNxtV@4JDjLaslOu2j-(3txO(`xrysgJIueDvO z6Xhn$mzUQ?O2QRekRgi!Q$tWI1!GoU2}HJ$;n3e{z3o4krGpn1{Y`o3Y7G z7cmqVn_|P8AzKzz9K2^Z2K?zw3b5sQSjNi0YchMTuPkL zfDlzC)4f+-m@!3~(~WC%s$8pH8GYCT?$W>gyZd-PIk=oGZ> z?I#j0$uFiWCH`dz2$ZYe>lXb6e+2RxQHFp$lq@Ra_zDhtEw?Ic z-98MFA4r8cg$b}s2xfW(TVG^<^U<3dAy5nQD#Nb;%M6&&f`qGuV)mLs>5j+=8*+e2 zEU?j2cs{h(msL?lh7H?N-i&9bBSt8|tymUhEgrA&e{Q;^FF=7ifbgHW9PIV|wPa+U zOA`e26P9VT5#k}ulPtTzfm}|O!<5}Oy8WsmV#oS z0^9bCcxwP53cJ3{?{ISepc!e<(JL#la$zw_N_D7T^L(RU8)8eK1wFW6ZC;I zU4#a_^k?0H$(CDZoKq+o%W4Q zW!}G){$1SBYG<}a=nb9a%X$t*TDMT)`FnbO8_Q&_kk5x1gFi0fN!rXDFAYuJmiT3D zDqf2#9vNXdZ6z%zbnuU`7&ttp(HZ|K;%9GlE=J}Qpx!jZNC0w#&+yx%!4ejEgQ<$T z-&Uwu$DAFz1tMqOCc12`hPNPa)!NqNeoexO#bGaXS`E&m;yZ2|?zF$fKHKY??=aOm z%rv3}GE-vA+9t`t*CUaaGjN60Sws0bi^kWFo3|HvQ$Fv=2#xAFyjBn|CfA&o$R+WF z9{QnR(7KONh%qyuszhi0|-nb%%=ub!bUAL6?o0z81;qqDK!;^6R;Zo ze&m2V&>L_O!1s575RR|1W%aOAK(VAF{O8nkOY#rAHi15s&TTNKo)Nrq0r2TjI0je- z&}H2bLPRJQ@SsF5=MQt5(gLN1*j``uxgRiClEK}9V9QE6cMQE`0@bPqNJm3Tde=Mz zI22U-VB-88j_6<_F&#lL0wzx>Bgph5&!aHV0CThx(zQ?$1JA*45Vx{mPM|YSr-AsN z1-`G%xWecZRD0D#RQ>)B%SlwWoA!#2PB@^{e#2zZx#SZ;sCMqqzI245uOF5<(V3sc zF1!rJGAqjJFOwn8_6#A@BlslD!T+w(B35y->zOfyEmw>vr=#v1>nNJ4HB1o{VKeC_ zpETD2Q9>_4>2|o7J1E!ATxT+^0ev8$3lMpKbD0UpS9Y~yG|K;OAejN=c|-Ssfg-to zV40W0`l0x!MXewd;)kTdoshQBfZP_Rga-64sjy*Hq^rZ-K;Xn!%k7VYKhmHxaSiDI z?mBacpO;aS|7q7B%EqM4>&r?@d-F0t6{eee8*|)Abmi9*N!T z!jr}KwLvv=X)jePY`N?M?(0?@hYhRZrkKNVoQ+_A22B&LvvG}0leji1tYg%{bQ7k= z`#z=2%|17ZyT-qOlydWV6pM0qAl~0)^8n+76+F-L*YBdi_pZ4qj^ct)N$h#puD!2c zq(orwSn6sEVuS|#ZG3DqDNabMIyuM5D%x- zonuA1XuW1JwrLN)i(q^<1WzqKW&>(fr?LA>vSjiysJmVTm>aI24XrhNCI30tQ&qA_ zlc|ye)L0Gm1XxyihG%+rxsR8*s2{&o-wP+~($m=B{Q12{cCgQt_pv9yuPJ}yJF#mG pxnWMyAe(HRb|rq+(SPSjUW$!3D|uA2!g2ndvNXS9R$+Q0{{MJ*=YjwL diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cb3b360db..ebf263c19 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -214,5 +214,5 @@ headless: true - [http接口文档]({{< relref "./docs/rubik/http接口文档.md" >}}) - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor使用指南.md" >}}) + - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) - [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) -- Gitee From 2c8ef7e9f6044724dec660f69fe2d1a0b3aec807 Mon Sep 17 00:00:00 2001 From: Poorunga <2744323@qq.com> Date: Thu, 31 Mar 2022 11:03:31 +0800 Subject: [PATCH 012/130] modify app version in kubeedge docs --- ...Edge\351\203\250\347\275\262\346\214\207\345\215\227.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" "b/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" index ec91c0ddd..12babcdc6 100644 --- "a/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/KubeEdge/KubeEdge\351\203\250\347\275\262\346\214\207\345\215\227.md" @@ -20,9 +20,9 @@ iSulad 是一个轻量级容器 runtime 守护程序,专为 IOT 和 Cloud 基 | 组件 | 版本 | | ---------- | --------------------------------- | -| OS | openEuler 21.09 | +| OS | openEuler 22.03 | | Kubernetes | 1.20.2-4 | -| iSulad | 2.0.9-20210625.165022.git5a088d9c | +| iSulad | 2.0.11 | | KubeEdge | v1.8.0 | ### 节点规划(示例) @@ -64,7 +64,7 @@ $ ./setup-cloud.sh > 提示:在云侧节点可以访问外网的条件下建议优先选用 `kubeadm` 工具部署 k8s,示例: ```bash -$ kubeadm init --apiserver-advertise-address=云侧IP --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +$ kubeadm init --apiserver-advertise-address=云侧IP --kubernetes-version v1.20.15 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock ... Your Kubernetes control-plane has initialized successfully! ... -- Gitee From aa6d2b445e5ef2defdb684ca408437575d3c40f0 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Thu, 31 Mar 2022 14:24:15 +0800 Subject: [PATCH 013/130] update imagetailor menu --- ...77\347\224\250\346\214\207\345\215\227.md" | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" index f7b29e358..3902c6e0b 100644 --- "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -1,18 +1,18 @@ # imageTailor 使用指南 - [简介](#简介) -- [安装工具](# 安装工具) +- [安装工具](#安装工具) - [软硬件要求](#软硬件要求) - [获取安装包](#获取安装包) - - [安装 imageTailor](#安装 imageTailor) + - [安装 imageTailor](#安装-imageTailor) - [目录介绍](#目录介绍) - [定制系统](#定制系统) - [总体流程](#总体流程) - [定制业务包](#定制业务包) - - [配置本地 repo 源](#配置本地 repo 源) + - [配置本地 repo 源](#配置本地-repo-源) - [添加文件](#添加文件) - - [添加 RPM 包](#添加 RPM 包) - - [添加 hook 脚本](#添加 hook 脚本) + - [添加 RPM 包](#添加-RPM-包) + - [添加 hook 脚本](#添加-hook-脚本) - [配置系统参数](#配置系统参数) - [配置主机参数](#配置主机参数) - [配置初始密码](#配置初始密码) @@ -229,18 +229,16 @@ imageTailor 工具安装完成后,工具包的目录结构如下: 定制 ISO 操作系统镜像,必须在 /opt/imageTailor/repos/euler_base/ 目录配置 repo 源。本节主要介绍配置本地 repo 源的方法。 -以 openEuler 发布 ISO 的 RPM 包为例。 - -1. 下载 openEuler 发布的 ISO 。 +1. 下载 openEuler 发布的 ISO (必须使用 openEuler 发布 everything 版本镜像 的 RPM 包)。 ```shell $ cd /opt - $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso ``` 2. 创建挂载目录 /opt/openEuler_repo ,并挂载 ISO 到该目录 。 ```shell $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. ``` @@ -446,7 +444,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: 必选配置。是否裁剪 RPM 包。可配置为 yes、no 或者 debug 。yes 表示裁剪,no 表示不裁剪(仅安装 rpm.conf 中的 RPM 包),debug 表示裁剪但会保留 `rpm` 命令方便安装后定制。默认值为 no 。 - > ![](.\public_sys-resources\icon-note.gif)说明: + >![](./public_sys-resources/icon-note.gif) 说明: > > - imageTailor 工具会先安装用户添加的 RPM 包,再删除 cmd.conf > 中 \ 区域的文件,最后删除 @@ -485,7 +483,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: -> ![](.\public_sys-resources\icon-note.gif)说明: +>![](./public_sys-resources/icon-note.gif) 说明: > > sys_cut 和 sys_usrrpm_cut 同时配置时,sys_cut 优先级更高,即遵循如下原则: > @@ -512,7 +510,7 @@ openEuler 提供的默认配置如下,用户可以需要进行修改: > ![](./public_sys-resources/icon-note.gif)说明: > -> root 初始密码和 grub2 初始密码,必须由用户自行配置。 +> root 初始密码和 grub 初始密码,必须由用户自行配置。 ##### 配置 root 初始密码 @@ -581,18 +579,18 @@ root 初始密码保存在 "/opt/imageTailor/custom/cfg_openEuler/rpm.conf" 中 ``` -##### 配置 grub2 初始密码 +##### 配置 grub 初始密码 -grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub2 初始密码。如果未配置 grub2 初始密码,制作 ISO 镜像会失败。 +grub 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub 中,用户通过修改该文件配置 grub 初始密码。如果未配置 grub 初始密码,制作 ISO 镜像会失败。 > ![](./public_sys-resources/icon-note.gif)说明: > -> - 配置 gurb2 初始密码需要使用 root 权限。 -> - grub2 密码对应的默认用户为 root 。 +> - 配置 grub 初始密码需要使用 root 权限。 +> - grub 密码对应的默认用户为 root 。 > > - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 -1. 执行如下命令,根据提示设置 grub2 密码: +1. 执行如下命令,根据提示设置 grub 密码: ```shell $ sudo grub2-set-password -o ./ @@ -603,7 +601,7 @@ grub2 初始密码保存在 /opt/imageTailor/custom/cfg_openEuler/usr_file/etc/d Update your configuration with grub2-mkconfig to support this feature. ``` -2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub 加密密码。 ```shell $ sudo cat user.cfg @@ -788,7 +786,7 @@ GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic soft 使用 mkdliso 制作 ISO 镜像的操作步骤如下: -> ![](.\public_sys-resources\icon-note.gif)说明: +>![](./public_sys-resources/icon-note.gif) 说明: > > - mkdliso 所在的绝对路径中不能有空格,否则会导致制作 ISO 失败。 > - 制作 ISO 的环境中,umask 的值必须设置为 0022。 @@ -871,8 +869,8 @@ Pacific/ zone.tab 3. 安装 imageTailor 裁剪工具。具体安装方法请参见 [安装工具](#安装工具) 章节。 - ```shell -$ sudo yum install -y imageTailor + ```shell + $ sudo yum install -y imageTailor $ ll /opt/imageTailor/ total 88K drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom @@ -885,9 +883,9 @@ $ sudo yum install -y imageTailor 4. 配置本地 repo 源。 ```shell -$ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso $ sudo mkdir -p /opt/openEuler_repo - $ sudo mount openEuler-22.03-LTS-aarch64-dvd.iso /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base @@ -924,12 +922,12 @@ $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.0 $ sudo rm -rf /opt/imageTailor/result $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force ...... - Complete release iso file at: result/2022-03-09-15-31/openEuler-x86_64.iso + Complete release iso file at: result/2022-03-09-15-31/openEuler-aarch64.iso move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz $ ll result/2022-03-09-15-31/ total 889M - -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-x86_64.iso - -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-x86_64.iso.sha256 + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-aarch64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-aarch64.iso.sha256 ``` -- Gitee From 6d6610074c44fce83c7d62f9224689b9c1138518 Mon Sep 17 00:00:00 2001 From: wuchangsheng Date: Wed, 30 Mar 2022 16:55:23 +0800 Subject: [PATCH 014/130] modify Gazelle doc standard --- .../gazelle.md => Gazelle/Gazelle.md} | 260 ++++++++---------- docs/zh/menu/index.md | 2 +- 2 files changed, 123 insertions(+), 139 deletions(-) rename docs/zh/docs/{gazelle/gazelle.md => Gazelle/Gazelle.md} (42%) diff --git a/docs/zh/docs/gazelle/gazelle.md b/docs/zh/docs/Gazelle/Gazelle.md similarity index 42% rename from docs/zh/docs/gazelle/gazelle.md rename to docs/zh/docs/Gazelle/Gazelle.md index 8ea1f3e52..61f298c06 100644 --- a/docs/zh/docs/gazelle/gazelle.md +++ b/docs/zh/docs/Gazelle/Gazelle.md @@ -1,88 +1,75 @@ -# gazelle +# 用户态协议栈Gazelle用户指南 -## Introduction -gazelle是高性能的用户态协议栈,通过dpdk在用户态直接读写网卡报文,共享大页内存传递报文,并使用轻量级lwip协议栈。能够大幅提高应用的网络IO吞吐能力. +## 简介 -## Compile -- 编译依赖软件包 -cmake gcc-c++ lwip dpdk-devel(>=21.11-2) -numactl-devel libpcap-devel libconfig-devel libboundscheck rpm-build -- 编译 -``` sh -#创建目录 -mkdir -p ~/rpmbuild/SPECS -mkdir -p ~/rpmbuild/SOURCES - -#创建压缩包 -mkdir gazelle-1.0.0 -mv build gazelle-1.0.0 -mv src gazelle-1.0.0 -tar zcvf gazelle-1.0.0.tar.gz gazelle-1.0.0/ - -#编包 -mv gazelle-1.0.0.tar.gz ~/rpmbuild/SPECS -cp gazelle.spec ~/rpmbuild/SPECS -cd ~/rpmbuild/SPECS -rpmbuild -bb gazelle.spec - -#编出的包 -ls ~/rpmbuild/RPMS -``` +Gazelle是一款高性能用户态协议栈。它基于DPDK在用户态直接读写网卡报文,共享大页内存传递报文,使用轻量级LwIP协议栈。能够大幅提高应用的网络I/O吞吐能力。专注于数据库网络性能加速,如MySQL、redis等。 +- 高性能 +报文零拷贝,无锁,灵活scale-out,自适应调度。 +- 通用性 +完全兼容POSIX,零修改,适用不同类型的应用。 -## Install -``` sh +单进程且网卡支持多队列时,只需使用liblstack.so有更短的报文路径。其余场景使用ltran进程分发报文到各个线程。 + +## 安装 +配置openEuler的yum源,直接使用yum命令安装 +```sh #dpdk >= 21.11-2 yum install dpdk yum install libconfig -yum install numacttl +yum install numactl yum install libboundscheck yum install libpcap yum install gazelle - ``` -## Use -### 1. 安装ko模块 +## 使用方法 +配置运行环境,使用Gazelle加速应用程序步骤如下: +### 1. 使用root权限安装ko +根据实际情况选择使用ko,提供虚拟网口、绑定网卡到用户态功能。 +若使用虚拟网口功能,则使用rte_kni.ko ``` sh -modprobe uio -insmod /usr/lib/modules/5.10.0-54.0.0.27.oe1.x86_64/extra/dpdk/igb_uio.ko -insmod /usr/lib/modules/5.10.0-54.0.0.27.oe1.x86_64/extra/dpdk/rte_kni.ko carrier="on" +modprobe rte_kni carrier="on" +``` +网卡从内核驱动绑为用户态驱动的ko,根据实际情况选择一种 +``` sh +#若IOMMU能使用 +modprobe vfio-pci + +#若IOMMU不能使用,且VFIO支持noiommu +modprobe vfio enable_unsafe_noiommu_mode=1 +modprobe vfio-pci + +#其它情况 +modprobe igb_uio ``` + ### 2. dpdk绑定网卡 -- 对于虚拟网卡或一般物理网卡,绑定到驱动igb_uio +将网卡绑定到步骤1选择的驱动。为用户态网卡驱动提供网卡资源访问接口。 ``` sh +#使用vfio-pci +dpdk-devbind -b vfio-pci enp3s0 + +#使用igb_uio dpdk-devbind -b igb_uio enp3s0 ``` -- 1822网卡绑定到驱动vfio-pci(由kernel提供) + +### 3. 大页内存配置 +Gazelle使用大页内存提高效率。使用root权限配置系统预留大页内存,可选用任意页大小。因每页内存都需要一个fd,使用内存较大时,建议使用1G的大页,避免占用过多fd。 +根据实际情况,选择一种页大小,配置足够的大页内存即可。配置大页操作如下: ``` sh -modprobe vfio-pci -dpdk-devbind -b vfio-pci enp3s0 -``` +#配置2M大页内存:在node0上配置 2M * 1024 = 2G +echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages -### 3. 大页内存配置 -dpdk提供了高效的大页内存管理和共享机制,gazelle的报文数据、无锁队列等都使用了大页内存。大页内存需要root用户配置。2M或1G大页按实际需要配置,推荐使用2M大页内存,该内存是本机上ltran和所有lstack可以使用的总内存,具体方法如下: -- 2M大页配置 - - 配置系统大页数量 - ``` sh - #示例:在node0上配置2M * 2000 = 4000M - echo 2000 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node1/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node2/hugepages/hugepages-2048kB/nr_hugepages - echo 0 > /sys/devices/system/node/node3/hugepages/hugepages-2048kB/nr_hugepages - # 查看配置结果 - grep Huge /proc/meminfo - ``` -- 1G大页配置 -1G大页配置方法与2M类似 - - 配置系统大页数量 - ``` sh - #示例:在node0上配置1G * 5 = 5G - echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages - ``` +#配置1G大页内存:在node0上配置1G * 5 = 5G +echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages + +#查看配置结果 +grep Huge /proc/meminfo +``` ### 4. 挂载大页内存 -创建两个目录,分别给lstack的进程、ltran进程使用。操作步骤如下: +创建两个目录,分别给lstack的进程、ltran进程访问大页内存使用。操作步骤如下: ``` sh mkdir -p /mnt/hugepages mkdir -p /mnt/hugepages-2M @@ -92,34 +79,35 @@ mount -t hugetlbfs nodev /mnt/hugepages mount -t hugetlbfs nodev /mnt/hugepages-2M ``` -### 5. 应用程序从内核协议栈切换至用户态协议栈 -+ 一种方式:重新编译程序 -修改应用的makefile文件,使其链接liblstack.so。示例如下: -``` makefile -#在makefile中添加 -ifdef USE_GAZELLE - -include /etc/gazelle/lstack.Makefile -endif -gcc test.c -o test $(LSTACK_LIBS) +### 5. 应用程序使用Gazelle +有两种使能Gazelle方法,根据需要选择其一 +- 重新编译应用程序,链接Gazelle的库 +修改应用makefile文件链接liblstack.so,示例如下: +``` +#makefile中添加Gazelle的Makefile +-include /etc/gazelle/lstack.Makefile + +#编译添加LSTACK_LIBS变量 +gcc test.c -o test ${LSTACK_LIBS} ``` -+ 另一个方式:使用LD_PRELOAD +- 使用LD_PRELOAD加载Gazelle的库 +GAZELLE_BIND_PROCNAME环境变量指定进程名,LD_PRELOAD指定Gazelle库路径 ``` -GAZELLE_BIND_PROCNAME=test(具体进程名) LD_PRELOAD=/usr/lib64/liblstack.so ./test +GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test ``` ### 6. 配置文件 -- lstack.conf用于指定lstack的启动参数,Gazelle发布件会包括ltran.conf供用户参考,路径为/etc/gazelle/lstack.conf, 配置文件参数如下 +- lstack.conf用于指定lstack的启动参数,默认路径为/etc/gazelle/lstack.conf, 配置文件参数如下 |选项|参数格式|说明| |:---|:---|:---| |dpdk_args|--socket-mem(必需)
--huge-dir(必需)
--proc-type(必需)
--legacy-mem
--map-perfect
等|dpdk初始化参数,参考dpdk说明| |use_ltran| 0/1 | 是否使用ltran | -|num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量),仅在use_ltran=0时生效,如果机器不支持网卡多队列,lstack线程数量应该为1| -|num_weakup|"1,3,5 ..."|weakup线程绑定的cpu编号,编号的数量为weakup线程个数,与lstack线程的数量保持一致| -|numa_bind|0/1|是否支持将用户线程绑定到与某lstack线程相同numa内| +|num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量)。可按NUMA选择cpu| +|num_wakeup|"1,3,5 ..."|wakeup线程绑定的cpu编号,编号的数量为wakeup线程个数,与lstack线程的数量保持一致。与numcpus选择对应NUMA的cpu。不配置则为不使用唤醒线程| |low_power_mode|0/1|是否开启低功耗模式,暂不支持| -|kni_swith|0/1|rte_kni开关,默认为0| +|kni_swith|0/1|rte_kni开关,默认为0。只有不使用ltran时才能开启| |host_addr|"192.168.xx.xx"|协议栈的IP地址,必须和redis-server配置
文件里的“bind”字段保存一致。| |mask_addr|"255.255.xx.xx"|掩码地址| |gateway_addr|"192.168.xx.1"|网关地址| @@ -135,10 +123,8 @@ kni_switch=0 low_power_mode=0 -num_cpus="2" -num_weakup="3" - -numa_bind=1 +num_cpus="2,22" +num_wakeup="3,23" host_addr="192.168.1.10" mask_addr="255.255.255.0" @@ -146,7 +132,7 @@ gateway_addr="192.168.1.1" devices="aa:bb:cc:dd:ee:ff" ``` -- ltran.conf用于指定ltran启动的参数,Gazelle发布件会包括ltran.conf供用户参考,路径为/etc/gazelle/ltran.conf,仅在lstack.conf内配置use_ltran=1时生效,配置文件格式如下 +- ltran.conf用于指定ltran启动的参数,默认路径为/etc/gazelle/ltran.conf。使用ltran时,lstack.conf内配置use_ltran=1,配置参数如下: |功能分类|选项|参数格式|说明| |:---|:---|:---|:---| @@ -180,24 +166,26 @@ bond_macs="aa:bb:cc:dd:ee:ff" bond_ports="0x1" tcp_conn_scan_interval=10 -``` -### 7. 启动 -- 不使用ltran模式(use_ltran=0)时,不需要启动ltran -- 启动ltran,如果不指定--config-file,则使用默认路径/etc/gazelle/ltran.conf +``` +### 7. 启动应用程序 +- 启动ltran进程 +单进程且网卡支持多队列,则直接使用网卡多队列分发报文到各线程,不启动ltran进程,lstack.conf的use_ltran配置为0. +启动ltran时不使用-config-file指定配置文件,则使用默认路径/etc/gazelle/ltran.conf ``` sh ltran --config-file ./ltran.conf ``` -- 启动redis,如果不指定环境变量LSTACK_CONF_PATH,则使用默认路径/etc/gazelle/lstack.conf +- 启动应用程序 +启动应用程序前不使用环境变量LSTACK_CONF_PATH指定配置文件,则使用默认路径/etc/gazelle/lstack.conf ``` sh export LSTACK_CONF_PATH=./lstack.conf -redis-server redis.conf +LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf ``` ### 8. API -liblstack.so编译进应用程序后wrap网络编程标准接口,应用程序无需修改代码。 +Gazelle wrap应用程序POSIX接口,应用程序无需修改代码。 -### 9. gazellectl -- 不使用ltran模式时不支持gazellectl ltran xxx 命令 +### 9. 调测命令 +- 不使用ltran模式时不支持gazellectl ltran xxx命令,以及lstack -r命令 ``` Usage: gazellectl [-h | help] or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] @@ -226,54 +214,50 @@ Usage: gazellectl [-h | help] #### 1. dpdk配置文件的位置 如果是root用户,dpdk启动后的配置文件将会放到/var/run/dpdk目录下; 如果是非root用户,dpdk配置文件的路径将由环境变量XDG_RUNTIME_DIR决定; -+ 如果XDG_RUNTIME_DIR为空,dpdk配置文件放到/tmp/dpdk目录下; -+ 如果XDG_RUNTIME_DIR不为空,dpdk配置文件放到变量XDG_RUNTIME_DIR下; -+ 注意有些机器会默认设置XDG_RUNTIME_DIR +- 如果XDG_RUNTIME_DIR为空,dpdk配置文件放到/tmp/dpdk目录下; +- 如果XDG_RUNTIME_DIR不为空,dpdk配置文件放到变量XDG_RUNTIME_DIR下; +- 注意有些机器会默认设置XDG_RUNTIME_DIR -## Constraints -- 提供的命令行、配置文件以及配置大页内存需要root权限执行或修改。非root用户使用,需先提权以及修改文件权限。 -- 若要把用户态网卡绑回内核驱动,必须先将Gazelle退出。 +## 约束限制 + +使用 Gazelle 存在一些约束限制: +#### 功能约束 - 不支持accept阻塞模式或者connect阻塞模式。 -- 最多只支持20000个链接(需要保证进程内,非网络连接的fd个数小于2000个)。 -- 协议栈当前只支持tcp、icmp、arp、ipv4。 -- 大页内存不支持在挂载点里创建子目录重新挂载。 -- 在对端ping时,要求指定报文长度小于等于14000。 +- 最多支持1500个TCP连接。 +- 当前仅支持TCP、ICMP、ARP、IPv4 协议。 +- 在对端ping Gazelle时,要求指定报文长度小于等于14000B。 - 不支持使用透明大页。 -- 需要保证ltran的可用大页内存 >=1G -- 需要保证应用实例协议栈线程的可用大页内存 >=800M -- 不支持32位系统使用。 - ltran不支持使用多种类型的网卡混合组bond。 - ltran的bond1主备模式,只支持链路层故障主备切换(例如网线断开),不支持物理层故障主备切换(例如网卡下电、拔网卡)。 -- 构建X86版本使用-march=native选项,基于构建环境的CPU(Intel® Xeon® Gold 5118 CPU @ 2.30GHz)指令集进行优化。要求运行环境CPU支持SSE4.2、AVX、AVX2、AVX-512指令集。 -- 最大IP分片数为10(ping最大包长14790),TCP协议不使用IP分片。 -- sysctl配置网卡rp_filter参数为1,否则可能使用内核协议栈 -- 虚拟机网卡不支持多队列。 -- 不使用ltran模式,kni网口只支持本地通讯使用,且需要启动前配置NetworkManager不管理kni网卡 -- 虚拟kni网口的ip及mac地址,需要与lstack配置文件保持一致 - -## Security risk note -gazelle有如下安全风险,用户需要评估使用场景风险 -1. 共享内存 +- 虚拟机网卡不支持多队列。 +#### 操作约束 +- 提供的命令行、配置文件默认root权限。非root用户使用,需先提权以及修改文件所有者。 +- 将用户态网卡绑回到内核驱动,必须先退出Gazelle。 +- 大页内存不支持在挂载点里创建子目录重新挂载。 +- ltran需要最低大页内存为1GB。 +- 每个应用实例协议栈线程最低大页内存为800MB 。 +- 仅支持64位系统。 +- 构建x86版本的Gazelle使用了-march=native选项,基于构建环境的CPU(Intel® Xeon® Gold 5118 CPU @ 2.30GHz指令集进行优化。要求运行环境CPU支持 SSE4.2、AVX、AVX2、AVX-512 指令集。 +- 最大IP分片数为10(ping 最大包长14790B),TCP协议不使用IP分片。 +- sysctl配置网卡rp_filter参数为1,否则可能不按预期使用Gazelle协议栈,而是依然使用内核协议栈。 +- 不使用ltran模式,KNI网口不可配置只支持本地通讯使用,且需要启动前配置NetworkManager不管理KNI网卡。 +- 虚拟KNI网口的IP及mac地址,需要与lstack.conf配置文件保持一致 。 + +## 风险提示 +Gazelle可能存在如下安全风险,用户需要根据使用场景评估风险。 + +**共享内存** - 现状 -大页内存mount至/mnt/hugepages-2M目录,链接liblstack.so的进程初始化时在/mnt/hugepages-2M目录下创建文件,每个文件对应2M大页内存,并mmap这些文件。ltran在收到lstask的注册信息后,根据大页内存配置信息也mmap目录下文件,实现大页内存共享。 -ltran在/mnt/hugepages目录的大页内存同理。 -- 当前消减措施 -大页文件权限600,只有OWNER用户才能访问文件,默认root用户,支持配置成其它用户; -大页文件有dpdk文件锁,不能直接写或者mmap。 -- 风险点 -属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致gazelle程序crash。建议用户下的进程属于同一信任域。 -2. 流量限制 -- 风险点 -gazelle没有做流量限制,用户有能力发送最大网卡线速流量的报文到网络。 -3. 进程仿冒 -- 风险点 -合法注册到ltran的两个lstack进程,进程A可仿冒进程B发送仿冒消息给ltran,修改ltran的转发控制信息,造成进程B通讯异常,进程B报文转发给进程A等问题。建议lstack进程都为可信任进程。 - -## How to Contribute -We are happy to provide guidance for the new contributors. -Please sign the CLA before contributing. - -## Licensing -gazelle is licensed under the Mulan PSL v2. - - + 大页内存 mount 至 /mnt/hugepages-2M 目录,链接 liblstack.so 的进程初始化时在 /mnt/hugepages-2M 目录下创建文件,每个文件对应 2M 大页内存,并 mmap 这些文件。ltran 在收到 lstask 的注册信息后,根据大页内存配置信息也 mmap 目录下文件,实现大页内存共享。 + ltran 在 /mnt/hugepages 目录的大页内存同理。 +- 当前消减措施 + 大页文件权限 600,只有 OWNER 用户才能访问文件,默认 root 用户,支持配置成其它用户; + 大页文件有 DPDK 文件锁,不能直接写或者映射。 +- 风险点 + 属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致Gazelle程序crash。建议用户下的进程属于同一信任域。 + +**流量限制** +Gazelle没有做流量限制,用户有能力发送最大网卡线速流量的报文到网络,可能导致网络流量拥塞。 + +**进程仿冒** +合法注册到ltran的两个lstack进程,进程A可仿冒进程B发送仿冒消息给ltran,修改ltran的转发控制信息,造成进程B通讯异常,进程B报文转发给进程A信息泄露等问题。建议lstack进程都为可信任进程。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 344d0fdd7..efd2f5678 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -215,7 +215,7 @@ headless: true - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) -- [gazelle用户指南]({{< relref "./docs/gazelle/gazelle.md" >}}) +- [Gazelle用户指南]({{< relref "./docs/Gazelle/Gazelle.md" >}}) - [NestOS用户指南]({{< relref "./docs/NestOS/overview.md" >}}) - [安装与部署]({{< relref "./docs/NestOS/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/NestOS/使用方法.md" >}}) -- Gitee From d4a93eb205654167dbcba28ee5fcfa2da88b7876 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 15:34:05 +0800 Subject: [PATCH 015/130] =?UTF-8?q?22.03-LTS=E5=88=86=E6=94=AF=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E5=88=B0master=E5=88=86=E6=94=AF=20=E5=88=86=E6=94=AF?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 89 +++++++++-- docs/zh/docs/Embedded/embedded.md | 4 +- ...21\350\241\214\350\257\264\346\230\216.md" | 32 ++++ ...\273\272\346\214\207\345\257\274.markdown" | 141 +---------------- ...05\344\270\216\350\277\220\350\241\214.md" | 43 ++++-- ...\273\272\346\214\207\345\257\274.markdown" | 31 ++-- ...\273\272\346\214\207\345\257\274.markdown" | 142 ++++++++++++++++++ ...\273\272\346\214\207\345\257\274.markdown" | 4 - ...63\351\224\256\347\211\271\346\200\247.md" | 2 +- ...73\347\273\237\345\256\211\350\243\205.md" | 32 +++- docs/zh/menu/index.md | 7 +- 11 files changed, 333 insertions(+), 194 deletions(-) create mode 100644 "docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" rename "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" => "docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" (77%) create mode 100644 "docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" delete mode 100644 "docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 283757eed..96bc29e1e 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -5,8 +5,9 @@ - [安装SDK](#安装SDK) -- [使用SDK编译](#使用SDK编译) - +- [使用SDK编译hello world样例](#使用SDK编译hello world样例) +- [使用SDK编译内核模块样例](#使用SDK编译内核模块样例) +- ### 安装SDK @@ -14,11 +15,11 @@ 运行如下命令: -``` {.sourceCode .console} +``` sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh ``` -根据提示输入工具链的安装路径,默认路径是/opt/openeuler/\/;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 +根据提示输入工具链的安装路径,默认路径是`/opt/openeuler/\/`;若不设置,则按默认路径安装;也可以配置相对路径或绝对路径。 举例如下: @@ -38,7 +39,7 @@ $ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi 运行source命令。上例中前一步执行结束最后已打印source命令,运行即可。 -``` {.sourceCode .console} +``` . /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi ``` @@ -46,13 +47,11 @@ $ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi 运行如下命令,查看是否安装成功、环境设置成功。 -``` {.sourceCode .console} +``` arm-openeuler-linux-gnueabi-gcc -v ``` -### 使用SDK编译 - -下面以使用SDK编译hello world为样例。 +### 使用SDK编译hello world样例 1. **准备代码** @@ -81,7 +80,7 @@ add_executable(hello hello.c) 进入hello.c文件所在目录,使用工具链编译,命令如下: -``` {.sourceCode .console} +``` cmake .. make ``` @@ -92,9 +91,75 @@ make 在openEuler Embedded系统中运行hello程序。 -``` {.sourceCode .console} +``` cd /tmp/myfiles/ ./hello ``` -如运行成功,则会输出\"hello world\"。 \ No newline at end of file +如运行成功,则会输出\"hello world\"。 + +### 使用SDK编译内核模块样例 + +1. **准备代码** + +以编译一个内核模块为例,运行在openEuler Embedded内核中。 + +创建一个hello.c文件,源码如下: + +```c +#include +#include + +static int hello_init(void) +{ + printk("Hello, openEuler Embedded!\r\n"); + return 0; +} + +static void hello_exit(void) +{ + printk("Byebye!"); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_LICENSE(GPL); +``` + +编写Makefile,和hello.c文件放在同一个目录: + +``` + KERNELDIR := ${KERNEL_SRC_DIR} + CURRENT_PATH := $(shell pwd) + + target := hello + obj-m := $(target).o + + build := kernel_modules + + kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean +``` + +`KERNEL_SRC_DIR` 为SDK中内核源码树的目录,该变量在安装SDK后会被自动设置。 + +2. **编译生成内核模块** + +进入hello.c文件所在目录,使用工具链编译,命令如下: + + make + +将编译好的hello.ko拷贝到openEuler Embedded系统的目录下。 + +如何拷贝可以参考前文所述使能共享文件系统场景。 + +3. **插入内核模块** + +在openEuler Embedded系统中插入内核模块: + + insmod hello.ko + +如运行成功,则会在内核日志中出现"Hello, openEuler Embedded!"。 \ No newline at end of file diff --git a/docs/zh/docs/Embedded/embedded.md b/docs/zh/docs/Embedded/embedded.md index e63829588..44412fc68 100755 --- a/docs/zh/docs/Embedded/embedded.md +++ b/docs/zh/docs/Embedded/embedded.md @@ -1,5 +1,5 @@ # openEuler Embedded 用户指南 -openEuler Embedded是基于openEuler社区面向嵌入式场景的Linux版本。由于嵌入式系统应用受到多个因素的约束,如资源、功耗、多样性等,使得面向服务器领域的Linux及相应的构建系统很难满足嵌入式场景的要求,因此业界广泛采用[Yocto](https://www.yoctoproject.org/)来定制化构建嵌入式Linux。openEuler Embedded当前也采用的Yocto构建,但实现了与openEuler其他版本代码同源,具体的构建方法请参考[SIG-Yocto](https://gitee.com/openeuler/community/tree/master/sig/sig-Yocto)下相关代码仓中的内容。 +openEuler Embedded是基于openEuler社区面向嵌入式场景的Linux版本,旨在成为一个高质量的以Linux为中心的嵌入式系统软件平台。openEuler Embedded在内核版本、软件包版本等代码层面会与openEuler其他场景的Linux保持一致,共同演进,不同之处在于针对嵌入场景的内核配置、软件包的组合与配置、代码特性补丁的不同。 -本文档主要用于介绍如何获取预先构建好的镜像,如何运行镜像,以及如何基于镜像完成基本的嵌入式Linux应用开发。使用人员需要具备基本的Linux操作系统知识。 +本文档主要用于介绍如何获取预先构建好的镜像,如何运行镜像,如何基于镜像完成基本的嵌入式Linux应用开发以及如何构建openEuler Embedded。使用人员需要具备基本的Linux操作系统知识。 diff --git "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" new file mode 100644 index 000000000..3fd5a5328 --- /dev/null +++ "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" @@ -0,0 +1,32 @@ +# openEuler Embedded 22.03发行说明 + +openEuler Embedded 22.03是openEuler Embedded第一次正式发布,包含的内容大概如下: + +## 内核 + +- 内核升级到 5.10.0-60.17.0 + +- 内核支持Preempt-RT补丁 + +- 内核支持树莓派4B相关补丁 + +## 软件包 + +- 支持80+软件包,详见[openEuler Embedded所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) + +## 亮点特性 + +- 多OS混合部署框架的初步实现,支持openEuler Embedded和Zephyr的混合部署,详见[多OS混合部署框架](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html) +- 分布式软总线的初步集成,详见[分布式软总线](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html) + +- 安全加固指导,详见[openEuler Embedded的安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) +- 基于Preempt-RT的软实时,详见[openEuler Embedded软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) + +## 南向生态 + +- 新增树莓派4B支持,详见[openEuler Embedded树莓派系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) + +## 构建系统 + +- 初步的openEuler Embedded构建体系, 详见[快速构建指导](./快速构建指导.html) +- 容器化构建,详见[容器构建指导](./容器构建指导.html) \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index fc4974d26..f9776a511 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,143 +1,4 @@ openEuler Embedded构建指导 ===================== -本章主要介绍如何构建openEuler Embedded。 - - - -- [环境准备](#环境准备) - - [Yocto中主机端命令使用](#Yocto中主机端命令使用) - - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) - - [已安装好工具的构建容器](#已安装好工具的构建容器) -- [openEuler Embedded版本构建](#openEuler Embedded版本构建) - - [构建代码下载](#构建代码下载) - - [编译构建](#编译构建) - - [构建结果说明](#构建结果说明) - - -环境准备 --------------- - -### Yocto中主机端命令使用 - -Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: - -- Python3 \> 3.6.0 -- Git \> 1.8.3.1 -- Tar \> 1.28 - -在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 - -为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 - -Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: - -![](./public_sys-resources/hosttools.png) - -当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: - -| 工具名 | 用途 | -| ------ | ------------- | -| cmake | cmake构建工具 | -| ninjia | ninja构建系统 | - -### openEuler Embedded所需构建工具 - -- 构建OS - - [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) - -- 安装系统额外工具 - -``` -yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel -``` - -- 预编译的交叉工具链和库 - - Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: - - - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) - - [ARM64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) - -### 已安装好工具的构建容器 - -openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 - -使用者可以通过如下链接获得容器镜像直接用于编译: - -​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) - -具体构建指导请参考[openEuler Embedded容器构建指导](https://docs.openeuler.org/zh/22.03_LTS/docs/Embedded/openEuler Embedded容器构建指导.html)。 - -## openEuler Embedded版本构建 - -### 构建代码下载 - -openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: - -><顶层目录openeuler_embedded> ->├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 ->├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 - -1. 获取源码下载脚本 - - 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: - - ``` - git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler - ``` - - 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: - - - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 - - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 - - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 - -2. 通过脚本下载源码 - - - 下载最新代码: - - ``` - sh src/yocto-meta-openeuler/scripts/download_code.sh - ``` - - - 下载指定版本代码: - - ``` - sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" - ``` - - 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 - -### 编译构建 - -一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 - -编译脚本的主要流程说明: - -1. 设置PATH增加额外工具路径 -2. TEMPLATECONF指定local.conf.sample等配置文件路径 -3. 调用poky仓的oe-init-build-env进行初始化配置 -4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 -5. 在编译目录执行bitbake openeuler-image编译openEuler - Embedded的image和sdk -6. 执行完发布件在编译目录的output目录下 - -运行编译脚本,以编译标准arm架构为例,编译方法如下: - - source src/yocto-meta-openeuler/scripts/compile.sh arm-std - bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 - -### 构建结果说明 - -结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: - -| filename | description | -| --------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | -| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | -| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | -| zImage | openEuler Embedded compressed image | \ No newline at end of file +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index 8111524af..c8d5dfe0a 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -11,9 +11,10 @@ - [极简运行场景](#极简运行场景) - [使能共享文件系统场景](#使能共享文件系统场景) - [使能网络场景](#使能网络场景) - + ## 获取镜像 + 当前发布的已构建好的镜像,只支持arm和aarch64两种架构,且只支持qemu中ARM virt-4.0平台,您可以通过如下链接获得相应的镜像: - [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm):32位arm架构,ARM Cortex A15处理器 @@ -30,13 +31,13 @@ - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) - 根文件系统镜像(依据具体需求,以下二选一) - + - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - + - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 - + - SDK(Software Development Kit)工具 - + - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -44,19 +45,21 @@ 通过运行镜像,一方面您可以体验openEuler Embedded的功能,一方面也可以完成基本的嵌入式Linux开发。 --- + **注意事项** - 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 >![](./public_sys-resources/icon-note.gif) **说明:** - >后续说明以标准根文件系统为例(initrd)。 +> +>后续说明以标准根文件系统为例(initrd)。 --- qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: -``` {.sourceCode .console} +``` qemu-system-aarch64 --version ``` @@ -67,17 +70,21 @@ qemu-system-aarch64 --version 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd ``` >![](./public_sys-resources/icon-note.gif) **说明:** - >- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 - >- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 +> +>- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 +>- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 2. **检查运行是否成功** @@ -93,10 +100,13 @@ qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp ``` @@ -104,11 +114,13 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr 2. **映射文件系统** 在openEuler Embedded启动并登录之后,需要运行如下命令,映射(mount)共享文件系统 + ``` cd /tmp mkdir host mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host ``` + 即把共享文件系统映射到openEuler Embedded的/tmp/host目录下。 3. **检查共享是否成功** @@ -119,21 +131,27 @@ mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host cd /tmp/host ls ``` + 如能发现hello_openeuler.txt,则共享成功。 ### 使能网络场景 通过qemu的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler embedded之间的网络通信。 + 1. **启动qemu** 针对arm(ARM Cortex A15),运行如下命令: + ``` qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` + 针对aarch64(ARM Cortex A57),运行如下命令: + ``` qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup ``` + 2. **宿主上建立虚拟网卡** 在宿主机上需要建立名为tap0的虚拟网卡,可以借助脚本实现,创建qemu-ifup脚本,放在/etc/下,具体内容如下: @@ -142,6 +160,7 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr #!/bin/bash ifconfig $1 192.168.10.1 up ``` + 其执行需要root权限: ``` @@ -153,6 +172,7 @@ chmod a+x qemu-ifup 3. **配置openEuler embedded网卡** openEuler Embedded登陆后,执行如下命令: + ``` ifconfig eth0 192.168.10.2 ``` @@ -160,6 +180,7 @@ ifconfig eth0 192.168.10.2 4. **确认网络连通** 在openEuler Embedded中,执行如下命令: + ``` ping 192.168.10.1 ``` @@ -167,5 +188,7 @@ ping 192.168.10.1 如能ping通,则宿主机和openEuler Embedded之间的网络是连通的。 --- + >![](./public_sys-resources/icon-note.gif) **说明:** - >如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 +> +>如需openEuler Embedded借助宿主机访问互联网,则需要在宿主机上建立网桥,此处不详述,如有需要,请自行查阅相关资料。 \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" similarity index 77% rename from "docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" rename to "docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 2074cf578..a0803aa14 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -9,7 +9,7 @@ openEuler Embedded容器构建指导 - [安装docker](#安装docker) - [获取容器镜像](#获取容器镜像) - [准备容器构建环境](#准备容器构建环境) -- [openEuler Embedded版本构建](#openEuler Embedded版本构建) +- [版本构建](#版本构建) - [下载源码](#下载源码) - [编译构建](#编译构建) - [构建结果说明](#构建结果说明) @@ -32,7 +32,7 @@ openEuler Embedded容器构建指导 运行如下命令,可以看到当前docker版本信息,则说明当前环境已安装docker,无需再次安装。 -``` {.sourceCode .console} +``` docker version ``` @@ -50,10 +50,10 @@ sudo yum install docker --------------- -通过docker pull命令拉取华为云中的镜像到宿主机。命令如下: +通过`docker pull`命令拉取华为云中的镜像到宿主机。命令如下: ``` -docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container ``` ### 准备容器构建环境 @@ -62,10 +62,10 @@ docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-contai #### 1.启动容器 -可通过docker run命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: +可通过`docker run`命令启动容器,为了保证容器启动后可以在后台运行,且可以正常访问网络,建议使用如下命令启动: ``` -docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container bash ``` 参数说明: @@ -73,9 +73,8 @@ docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedd - -i 让容器的标准输入保持打开 - -d 让 Docker 容器在后台以守护态(Daemonized)形式运行 - -t 选项让Docker分配一个伪终端(pseudo-tty)并绑定到容器的标准输入上 -- \--network 将容器连接到(host)网络 -- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest - (镜像名称:镜像版本) +- --network 将容器连接到(host)网络 +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container 指定镜像名称 - bash 进入容器的方式 #### 2.查看已启动的容器id @@ -92,7 +91,7 @@ docker exec -it 容器id bash 构建环境已准备完成,下面就可以在容器中进行构建了。 -## openEuler Embedded版本构建 +## 版本构建 ### 下载源码 @@ -144,9 +143,9 @@ bitbake openeuler-image 结果件默认生成在构建目录下的output目录下,例如上面aarch64-std的构建结果件生成在/usr1/build/output目录下,如下表: -| filename | description | -| --------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | -| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | -| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | -| zImage | openEuler Embedded compressed image | \ No newline at end of file +| filename | description | +| ---------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" new file mode 100644 index 000000000..1080d7193 --- /dev/null +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -0,0 +1,142 @@ +快速构建指导 +===================== + +本章主要介绍如何构建openEuler Embedded。 + + + +- [环境准备](#环境准备) + - [Yocto中主机端命令使用](#Yocto中主机端命令使用) + - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) + - [已安装好工具的构建容器](#已安装好工具的构建容器) +- [版本构建](#版本构建) + - [构建代码下载](#构建代码下载) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) + + +环境准备 +-------------- + +### Yocto中主机端命令使用 + +Yocto或者说Bitbake本质上是一组python程序,其最小运行环境要求如下: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +在构建过程中所需要的其他工具,Yocto都可以根据相应的软件包配方自行构建出来,从而达到自包含的效果。在这个过程中,Yocto还会依据自身需要,对相应的工具打上yocto专属补丁(如dnf,rpm等)。这些主机工具会在第一次的构建中从源码开始构建,因此Yocto第一次构建比较费时。 + +为了加速构建特别是第一次构建,openEuler Embedded采取了"能用原生工具就用原生工具,能不构建就不构建"的策略,尽可能使用主机上预编译的原生的工具。这就需要依赖主机上软件包管理工具(apt, dnf, yum, zypper等)实现安装好。 + +Yocto是通过HOSTTOOLS变量来实现主机工具的引入,为会每个在HOSTTOOLS中列出的工具建立相应的软链接。为了避免来自主机对构建环境的污染,Yocto会重新准备不同于主机的环境,例如PATH变量等,因此如果新增依赖主机上的某个命令,需显示在Yocto的HOSTTOOLS变量中增加,否则即使主机上存在,Yocto构建时也会报错找不到相应的工具。相应流程如下图所示: + +![](./public_sys-resources/hosttools.png) + +当前openEuler Embedded所需要主机工具已经默认在local.conf.sample中的HOSTTOOLS定义,主要工具描述如下: + +| 工具名 | 用途 | +| ------ | ------------- | +| cmake | cmake构建工具 | +| ninjia | ninja构建系统 | + +### openEuler Embedded所需构建工具 + +- 构建OS + + [操作系统:openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- 安装系统额外工具 + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- 预编译的交叉工具链和库 + + Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 + + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + + - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [ARM 64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + +### 已安装好工具的构建容器 + +openEuler Embedded的构建过程中会使用到大量的各式各样的主机工具。如前文所述,为了加速构建,openEuler Embedded依赖主机事先安装好相应的工具,但这也会带来一不同主机环境会有不同的工具版本的问题,例如构建需要cmake高于1.9版本,但主机上最高只有cmake 1.8。为了解决这一问题,openEuler Embedded提供了专门的构建容器,提供统一的构建环境。 + +使用者可以通过如下链接获得容器镜像直接用于编译: + +​ [openEuler Embedded构建容器的基础镜像](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +具体构建指导请参考[容器构建指导](./容器构建指导.html)。 + +## 版本构建 + +### 构建代码下载 + +openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_embedded为顶层目录: + +><顶层目录openeuler_embedded> +>├── src 源代码目录,包含所有软件包代码、内核代码和Yocto构建代码 +>├── build openEuler Embedded的构建目录,生成的各种镜像放在此目录下 + +1. 获取源码下载脚本 + + 将脚本下载到指定目录,例如下载到src/yocto-meta-openeuler目录下: + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + 脚本为src/yocto-meta-openeuler/scripts/download\_code.sh,此脚本有3个参数: + + - 参数1:下载的源码路径,默认相对脚本位置下载,例如前面样例,代码仓会下到src/下 + - 参数2:下载的分支,默认值见脚本,不同分支按版本确定 + - 参数3:下代码的xml文件,标准manifest格式,按xml配置下代码 + +2. 通过脚本下载源码 + + - 下载最新代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - 下载指定版本代码: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + 指定openEuler Embedded版本的代码的manifest.xml文件从openEuler Embedded发布件目录embedded\_img/source-list/下获取。 + +### 编译构建 + +一键式构建脚本:src/yocto-meta-openeuler/scripts/compile.sh, 具体细节可以参考该脚本。 + +编译脚本的主要流程说明: + +1. 设置PATH增加额外工具路径 +2. TEMPLATECONF指定local.conf.sample等配置文件路径 +3. 调用poky仓的oe-init-build-env进行初始化配置 +4. 在编译目录的conf/local.conf中配置MACHINE,按需增加额外新增的层 +5. 在编译目录执行bitbake openeuler-image编译openEuler Embedded的image和sdk +6. 执行完发布件在编译目录的output目录下 + +运行编译脚本,以编译标准arm架构为例,编译方法如下: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image #执行第一条source后,会提示出bitbake命令 + +### 构建结果说明 + +结果件默认生成在构建目录下的output目录下,例如上面arm的构建结果件生成在/usr1/build/output目录下,如下表: + +| filename | description | +| ---------------------------------------------------------- | ----------------------------------- | +| Image-5.10.0 | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" deleted file mode 100644 index f9776a511..000000000 --- "a/docs/zh/docs/Embedded/\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ /dev/null @@ -1,4 +0,0 @@ -openEuler Embedded构建指导 -===================== - -本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 5ea9dcfe0..9eb473df3 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -69,7 +69,7 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 ## 嵌入式镜像 - **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 -- **多硬件支持**,新增支持树莓派作为嵌入式场景通用硬件。 +- **多硬件支持**,新增支持树莓派4B作为嵌入式场景通用硬件。 - **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 - **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 - **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index 3cf60381b..ac05dbab2 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -2,11 +2,12 @@ ## 发布件
-openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表4](#table953512211576)。 +openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)、[嵌入式镜像](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表5](#table953512211576)。 **表 1** 发布ISO列表 +

名称

描述

@@ -64,6 +65,7 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 **表 2** 虚拟机镜像 +

名称

描述

@@ -107,10 +109,22 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+**表 4** 嵌入式镜像列表 -**表 4** repo源列表 +| 名称 | 描述 | +| -------------------------------------- | ------------------------------- | +| arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | +| arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | +| arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | +| arm64/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | +| arm64/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm64/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| source-list/manifest.xml | 构建使用的源码清单 | + +**表 5** repo源列表 + + + +

目录

描述

@@ -142,6 +156,11 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03

存放虚拟机镜像

embedded_img

+

存放嵌入式镜像

+

everything

存放全量软件包源

@@ -170,11 +189,12 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+ ## 最小硬件要求 -安装 openEuler 22.03-LTS 所需的最小硬件要求如[表5](#zh-cn_topic_0182825778_tff48b99c9bf24b84bb602c53229e2541)所示。 +安装 openEuler 22.03-LTS 所需的最小硬件要求如[表6](#zh-cn_topic_0182825778_tff48b99c9bf24b84bb602c53229e2541)所示。 -**表 5** 最小硬件要求 +**表 6** 最小硬件要求 - - @@ -462,10 +462,10 @@ In the XML configuration of libvirt, each controller element \(**controller**\) - @@ -515,14 +515,14 @@ In addition to storage devices and network devices, some external devices need t #### Elements -- **serial**: serial port device +- **serial**: serial port device. - Attribute **type**: specifies the serial port type. The common attribute values are **pty**, **tcp**, **pipe**, and **file**. + Attribute **type**: serial port type. The common attribute values are **pty**, **tcp**, **pipe**, and **file**. -- **video**: media device +- **video**: media device. - **type** attribute: media device type The common attribute value of the AArch architecture is **virtio**, and that of the x86\_64 architecture is **vga** or **cirrus**. + Attribute **type** : media device type. The common attribute value of the AArch64 architecture is **virtio**, and that of the x86\_64 architecture is **vga** or **cirrus**. Subelement **model**: subelement of **video**, which is used to specify the media device type. @@ -538,16 +538,16 @@ In addition to storage devices and network devices, some external devices need t - **input**: output device - **type** attribute: specifies the type of the output device. The common attribute values are **tabe** and **keyboard**, indicating that the output device is the tablet and keyboard respectively. + Attribute **type**: type of the output device. The common attribute values are **tabe** and **keyboard**, indicating that the output device is the tablet and keyboard respectively. - **bus**: specifies the bus to be mounted. The common attribute value is **USB**. + **bus**: bus to be mounted. The common attribute value is **USB**. -- **emulator**: emulator application path -- **graphics**: graphics device +- **emulator**: emulator application path. +- **graphics**: graphics device. - **type** attribute: specifies the type of a graphics device. The common attribute value is **vnc**. + Attribute **type**: type of a graphics device. The common attribute value is **vnc**. - **listen** attribute: specifies the IP address to be listened to. + Attribute **listen**: IP address to be listened to. #### Configuration Example @@ -584,11 +584,11 @@ The XML configuration file contains configurations related to the system archite - **os**: defines VM startup parameters. - Subelement **type**: specifies the VM type. The attribute **arch** indicates the architecture type, for example, AArch64. The attribute **machine** indicates the type of VM chipset. Supported chipset type can be queried by running the **qemu-kvm -machine ?** command. For example, the AArch64 architecture supports the **virt** type. + Subelement **type**: VM type. The attribute **arch** indicates the architecture type, for example, AArch64. The attribute **machine** indicates the type of VM chipset. The supported chipset type can be queried by running the **qemu-kvm -machine ?** command. For example, the AArch64 architecture supports the **virt** type. - Subelement **loader**: specifies the firmware to be loaded, for example, the UEFI file provided by the EDK. The **readonly** attribute indicates whether the file is read-only. The value can be **yes** or **no**. The **type** attribute indicates the **loader** type. The common values are **rom** and **pflash**. + Subelement **loader**: firmware to be loaded, for example, the UEFI file provided by the EDK. The **readonly** attribute indicates whether the file is read-only. The value can be **yes** or **no**. The **type** attribute indicates the **loader** type. The common values are **rom** and **pflash**. - Subelement **nvram**: specifies the path of the **nvram** file, which is used to store the UEFI startup configuration. + Subelement **nvram**: path of the **nvram** file, which is used to store the UEFI startup configuration. - **features**: Hypervisor controls some VM CPU/machine features, such as the advanced configuration and power interface \(ACPI\) and the GICv3 interrupt controller specified by the ARM processor. @@ -641,14 +641,14 @@ In addition to system resources and virtual devices, other elements need to be c ### Elements -- **iothreads**: specifies the number of **iothread**, which can be used to accelerate storage device performance. +- **iothreads**: number of **iothread**, which can be used to accelerate storage device performance. - **on\_poweroff**: action taken when a VM is powered off. - **on\_reboot**: action taken when a VM is rebooted. - **on\_crash**: action taken when a VM is on crash. -- **clock**: indicates the clock type. +- **clock**: clock type. - **offset** attribute: specifies the VM clock synchronization type. The value can be **localtime**, **utc**, **timezone**, or **variable**. + Attribute **offset**: VM clock synchronization type. The value can be **localtime**, **utc**, **timezone**, or **variable**. ### Configuration Example diff --git a/docs/zh/docs/Gazelle/Gazelle.md b/docs/zh/docs/Gazelle/Gazelle.md index d65ef9bf6..f5cd65418 100644 --- a/docs/zh/docs/Gazelle/Gazelle.md +++ b/docs/zh/docs/Gazelle/Gazelle.md @@ -112,7 +112,7 @@ GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test |num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量)。可按NUMA选择cpu| |num_wakeup|"1,3,5 ..."|wakeup线程绑定的cpu编号,编号的数量为wakeup线程个数,与lstack线程的数量保持一致。与numcpus选择对应NUMA的cpu。不配置则为不使用唤醒线程| |low_power_mode|0/1|是否开启低功耗模式,暂不支持| -|kni_swith|0/1|rte_kni开关,默认为0。只有不使用ltran时才能开启| +|kni_switch|0/1|rte_kni开关,默认为0。只有不使用ltran时才能开启| |host_addr|"192.168.xx.xx"|协议栈的IP地址,也是应用程序的IP地址| |mask_addr|"255.255.xx.xx"|掩码地址| |gateway_addr|"192.168.xx.1"|网关地址| @@ -149,7 +149,7 @@ devices="aa:bb:cc:dd:ee:ff" |dispatch_subnet_length|n|子网长度,表示ltran能识别的子网长度,例如length为4时,192.168.1.1-192.168.1.16| |bond_mode|n|bond模式,目前只支持Active Backup(Mode1),取值为1| |bond_miimon|n|bond链路监控时间,单位为ms,取值范围为1到2^64 - 1 - (1000 * 1000)| -|bond_ports|"0x01"|使用的dpdk网卡,0x1表示第一块| +|bond_ports|"0x01"|使用的dpdk网卡,0x01表示第一块| |bond_macs|"aa:bb:cc:dd:ee:ff"|绑定的网卡mac地址,需要跟kni的mac地址保持一致| |bond_mtu|n|最大传输单元,默认是1500,不能超过1500,最小值为68,不能低于68| -- Gitee From c688b135b2c98f7bad50dede35644e8bbac4b734 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Wed, 24 Aug 2022 09:59:58 +0000 Subject: [PATCH 117/130] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20memory-fabric?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/memory-fabric/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/zh/docs/memory-fabric/.keep diff --git a/docs/zh/docs/memory-fabric/.keep b/docs/zh/docs/memory-fabric/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From c4a316642e083a406f07a79607b735f6f522edd6 Mon Sep 17 00:00:00 2001 From: gomico Date: Thu, 25 Aug 2022 17:02:25 +0800 Subject: [PATCH 118/130] update translation for some zh docs --- docs/en/docs/Installation/faqs.md | 4 +- .../Installation/installation-preparations.md | 44 ++-- .../docs/SecHarden/selinux-configuration.md | 201 ++++++++++++++++-- .../comm_crypto_app_conf.md | 1 + .../thirdparty_migration/OpenStack-train.md | 2 +- .../en/docs/thirdparty_migration/openstack.md | 1 + .../docs/thirdparty_migration/thidrparty.md | 2 - docs/en/docs/userguide/images/panel.png | Bin 0 -> 39247 bytes docs/en/docs/userguide/patch-tracking.md | 32 +-- docs/en/docs/userguide/pkgship.md | 52 +++-- docs/en/menu/index.md | 2 +- 11 files changed, 261 insertions(+), 80 deletions(-) create mode 100644 docs/en/docs/commercial_cryptography_features/comm_crypto_app_conf.md create mode 100644 docs/en/docs/thirdparty_migration/openstack.md create mode 100644 docs/en/docs/userguide/images/panel.png diff --git a/docs/en/docs/Installation/faqs.md b/docs/en/docs/Installation/faqs.md index 5e37d8b7d..fcb09a816 100644 --- a/docs/en/docs/Installation/faqs.md +++ b/docs/en/docs/Installation/faqs.md @@ -262,11 +262,11 @@ During the installation of openEuler on an x86 PM in UEFI mode, the system stays ### Possible Causes -After **secure boot** is set to **enabled**, the mainboard verifies the boot program and OS. If the boot program and OS are not signed using the corresponding private key, they cannot pass the authentication of the built-in public key on the mainboard. +After **Secure Boot** is set to **Enabled**, the mainboard verifies the boot program and OS. If the boot program and OS are not signed using the corresponding private key, they cannot pass the authentication of the built-in public key on the mainboard. ### Solutions -Access the BIOS, set **secure boot** to **disabled**, and reinstall the openEuler. +Access the BIOS, set **Secure Boot** to **Disabled**, and reinstall the openEuler. 1. During the system startup, press **F11** and enter the password **Admin@9000** to access the BIOS. diff --git a/docs/en/docs/Installation/installation-preparations.md b/docs/en/docs/Installation/installation-preparations.md index a98d1f8e1..57a45ae22 100644 --- a/docs/en/docs/Installation/installation-preparations.md +++ b/docs/en/docs/Installation/installation-preparations.md @@ -5,17 +5,17 @@ This section describes the compatibility of the hardware and software and the re - [Installation Preparations](#installation-preparations) - - [Obtaining the Installation Source](#obtaining-the-installation-source) - - [Release Package Integrity Check](#release-package-integrity-check) - - [Introduction](#introduction) - - [Prerequisites](#prerequisites) - - [Procedures](#procedures) - - [Installation Requirements for PMs](#installation-requirements-for-pms) - - [Hardware Compatibility](#hardware-compatibility) - - [Minimum Hardware Specifications](#minimum-hardware-specifications) - - [Installation Requirements for VMs](#installation-requirements-for-vms) - - [Virtualization Platform Compatibility](#virtualization-platform-compatibility) - - [Minimum Virtualization Space](#minimum-virtualization-space) + - [Obtaining the Installation Source](#obtaining-the-installation-source) + - [Release Package Integrity Check](#release-package-integrity-check) + - [Introduction](#introduction) + - [Prerequisites](#prerequisites) + - [Procedures](#procedures) + - [Installation Requirements for PMs](#installation-requirements-for-pms) + - [Hardware Compatibility](#hardware-compatibility) + - [Minimum Hardware Specifications](#minimum-hardware-specifications) + - [Installation Requirements for VMs](#installation-requirements-for-vms) + - [Virtualization Platform Compatibility](#virtualization-platform-compatibility) + - [Minimum Virtualization Space](#minimum-virtualization-space) @@ -25,22 +25,22 @@ Obtain the openEuler release package and verification file before the installati Perform the following operations to obtain the openEuler release package: -1. Log in to the [openEuler Community](https://openeuler.org/zh/) website. -2. Click **Download**. -3. Choose the card **openEuler-21.09** and click **Download ISO**. The download list is displayed. - - **aarch64**: ISO image file of the AArch64 architecture - - **x86_64**: ISO image file of the x86_64 architecture - - **source**: ISO image file of the openEuler source code -4. Select the target openEuler release package and verification file based on the actual environment to be installed. +1. Visit the [openEuler](https://www.openeuler.org/en/) website. +2. Click **Download > Software Packages**. +3. Click **Server Image** below **openEuler 21.09**. The ISO list is displayed. + - **aarch64**: ISO image files of the AArch64 architecture + - **x86_64**: ISO image files of the x86_64 architecture + - **source**: ISO image files of the openEuler source code +4. Select the target openEuler release package and verification file based on the actual environment. - AArch64 architecture: 1. Click **aarch64**. - 2. If you install the environment on the local host, download the release package **openEuler-21.09-aarch64-dvd.iso** and the verification file **openEuler-21.09-aarch64-dvd.iso.sha256sum** to the local host. - 3. If you install the environment on the network, download the release package **openEuler-21.09-netinst-aarch64-dvd.iso** and the verification file **openEuler-21.09-netinst-aarch64-dvd.iso.sha256sum** to the local host. + 2. If you install openEuler from a local source, download the release package **openEuler-21.09-aarch64-dvd.iso** and the verification file **openEuler-21.09-aarch64-dvd.iso.sha256sum** to the local host. + 3. If you install openEuler through the network, download the release package **openEuler-21.09-netinst-aarch64-dvd.iso** and the verification file **openEuler-21.09-netinst-aarch64-dvd.iso.sha256sum** to the local host. - x86_64 architecture: 1. Click **x86_64**. - 2. If you install the environment on the local host, download the release package **openEuler-21.09-x86_64-dvd.iso** and the verification file **openEuler-21.09-x86_64-dvd.iso.sha256sum** to the local host. - 3. If you install the environment on the network, download the release package **openEuler-21.09-netinst-x86_64-dvd.iso** and the verification file **openEuler-21.09-netinst-x86_64-dvd.iso.sha256sum** to the local host. + 1. If you install openEuler from a local source, download the release package **openEuler-21.09-x86_64-dvd.iso** and the verification file **openEuler-21.09-x86_64-dvd.iso.sha256sum** to the local host. + 1. If you install openEuler through the network, download the release package **openEuler-21.09-netinst-x86_64-dvd.iso** and the verification file **openEuler-21.09-netinst-x86_64-dvd.iso.sha256sum** to the local host. >![](./public_sys-resources/icon-note.gif) **Note** > When the network is available, install the environment on the network because the ISO release package is small. diff --git a/docs/en/docs/SecHarden/selinux-configuration.md b/docs/en/docs/SecHarden/selinux-configuration.md index 6644c4cc1..3e0540624 100644 --- a/docs/en/docs/SecHarden/selinux-configuration.md +++ b/docs/en/docs/SecHarden/selinux-configuration.md @@ -6,49 +6,86 @@ Discretionary access control \(DAC\) determines whether a resource can be access By default, openEuler uses SELinux to improve system security. SELinux has three modes: -- **permissive**: The SELinux outputs alarms but does not forcibly execute the security policy. -- **enforcing**: The SELinux security policy is forcibly executed. -- **disabled**: The SELinux security policy is not loaded. +- **permissive**: The SELinux outputs alarms but does not forcibly execute the security policies. +- **enforcing**: The SELinux security policies are forcibly executed. +- **disabled**: The SELinux security policies are not loaded. ## Configuration Description -SELinux is enabled for openEuler by default and the default mode is enforcing. You can change the SELinux mode by changing the value of **SELINUX** in **/etc/selinux/config**. +- Obtain the SELinux running status: + ``` + # getenforce + Enforcing + ``` -- To disable the SELinux policy, run the following command: +- Set the enforcing mode when SELinux is enabled: + ``` + # setenforce 1 + # getenforce + Enforcing + ``` +- Set the permissive mode when SELinux is enabled: ``` - SELINUX=disabled + # setenforce 0 + # getenforce + Permissive ``` -- To use the permissive policy, run the following command: +- Disable SELinux when SELinux is enabled. (A reboot is required.) + 1. Modify the SELinux configuration file **/etc/selinux/config** and set **SELINUX=disabled**. + ``` + # cat /etc/selinux/config | grep "SELINUX=" + SELINUX=disabled + 2. Reboot the system. + ``` + # reboot + ``` + 3. The status is changed successfully. + ``` + # getenforce + Disabled + ``` +- Set the permissive mode when SELinux is disabled: + 1. Modify the SELinux configuration file **/etc/selinux/config** and set **SELINUX=permissive**. ``` + # cat /etc/selinux/config | grep "SELINUX=" SELINUX=permissive + 2. Create the **.autorelabel** file in the root directory. ``` - - ->![](./public_sys-resources/icon-note.gif) **NOTE:** ->When you switch between the disabled mode and the other mode, you need to restart the system for the switch to take effect. ->``` -># reboot ->``` - -## SELinux Commands - -- Query the SELinux mode. For example, the following shows that the SELinux mode is permissive. - + # touch /.autorelabel + ``` + 3. Reboot the system. The system will restart twice. + ``` + # reboot + ``` + 4. The status is changed successfully. ``` # getenforce Permissive ``` -- Set the SELinux mode. **0** indicates the permissive mode, and **1** indicates the enforcing mode. For example, run the following command to set the SELinux mode to enforcing. This command cannot be used to set the disabled mode. After the system is restarted, the mode set in **/etc/selinux/config** is restored. - +- Set the enforcing mode when SELinux is disabled: + 1. Set SELinux to the permissive mode. + 2. Modify the SELinux configuration file **/etc/selinux/config** and set **SELINUX=enforcing**. ``` - # setenforce 1 + # cat /etc/selinux/config | grep "SELINUX=" + SELINUX=enforcing + ``` + 3. Reboot the system. + ``` + # reboot ``` + 4. The status is changed successfully. + ``` + # getenforce + Enforcing + ``` + +## SELinux Commands -- Query the SELinux status. **SELinux status** indicates the SELinux status. **enabled** indicates that SELinux is enabled, and **disabled** indicates that SELinux is disabled. **Current mode** indicates the current security policy of the SELinux. +- Query the SELinux status. **SELinux status** indicates the SELinux status. **enabled** indicates that SELinux is enabled, and **disabled** indicates that SELinux is disabled. **Current mode** indicates the current mode of the SELinux. ``` # sestatus @@ -63,5 +100,123 @@ SELinux is enabled for openEuler by default and the default mode is enforcing. Y Memory protection checking: actual (secure) Max kernel policy version: 31 ``` +## Adding Policies +- Obtain and add missing policies based on the audit logs. (The audit service must be enabled and SELinux access denial logs must exist in audit logs.) + 1. Check whether the audit logs contain SELinux access denial logs. Use the actual audit log path. + ``` + # grep avc /var/log/audit/audit.log* + ``` + 2. Query missing rules. + ``` + # audit2allow -a /var/log/audit/audit.log* + ``` + 3. Generate a policy module based on the missing rule and name it **demo**. + ``` + # audit2allow -a /var/log/audit/audit.log* -M demo + ******************** IMPORTANT *********************** + To make this policy package active, execute: + semodule -i demo.pp + ``` + 4. Load the **demo** policy module. + ``` + # semodule -i demo.pp + ``` +- Compose and add the SELinux policy module. + 1. Compose the FC file (if the security context of file creation is involved). + ``` + # cat demo.fc + /usr/bin/example -- system_u:object_r:example_exec_t:s0 + /resource -- system_u:object_r:resource_file_t:s0 + ``` + 1. Compose the TE file (example). + ``` + # cat demo.te + module demo 1.0; + require + { + role unconfined_r; + role system_r; + type user_devpts_t; + type root_t; + attribute file_type; + attribute domain; + class dir { getattr search add_name create open remove_name rmdir setattr write }; + class file { entrypoint execute getattr open read map setattr write create }; + class process { sigchld rlimitinh siginh transition setcap getcap }; + class unix_stream_socket { accept bind connect listen recvfrom sendto listen create lock read write getattr setattr getopt setopt append shutdown ioctl connectto }; + class capability { chown dac_override dac_read_search }; + class chr_file { append getattr ioctl read write }; + }; + role unconfined_r types example_t; + role system_r types example_t; + type example_exec_t, file_type; + type resource_file_t, file_type; + type example_t, domain; + allow example_t user_devpts_t : chr_file { append getattr ioctl read write }; + allow example_t file_type : dir { getattr search }; + allow example_t example_exec_t : file { entrypoint execute getattr map open read }; + allow domain example_exec_t : file { execute getattr map open read }; + allow example_t example_exec_t : process { sigchld }; + allow domain example_t : process { rlimitinh siginh transition }; + allow example_t resource_file_t : file { create getattr open read setattr write }; + allow example_t root_t : dir { add_name create getattr open remove_name rmdir search setattr write }; + allow example_t example_t : unix_stream_socket { accept append bind connect create getattr getopt ioctl listen listen lock read recvfrom sendto setattr setopt shutdown write }; + allow example_t domain : unix_stream_socket { connectto }; + allow example_t example_t : capability { chown dac_override dac_read_search }; + allow example_t example_t : process { getcap setcap }; + type_transition domain example_exec_t : process example_t; + type_transition example_t root_t : file resource_file_t "resource"; + ``` + 1. Compile **demo.te** as **demo.mod**. + ``` + # checkmodule -Mmo demo.mod demo.te + ``` + 1. Package **demo.mod** and **demo.fc** as a policy module file. + ``` + semodule_package -m demo.mod -f demo.fc -o demo.pp + ``` + 1. Load the policy module. + ``` + # semodule -i demo.pp + ``` + 1. Delete the loaded policy module file. + ``` + # semodule -r demo + libsemanage.semanage_direct_remove_key: Removing last demo module (no other demo module exists at another priority). + ``` + +## Function Verification +- SELinux adopts an whitelist mechanism. Modules that are not configured with proper policies may fail to run properly due to lack of permissions. It is necessary to verify the functions of the modules and configure reasonable rules. + 1. Check whether the audit service is enabled: + ``` + # systemctl status auditd + ``` + 1. Set the SELinux mode to permissive. (Alarms are printed, but SELinux polices are not enforced. For details, see [Configuration Description](#configuration-description).) + ``` + # getenforce + Permissive + ``` + 1. Execute all function cases of the test module and check the SELinux access denial logs in the audit logs. + ``` + # grep avc /var/log/audit/audit.log* + ``` + 1. Analyze access denial logs and filter out missing rules. + ``` + type=AVC msg=audit(1596161643.271:1304): avc: denied { read } for pid=1782603 comm="smbd" name=".viminfo" dev="dm-0" ino=2488208 scontext=system_u:system_r:smbd_t:s0 tcontext=staff_u:object_r:user_home_t:s0 tclass=file permissive=1 + Indicates that the smbd process (security context: system_u:system_r:smbd_t:s0) is denied the permission to read the .viminfo file (security context: staff_u:object_r:user_home_t:s0). + permissive=1 indicates that the permissive mode is running. This log records only the operations that are not forbidden. + ``` + 1. Supplement the missing rules by referring to [Adding Policies](#adding-policies). + +## Precautions + +- Before enabling SELinux, you are advised to upgrade selinux-policy to the latest version using DNF. Otherwise, applications may fail to run properly. For example: + + ``` + dnf update selinux-policy -y + ``` + +- If the system cannot be started due to improper SELinux configuration (for example, a policy is deleted by mistake or no proper rule or security context is configured), you can add **selinux=0** to the startup parameters to disable SELinux. +- After SELinux is enabled, permission check is performed on access behaviors, which affects the operating system performance to some extent (related to the frequency of access operations in the running environment). diff --git a/docs/en/docs/commercial_cryptography_features/comm_crypto_app_conf.md b/docs/en/docs/commercial_cryptography_features/comm_crypto_app_conf.md new file mode 100644 index 000000000..30404ce4c --- /dev/null +++ b/docs/en/docs/commercial_cryptography_features/comm_crypto_app_conf.md @@ -0,0 +1 @@ +TODO \ No newline at end of file diff --git a/docs/en/docs/thirdparty_migration/OpenStack-train.md b/docs/en/docs/thirdparty_migration/OpenStack-train.md index 0816483f0..7ad42a286 100644 --- a/docs/en/docs/thirdparty_migration/OpenStack-train.md +++ b/docs/en/docs/thirdparty_migration/OpenStack-train.md @@ -37,7 +37,7 @@ OpenStack is an open source cloud computing infrastructure software project deve As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. -The official source of openEuler 20.03-LTS-SP3 now supports OpenStack Train. You can configure the Yum source then deploy OpenStack by following the instructions of this document. +The official source of openEuler 22.03-LTS now supports OpenStack Train. You can configure the Yum source then deploy OpenStack by following the instructions of this document. ## Conventions diff --git a/docs/en/docs/thirdparty_migration/openstack.md b/docs/en/docs/thirdparty_migration/openstack.md new file mode 100644 index 000000000..53304cbfd --- /dev/null +++ b/docs/en/docs/thirdparty_migration/openstack.md @@ -0,0 +1 @@ +openEuler OpenStack documents have been moved to [OpenStack SIG Doc](https://openeuler.gitee.io/openstack/). diff --git a/docs/en/docs/thirdparty_migration/thidrparty.md b/docs/en/docs/thirdparty_migration/thidrparty.md index 3006ebf93..66f591266 100644 --- a/docs/en/docs/thirdparty_migration/thidrparty.md +++ b/docs/en/docs/thirdparty_migration/thidrparty.md @@ -1,5 +1,3 @@ # Third-Party Software Porting Guide -This document helps you quickly port and deploy third-party software on openEuler. - This document is intended for community developers, open source enthusiasts, and partners who use the openEuler OS and intend to learn more about third-party software. Basic knowledge about the Linux OS is required for reading this document. \ No newline at end of file diff --git a/docs/en/docs/userguide/images/panel.png b/docs/en/docs/userguide/images/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..1e532446d7dd6c5208475bcfeae3dc717c6fe051 GIT binary patch literal 39247 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

?*EmLn4{*^>nSBTb8 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 literal 0 HcmV?d00001 diff --git a/docs/en/docs/userguide/patch-tracking.md b/docs/en/docs/userguide/patch-tracking.md index 67586ab4d..662b2767e 100644 --- a/docs/en/docs/userguide/patch-tracking.md +++ b/docs/en/docs/userguide/patch-tracking.md @@ -3,20 +3,22 @@ - [patch-tracking](#patch-tracking) - - [Overview](#overview) - - [Architecture](#architecture) - - [C/S Architecture](#cs-architecture) - - [Core Procedure](#core-procedure) - - [Data structure](#data-structure) - - [Tool Deployment](#tool-deployment) - - [Downloading Software](#downloading-software) - - [Installing the Tool](#installing-the-tool) - - [Generating a Certificate](#generating-a-certificate) - - [Configuring Parameters](#configuring-parameters) - - [Starting the Patch Tracking Service](#starting-the-patch-tracking-service) - - [Tool Usage](#tool-usage) - - [FAQ](#faq) - - [When I access api.github.com, the connection is refused.](#when-i-access-apigithubcom-the-connection-is-refused) + - [Overview](#overview) + - [Architecture](#architecture) + - [C/S Architecture](#cs-architecture) + - [Core Procedure](#core-procedure) + - [Data structure](#data-structure) + - [Tool Deployment](#tool-deployment) + - [Downloading Software](#downloading-software) + - [Installing the Tool](#installing-the-tool) + - [Generating a Certificate](#generating-a-certificate) + - [Configuring Parameters](#configuring-parameters) + - [Starting the Patch Tracking Service](#starting-the-patch-tracking-service) + - [Tool Usage](#tool-usage) + - [FAQ](#faq) + - [When I access api.github.com, the connection is refused.](#when-i-access-apigithubcom-the-connection-is-refused) + - [Symptom](#symptom) + - [Cause Analysis](#cause-analysis) @@ -335,4 +337,4 @@ During the operation of the patch-tracking, the following error message may occu #### Cause Analysis -The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, Huawei Cloud Hong Kong). \ No newline at end of file +The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, [Huawei CLOUD Elastic Cloud Server](https://www.huaweicloud.com/intl/en-us/product/ecs.html)). \ No newline at end of file diff --git a/docs/en/docs/userguide/pkgship.md b/docs/en/docs/userguide/pkgship.md index 569325f84..fcfbd7d7a 100644 --- a/docs/en/docs/userguide/pkgship.md +++ b/docs/en/docs/userguide/pkgship.md @@ -2,24 +2,26 @@ - [pkgship](#pkgship) - - [Introduction](#Introduction) - - [Architecture](#Architecture) - - [Downloading the Software](#Downloading the Software) - - [Operating Environment](#Operating Environment) - - [Installing the Tool](#Installing the Tool) - - [Configuring Parameters](#Configuring Parameters) - - [Starting and Stopping the Service](#Starting and Stopping the Service) - - [Using the Tool](#Using the Tool) - - [Viewing and Dumping Logs](#Viewing and Dumping Logs) + - [Introduction](#introduction) + - [Architecture](#architecture) + - [Using the Software Online](#using-the-software-online) + - [Downloading the Software](#downloading-the-software) + - [Operating Environment](#operating-environment) + - [Installing the Tool](#installing-the-tool) + - [Configuring Parameters](#configuring-parameters) + - [Starting and Stopping the Service](#starting-and-stopping-the-service) + - [Using the Tool](#using-the-tool) + - [Viewing and Dumping Logs](#viewing-and-dumping-logs) + - [pkgship-panel](#pkgship-panel) ## Introduction -The pkgship is a query tool used to manage the dependency of OS software packages and provide a complete dependency graph. The pkgship provides functions such as software package dependency query, lifecycle management, and patch query. +The pkgship is a query tool used to manage the dependency of OS software packages and provide a complete dependency graph. The pkgship provides functions such as software package dependency query and lifecycle management. -1. Software package dependency query: Allow community personnel to understand the impact on software when software packages are introduced, updated, or deleted. -2. Patch query: Allow community personnel to learn about the patches in the openEuler software package and obtain the patch information. For details, see [patch-tracking](../patch-tracking/README.md). +1. Software package basic information query: Allow community personnel to quickly obtain information about the name, version, and description of the software package. +2. Software package dependency query: Allow community personnel to understand the impact on software when software packages are introduced, updated, or deleted. ## Architecture @@ -27,11 +29,17 @@ The system uses the Flask-RESTful development mode. The following figure shows t ![avatar](./images/packagemanagement.png) +## Using the Software Online + +pkgship provides a [public online service](https://pkgmanage.openeuler.org/Packagemanagement). You can directly use pkgship online if you do not need to customize your query. + +To use a custom data source, install, configure, and use pkgship by referring to the following sections. + ## Downloading the Software * The repo source is officially released at: * You can obtain the source code at: -* You can obtain the RPM package at: +* You can obtain the RPM package at: ## Operating Environment @@ -41,6 +49,7 @@ The system uses the Flask-RESTful development mode. The following figure shows t |----------|----------| | CPU| 8 cores| | Memory| 32 GB (minimum: 4 GB)| +| Dive space| 20 GB| | Network bandwidth| 300 Mbit/s| | I/O| 375 MB/s| @@ -192,7 +201,7 @@ priority: 2 > > The SQLite file path cannot be configured directly. > -> The value of **dbname** can contain only lowercase letters and digits. +> The value of **dbname** can contain only lowercase letters, digits, periods (.), hyphens (-), underscores (_), and plus signs (+), and must start and end with lower case letters or digits. ## Starting and Stopping the Service @@ -409,3 +418,18 @@ Permission: The permissions on the path and the log file are 700 and 644, respec When the pkgship is started, the script for dumping data runs in the background. From the startup, dumping and compression are performed every other day. A total of 30 compressed files are retained. The compressed file name is **uwsgi.log-20201010***x***.zip**, where *x* indicates the hour when the file is compressed. After the pkgship is stopped, the script for dumping data is stopped and data is not dumped . When the pkgship is started again, the script for dumping data is executed again. + +## pkgship-panel + +### Introduction + +pkgship-panel integrates software package build information and maintenance information so that version maintenance personnel can quickly identify abnormal software packages and notify the package owners to solve the problems, ensuring build project stability and improving the OS build success rate. + +### Architecture + +![](images/panel.png) + +### Using the Tool + +The data source of pkgship-panel cannot be configured. You are advised to use the [pkgship-panel official website](https://pkgmanage.openeuler.org/Infomanagement). + diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 43140e2fa..4371e8013 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -178,7 +178,7 @@ headless: true - [KubeEdge Usage Guide]({{< relref "./docs/KubeEdge/kubeedge-usage-guide.md" >}}) - [KubeEdge Deployment Guide]({{< relref "./docs/KubeEdge/kubeedge-deployment-guide.md" >}}) - [Third-Party Software Deployment Guide]({{< relref "./docs/thirdparty_migration/thidrparty.md" >}}) - - [OpenStack-Wallaby Deployment Guide]({{< relref "./docs/thirdparty_migration/OpenStack-wallaby.md" >}}) + - [OpenStack]({{< relref "./docs/thirdparty_migration/openstack.md" >}}) - [HA User Guide]({{< relref "./docs/desktop/ha.md" >}}) - [Deploying an HA Cluster]({{< relref "./docs/thirdparty_migration/installha.md" >}}) - [HA Usage Example]({{< relref "./docs/desktop/HA_usage_example.md" >}}) -- Gitee From 8658e23f06287a626d6a390b7d7375b8b213ea85 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 03:51:39 +0000 Subject: [PATCH 119/130] =?UTF-8?q?add=20docs/zh/docs/memory-fabric/Memory?= =?UTF-8?q?=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...4\250\346\210\267\346\214\207\345\215\227" | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 "docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" new file mode 100644 index 000000000..3f11f556f --- /dev/null +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -0,0 +1,34 @@ +1、简介 +内存池套件设计目标为基于内存型介质和新型网络技术,构建高性能的分布式内存资源池,并通过BigMemory、MemPlog、MemKV等语义对应用提供服务。内存池套件使用和管理的资源来自于计算节点或者单独资源节点提供的可共享的DRAM/Persistent Memory/内存盘等(不支持普通disk直接互联池化)。结合新型互联协议(RDMA,CXL,UBUS)us级传输时延,期望内存池套件通过极低的软件时延和节点CPU开销带来整体性能提升。 +2、部署 +Memory Fabric需要支持多场景应用集成部署,根据节点类型、资源分布情况和应用需求对集成部署做如下描述: +(1) 计算和MF资源共节点时支持client和server同节点部署,如下图node1、node2所示。 +(2) 资源独立提供时也支持client、server分离节点部署,如下图node3、node4所示。 +(3) 支持(1)(2)场景混合部署。 +(4) 节点内支持多client,也支持多server模式部署,如下图node2所示。 +(5) client与同节点的server通信使用IPC,配置支持连接远端server时使用RPC通信。 +(6) server端接入集群管理服务中,用于统一的节点编号和资源信息广播。 + +3、启动 +Memory Fabric启动分为server和client两个部分。在节点上优先启动server端,完成集群注册、监控流程,然后启动本地资源注册(总容量通过配置文件获取)和通信建链流程,初始化完成后支持本地多client与server建立链接,可对外启动业务服务 +4、接口 +接口 说明 +int BM_Init(char *ockPath, int flags); +int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); int BM_Exit(void); 初始化 +带属性的初始化 +退出 +int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId); +int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId); +int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen); Namespace创建和销毁、查询 +int BM_AllocSec(BmInfo *bminfo, size_t size, int flags, BmAffinity* affinity); +int BM_FreeSec(BmInfo *bminfo, int flags); +int BM_BatchFreeSec(char *bmIdArray[], int num, int flags, const char *ns, const char *secId); Bigmemory对象申请和释放 +int BM_ExpandSec(BmInfo *bminfo, size_t size, int flags); bigMemory扩容 +int BM_MapSec(BmInfo *bminfo, int prot, int flags, void **ptr); +int BM_Unmap(char *bmId, void *ptr); bigMemory到连续虚拟空间map和unmap +int BM_CopySec(BmInfo *srcBM, size_t srcOffset, BmInfo *dstBM, size_t dstOffset, size_t length, int flags); bigMemory对象间拷贝 +int BM_SpecificObjSwapInSec(DiskFileDesc *file, BmInfo *bminfo, int flags, size_t offset, size_t length); 文件内容换入bigmemory对象 +int BM_ReadSec(BmInfo *bminfo, size_t offset, size_t length, void *buffer, int flags); +int BM_WriteSec(BmInfo *bminfo, size_t offset, size_t length, const void *buffer, int flags); Bigmemory读写 +int BM_GatherSec(intptr_t *inputInfo, BmOperatorCode operatorCode, int flags, BmInfo *bminfo, size_t *bmLen); 聚合操作接口 + -- Gitee From fd1c0d19009d14f950ef6964c0bcb655222940d3 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 04:40:53 +0000 Subject: [PATCH 120/130] =?UTF-8?q?update=20docs/zh/docs/memory-fabric/Mem?= =?UTF-8?q?ory=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...4\250\346\210\267\346\214\207\345\215\227" | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" index 3f11f556f..5c330e39b 100644 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -1,6 +1,18 @@ -1、简介 +# Memory Fabric用户指南 + + + +- [#Memory Fabric用户指南](#Memory Fabric用户指南) + - [简介](#简介) + - [部署](#部署) + - [启动](#启动) + - [接口](#接口) + + + +## 简介 内存池套件设计目标为基于内存型介质和新型网络技术,构建高性能的分布式内存资源池,并通过BigMemory、MemPlog、MemKV等语义对应用提供服务。内存池套件使用和管理的资源来自于计算节点或者单独资源节点提供的可共享的DRAM/Persistent Memory/内存盘等(不支持普通disk直接互联池化)。结合新型互联协议(RDMA,CXL,UBUS)us级传输时延,期望内存池套件通过极低的软件时延和节点CPU开销带来整体性能提升。 -2、部署 +## 部署 Memory Fabric需要支持多场景应用集成部署,根据节点类型、资源分布情况和应用需求对集成部署做如下描述: (1) 计算和MF资源共节点时支持client和server同节点部署,如下图node1、node2所示。 (2) 资源独立提供时也支持client、server分离节点部署,如下图node3、node4所示。 @@ -9,9 +21,20 @@ Memory Fabric需要支持多场景应用集成部署,根据节点类型、资 (5) client与同节点的server通信使用IPC,配置支持连接远端server时使用RPC通信。 (6) server端接入集群管理服务中,用于统一的节点编号和资源信息广播。 -3、启动 +## 启动 Memory Fabric启动分为server和client两个部分。在节点上优先启动server端,完成集群注册、监控流程,然后启动本地资源注册(总容量通过配置文件获取)和通信建链流程,初始化完成后支持本地多client与server建立链接,可对外启动业务服务 -4、接口 + +## 接口 +| 接口 | 说明 | +| ------------- | ------------------------------------------ | +|int BM_Init(char *ockPath, int flags); + int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); + int BM_Exit(void);| 初始化 + 带属性的初始化 + 退出 | +| Redis | 建议5.0.4及以上;建议大小配置为内存的3/4 | +| Python | 版本 3.8及以上 | + 接口 说明 int BM_Init(char *ockPath, int flags); int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); int BM_Exit(void); 初始化 -- Gitee From 7c226a83f1184ecf430066a705b83145eb77dbd2 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 04:42:25 +0000 Subject: [PATCH 121/130] =?UTF-8?q?update=20docs/zh/docs/memory-fabric/Mem?= =?UTF-8?q?ory=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...abric\347\224\250\346\210\267\346\214\207\345\215\227" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" index 5c330e39b..bfc90e036 100644 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -26,12 +26,12 @@ Memory Fabric启动分为server和client两个部分。在节点上优先启动s ## 接口 | 接口 | 说明 | -| ------------- | ------------------------------------------ | +| -----------------------------------------------------------| ------------------------------------------ | |int BM_Init(char *ockPath, int flags); int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); - int BM_Exit(void);| 初始化 - 带属性的初始化 - 退出 | + int BM_Exit(void); | 初始化 + 带属性的初始化 + 退出 | | Redis | 建议5.0.4及以上;建议大小配置为内存的3/4 | | Python | 版本 3.8及以上 | -- Gitee From 5ccfe3e843931b01caab6bd7eb3720b23bb85c2a Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 04:44:21 +0000 Subject: [PATCH 122/130] =?UTF-8?q?update=20docs/zh/docs/memory-fabric/Mem?= =?UTF-8?q?ory=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...bric\347\224\250\346\210\267\346\214\207\345\215\227" | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" index bfc90e036..8eaf52018 100644 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -27,11 +27,10 @@ Memory Fabric启动分为server和client两个部分。在节点上优先启动s ## 接口 | 接口 | 说明 | | -----------------------------------------------------------| ------------------------------------------ | -|int BM_Init(char *ockPath, int flags); - int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); - int BM_Exit(void); | 初始化 - 带属性的初始化 - 退出 | +|int BM_Init(char *ockPath, int flags); | 初始化 + int BM_InitWithExtAttr(char *ockPath, int flags, void *attr);| 带属性的初始化 + int BM_Exit(void); | 退出 | + | Redis | 建议5.0.4及以上;建议大小配置为内存的3/4 | | Python | 版本 3.8及以上 | -- Gitee From 0939fdbfb4504d777aa7d63a657cf047b05c34a8 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 04:47:39 +0000 Subject: [PATCH 123/130] =?UTF-8?q?update=20docs/zh/docs/memory-fabric/Mem?= =?UTF-8?q?ory=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...347\224\250\346\210\267\346\214\207\345\215\227" | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" index 8eaf52018..7fa233d8c 100644 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -26,12 +26,13 @@ Memory Fabric启动分为server和client两个部分。在节点上优先启动s ## 接口 | 接口 | 说明 | -| -----------------------------------------------------------| ------------------------------------------ | -|int BM_Init(char *ockPath, int flags); | 初始化 - int BM_InitWithExtAttr(char *ockPath, int flags, void *attr);| 带属性的初始化 - int BM_Exit(void); | 退出 | - -| Redis | 建议5.0.4及以上;建议大小配置为内存的3/4 | +| -----------------------------------------------------------| --------------------------------------------------------- | +|int BM_Init(char *ockPath, int flags); | 初始化 + int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); | 带属性的初始化 + int BM_Exit(void); | 退出 | +|int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId); + int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId); + int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen); | Namespace创建和销毁、查询 | | Python | 版本 3.8及以上 | 接口 说明 -- Gitee From dd8b8e8697e1c2f86162cd80306777fe6851b8c4 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 29 Aug 2022 06:22:10 +0000 Subject: [PATCH 124/130] =?UTF-8?q?update=20docs/zh/docs/memory-fabric/Mem?= =?UTF-8?q?ory=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...mory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" index 7fa233d8c..0c0d86eb8 100644 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" @@ -26,7 +26,7 @@ Memory Fabric启动分为server和client两个部分。在节点上优先启动s ## 接口 | 接口 | 说明 | -| -----------------------------------------------------------| --------------------------------------------------------- | +| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |int BM_Init(char *ockPath, int flags); | 初始化 int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); | 带属性的初始化 int BM_Exit(void); | 退出 | -- Gitee From 8a5ec6d0ca9721989fba6f00c608bdf6522e1d12 Mon Sep 17 00:00:00 2001 From: Zhang Yang Date: Mon, 29 Aug 2022 18:34:09 +0800 Subject: [PATCH 125/130] StratoVirt: introduce free page reporting of balloon(zh) Signed-off-by: Zhang Yang --- ...2\346\213\237\346\234\272\351\205\215\347\275\256.md" | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index 9ca583e37..4a7740035 100644 --- "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -459,20 +459,21 @@ $ mount -t hugetlbfs hugetlbfs /path/to/hugepages 轻量级虚拟机: ``` --device virtio-balloon-device,deflate-on-oom=true +-device virtio-balloon-device[,deflate-on-oom=true|false][,free-page-reporting=true|false] ``` 标准虚拟机: ``` --device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0,deflate-on-oom=true[,multifunction=on] +-device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0[,deflate-on-oom=true|false][,free-page-reporting=true|false][,multifunction=on|off] ``` ![](./public_sys-resources/icon-note.gif)**说明** 1. deflate-on-oom的取值为bool类型,表示是否开启auto deflate特性。开启时,如果balloon已经回收部分内存,当guest需要内存时,balloon设备会自动放气,归还内存给guest。不开启则不会自动归还。 -2. 使用qmp命令回收虚拟机内存时,应确保回收后虚拟机仍然有足够的内存来保持最基本的运行。否则可能会出现一些操作超时,以及导致虚拟机内部无法申请到空闲内存等现象。 -3. 如果虚拟机内部开启内存大页,balloon不能回收大页占用内存。 +2. free-page-reporting的取值为bool类型,表示是否开启free page reporting特性。开启时,如果guest内核向balloon设备发送了free pages,balloon将释放free pages所占用的内存。不开启则guest内核不会向balloon设备发送free pages。 +3. 使用qmp命令回收虚拟机内存时,应确保回收后虚拟机仍然有足够的内存来保持最基本的运行。否则可能会出现一些操作超时,以及导致虚拟机内部无法申请到空闲内存等现象。 +4. 如果虚拟机内部开启内存大页,balloon不能回收大页占用内存。 > deflate-on-oom=false时,当Guest中内存不足时,balloon不会自动放气并归还内存,可能会引起Guest内部OOM,进程被Kill,甚至虚拟机无法正常运行。 -- Gitee From 45bb428ca6c812a3e24a6559c96adaf961e9fd63 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 2 Sep 2022 02:29:47 +0000 Subject: [PATCH 126/130] =?UTF-8?q?add=20docs/zh/docs/memory-fabric/Memory?= =?UTF-8?q?=20Fabric=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dream03 --- ...50\346\210\267\346\214\207\345\215\227.md" | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 "docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" new file mode 100644 index 000000000..786dfc6d2 --- /dev/null +++ "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" @@ -0,0 +1,97 @@ +# Memory Fabric用户文档 + +- [简介](简介.md) +- [部署](部署.md) +- [启动](启动.md) +- [接口](接口.md) + +# 简介 + +内存池套件是基于内存型介质和新型网络技术,构建高性能的分布式内存资源池,并通过BigMemory、MemPlog、MemKV等语义对应用提供服务。 + +内存池套件使用和管理的资源来自计算节点或者单独资源节点提供的可共享的DRAM/Persistent Memory/内存盘等(不支持普通disk直接互联池化),结合新型互联协议(RDMA,CXL,UBUS)us级传输时延,期望内存池套件通过极低的软件时延和节点CPU开销带来整体性能提升。 + +# 部署 + +Memory Fabric需要根据节点类型、资源分布情况和应用需求做到多场景应用集成部署,具体描述如下: + +- 计算和MF资源共节点时支持client和server同节点部署,如[图1](#fig17349154610267)node1、node2所示。 +- 资源独立提供时也支持client、server分离节点部署,如[图1](#fig17349154610267)node3、node4所示。 +- 支持同节点部署和分离节点部署两种场景混合部署。 +- 节点内支持多client,也支持多server模式部署,如[图1](#fig17349154610267)node2所示。 +- client与同节点的server通信使用IPC,配置支持连接远端server时使用RPC通信。 +- server端接入集群管理服务中,用于统一的节点编号和资源信息广播。 + +**图 1** 集成部署 +![](figures/集成部署.png "集成部署") + +# 启动 + +Memory Fabric启动分为server和client两个部分。在节点上优先启动server端,完成集群注册、监控流程,然后启动本地资源注册\(总容量通过配置文件获取\)和通信建链流程,初始化完成后支持本地多client与server建立连接,可对外启动业务服务。 + +# 接口 + + + +

部件名称

@@ -204,9 +224,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 ## 硬件兼容性 -openEuler已验证支持的服务器和各部件典型配置请参见[表6](#zh-cn_topic_0227922427_table39822012)。openEuler后续将逐步增加对其他服务器的支持,也欢迎广大合作伙伴/开发者参与贡献和验证。openEuler当前支持的服务器可见[兼容列表](https://www.openeuler.org/zh/compatibility/)。 +openEuler已验证支持的服务器和各部件典型配置请参见[表7](#zh-cn_topic_0227922427_table39822012)。openEuler后续将逐步增加对其他服务器的支持,也欢迎广大合作伙伴/开发者参与贡献和验证。openEuler当前支持的服务器可见[兼容列表](https://www.openeuler.org/zh/compatibility/)。 -**表 6** 支持的服务器及典型配置 +**表 7** 支持的服务器及典型配置

厂商

diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 10868e4af..96a9cc64d 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -139,11 +139,12 @@ headless: true - [常见问题与解决方法]({{< relref "./docs/A-Tune/常见问题与解决方法.md" >}}) - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) + - [openEuler Embedded 22.03发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/构建指导.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) - - [openEuler Embedded容器构建指导]({{< relref "./docs/Embedded/openEuler Embedded容器构建指导.md" >}}) + - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [快速构建指导]({{< relref "./docs/Embedded/快速构建指导.md" >}}) + - [容器构建指导]({{< relref "./docs/Embedded/容器构建指导.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From b7aa50b1ed9a2a4c6a45814a1d3dd1640201defe Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 16:03:27 +0800 Subject: [PATCH 016/130] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=88=97=E8=A1=A8=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E9=94=99=E8=AF=AF=20=E4=BF=AE=E6=94=B9=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=88=97=E8=A1=A8=E5=90=8D=E7=A7=B0?= =?UTF-8?q?=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- .../\347\263\273\347\273\237\345\256\211\350\243\205.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index ac05dbab2..7424d86a5 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -116,9 +116,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 | arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | | arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | | arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | -| arm64/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | -| arm64/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | -| arm64/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| arm32/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | +| arm32/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm32/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | | source-list/manifest.xml | 构建使用的源码清单 | **表 5** repo源列表 -- Gitee From 096cc7e442c142a66a7df993029dcf37861046c3 Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 16:08:35 +0800 Subject: [PATCH 017/130] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=B5=8C=E5=85=A5?= =?UTF-8?q?=E5=BC=8F=E9=95=9C=E5=83=8F=E5=90=8D=E7=A7=B0=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=B5=8C=E5=85=A5=E5=BC=8F=E9=95=9C=E5=83=8F=E5=90=8D?= =?UTF-8?q?=E7=A7=B0=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- .../\347\263\273\347\273\237\345\256\211\350\243\205.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index 7424d86a5..d013e5af0 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -116,9 +116,9 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03 | arm64/aarch64-std/zImage | aarch64架构下支持qemu的内核镜像 | | arm64/aarch64-std/\*toolchain-22.03.sh | aarch64架构下对应的开发编译链 | | arm64/aarch64-std/\*rootfs.cpio.gz | aarch64架构下支持qemu的文件系统 | -| arm32/aarch64-std/zImage | arm架构下支持qemu的内核镜像 | -| arm32/aarch64-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | -| arm32/aarch64-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | +| arm32/arm-std/zImage | arm架构下支持qemu的内核镜像 | +| arm32/arm-std/\*toolchain-22.03.sh | arm架构下对应的开发编译链 | +| arm32/arm-std/\*rootfs.cpio.gz | arm架构下支持qemu的文件系统 | | source-list/manifest.xml | 构建使用的源码清单 | **表 5** repo源列表 -- Gitee From 625c93d6676aaae682755679a87c4e53151cccdb Mon Sep 17 00:00:00 2001 From: hwyytw Date: Thu, 31 Mar 2022 19:44:04 +0800 Subject: [PATCH 018/130] =?UTF-8?q?=E6=A0=B9=E6=8D=AE=E6=A3=80=E8=A7=86?= =?UTF-8?q?=E6=84=8F=E8=A7=81=E4=BF=AE=E6=94=B9=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9B=AE=E5=BD=95=E7=BB=93=E6=9E=84=E5=92=8C=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E6=A0=87=E9=A2=98=EF=BC=8C=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86?= =?UTF-8?q?=E9=94=99=E8=AF=AF=EF=BC=8C=E8=A1=A5=E5=85=85=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E6=8C=87=E5=AF=BC=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...DK\345\272\224\347\224\250\345\274\200\345\217\221.md" | 3 ++- ...\236\204\345\273\272\346\214\207\345\257\274.markdown" | 5 ++++- ...\236\204\345\273\272\346\214\207\345\257\274.markdown" | 2 +- docs/zh/menu/index.md | 8 ++++---- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 96bc29e1e..97be7a4c3 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -7,7 +7,8 @@ - [安装SDK](#安装SDK) - [使用SDK编译hello world样例](#使用SDK编译hello world样例) - [使用SDK编译内核模块样例](#使用SDK编译内核模块样例) -- + + ### 安装SDK diff --git "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index f9776a511..eb0f6a530 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/openEuler Embedded\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,4 +1,7 @@ openEuler Embedded构建指导 ===================== -本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 \ No newline at end of file +本文档主要提供了两种方式准备构建环境,并描述了详细的构建流程。用户根据需要选择一种方式即可。 + +- 初步的openEuler Embedded构建体系, 详见[快速构建指导](./快速构建指导.html) +- 容器化构建,详见[容器构建指导](./容器构建指导.html) \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index a0803aa14..7b7fe2d22 100644 --- "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -1,4 +1,4 @@ -openEuler Embedded容器构建指导 +容器构建指导 ============================== 由于openEuler Embedded构建过程需要基于openEuler操作系统,且需要安装较多系统工具和构建工具。为方便开发人员快速搭建构建环境,我们将构建过程所依赖的操作系统和工具封装到一个容器中,这就使得开发人员可以快速搭建一个构建环境,进而投入到代码开发中去,避免在准备环境阶段消耗大量时间。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index ff6949735..7b9fe8426 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -139,12 +139,12 @@ headless: true - [常见问题与解决方法]({{< relref "./docs/A-Tune/常见问题与解决方法.md" >}}) - [附录]({{< relref "./docs/A-Tune/附录.md" >}}) - [Embedded用户指南]({{< relref "./docs/Embedded/embedded.md" >}}) - - [openEuler Embedded 22.03发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) - - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) - - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - - [openEuler Embedded构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) + - [发行说明]({{< relref "./docs/Embedded/openEuler Embedded 22.03发行说明.md" >}}) + - [构建指导]({{< relref "./docs/Embedded/openEuler Embedded构建指导.md" >}}) - [快速构建指导]({{< relref "./docs/Embedded/快速构建指导.md" >}}) - [容器构建指导]({{< relref "./docs/Embedded/容器构建指导.md" >}}) + - [安装与运行]({{< relref "./docs/Embedded/安装与运行.md" >}}) + - [SDK应用开发]({{< relref "./docs/Embedded/SDK应用开发.md" >}}) - [内核热升级指南]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - [安装与部署]({{< relref "./docs/KernelLiveUpgrade/安装与部署.md" >}}) - [使用方法]({{< relref "./docs/KernelLiveUpgrade/使用方法.md" >}}) -- Gitee From 877bb8f2a76d747490c0338db286600682d64a1a Mon Sep 17 00:00:00 2001 From: yaozc701 Date: Sat, 2 Apr 2022 16:05:02 +0800 Subject: [PATCH 019/130] fix some error link --- .../\345\217\202\344\270\216\350\264\241\347\214\256.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/Releasenotes/\345\217\202\344\270\216\350\264\241\347\214\256.md" "b/docs/zh/docs/Releasenotes/\345\217\202\344\270\216\350\264\241\347\214\256.md" index ba43d4adf..66afb1466 100644 --- "a/docs/zh/docs/Releasenotes/\345\217\202\344\270\216\350\264\241\347\214\256.md" +++ "b/docs/zh/docs/Releasenotes/\345\217\202\344\270\216\350\264\241\347\214\256.md" @@ -1,20 +1,20 @@ # 参与贡献 -作为openEuler用户,你可以通过多种方式协助openEuler社区。参与社区贡献的方法请参见[贡献攻略](https://openeuler.org/zh/community/contribution/),这里简单列出部分方式供参考。 +作为openEuler用户,你可以通过多种方式协助openEuler社区。参与社区贡献的方法请参见[贡献攻略](https://www.openeuler.org/zh/community/contribution/),这里简单列出部分方式供参考。 ## 特别兴趣小组 -openEuler将拥有共同兴趣的人们聚在一起,组成了不同的特别兴趣小组(SIG)。当前已有的SIG请参见[SIG列表](https://openeuler.org/zh/sig/sig-list/)。 +openEuler将拥有共同兴趣的人们聚在一起,组成了不同的特别兴趣小组(SIG)。当前已有的SIG请参见[SIG列表](https://www.openeuler.org/zh/sig/sig-list/)。 我们欢迎并鼓励你加入已有的SIG或创建新的SIG,创建方法请参见[SIG管理指南](https://gitee.com/openeuler/community/blob/master/zh/technical-committee/governance/README.md)。 ## 邮件列表和任务 -欢迎你积极地帮助用户解决在[邮件列表](https://openeuler.org/zh/community/mailing-list/)和issue任务(包括[代码仓任务](https://gitee.com/organizations/openeuler/issues)和[软件包仓任务](https://gitee.com/organizations/src-openeuler/issues)) 中提出的问题。另外,我们也欢迎你提出问题。这些都将帮助openEuler社区更好地发展。 +欢迎你积极地帮助用户解决在[邮件列表](https://www.openeuler.org/zh/community/mailing-list/)和issue任务(包括[代码仓任务](https://gitee.com/organizations/openeuler/issues)和[软件包仓任务](https://gitee.com/organizations/src-openeuler/issues)) 中提出的问题。另外,我们也欢迎你提出问题。这些都将帮助openEuler社区更好地发展。 ## 文档 -你不仅可以通过提交代码参与社区贡献,我们也欢迎你反馈遇到的问题、困难,或者对文档易用性、完整性的改进建议等。例如获取软件或文档过程中的问题,使用系统过程中的难点。欢迎关注并改进[openEuler社区](https://openeuler.org/zh/)的文档模块。 +你不仅可以通过提交代码参与社区贡献,我们也欢迎你反馈遇到的问题、困难,或者对文档易用性、完整性的改进建议等。例如获取软件或文档过程中的问题,使用系统过程中的难点。欢迎关注并改进[openEuler社区](https://www.openeuler.org/zh/)的文档模块。 ## IRC -- Gitee From 26db81b7a797387feb93e1f85cac6c4eaf9b5b72 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:09:06 +0000 Subject: [PATCH 020/130] =?UTF-8?q?update=20README.md.=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=96=87=E6=A1=A3=E6=8D=89=E8=99=AB=E6=B4=BB=E5=8A=A8?= =?UTF-8?q?=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index a9fd16651..95450c2de 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ [English](./README-en.md) | 简体中文 +文档捉虫活动火热进行中,欢迎参加: +[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +[点我查看活动详情](#https://docs-bug.openeuler.sh/) + ### 介绍 Docs包含了openEuler社区的所有文档,包括发行说明、操作系统安装、管理员指南、虚拟化和容器的使用指导、A-Tune使用指导和应用开发指导等内容。 -- Gitee From e846c2741179e93ceda1d535aaaaac491a86cc35 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:11:18 +0000 Subject: [PATCH 021/130] update README.md. --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 95450c2de..4b0d8ce61 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,8 @@ [English](./README-en.md) | 简体中文 文档捉虫活动火热进行中,欢迎参加: -[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) +
[点我查看活动详情](#https://docs-bug.openeuler.sh/) ### 介绍 -- Gitee From cec993bd0a0f6d93d000d05db75438dda7b3ccf1 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:12:45 +0000 Subject: [PATCH 022/130] update README.md. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 4b0d8ce61..7f0c1d1b1 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ [English](./README-en.md) | 简体中文 文档捉虫活动火热进行中,欢迎参加: -[点我马上开启文档捉虫](#https://docs.openeuler.org/zh/) -
-[点我查看活动详情](#https://docs-bug.openeuler.sh/) +[点我马上开启文档捉虫](https://docs.openeuler.org/zh/) +
+[点我查看活动详情](https://docs-bug.openeuler.sh/) ### 介绍 -- Gitee From 914f956cd51f5e28db690fa8e11717c040d50cd4 Mon Sep 17 00:00:00 2001 From: amyMaYun Date: Sat, 9 Apr 2022 10:13:06 +0000 Subject: [PATCH 023/130] update README.md. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f0c1d1b1..22a5c33d7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [English](./README-en.md) | 简体中文 -文档捉虫活动火热进行中,欢迎参加: +文档捉虫活动火热进行中,欢迎参加:
[点我马上开启文档捉虫](https://docs.openeuler.org/zh/)
[点我查看活动详情](https://docs-bug.openeuler.sh/) -- Gitee From f676f4b30675ff71fdc590ed3b71b1d8d14e980f Mon Sep 17 00:00:00 2001 From: hwyytw Date: Mon, 11 Apr 2022 10:04:30 +0800 Subject: [PATCH 024/130] =?UTF-8?q?=E5=90=8C=E6=AD=A522.03=E5=88=86?= =?UTF-8?q?=E6=94=AF=E5=86=85=E5=AE=B9=E5=88=B0master=E5=88=86=E6=94=AF=20?= =?UTF-8?q?=E5=90=8C=E6=AD=A522.03=E5=88=86=E6=94=AF=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...24\347\224\250\345\274\200\345\217\221.md" | 19 +++++--- ...21\350\241\214\350\257\264\346\230\216.md" | 8 ++-- ...05\344\270\216\350\277\220\350\241\214.md" | 45 ++++++++----------- ...\273\272\346\214\207\345\257\274.markdown" | 2 +- ...\273\272\346\214\207\345\257\274.markdown" | 11 +++-- ...63\351\224\256\347\211\271\346\200\247.md" | 2 +- ...73\347\273\237\345\256\211\350\243\205.md" | 1 + 7 files changed, 47 insertions(+), 41 deletions(-) diff --git "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" index 97be7a4c3..4fb31398f 100644 --- "a/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ "b/docs/zh/docs/Embedded/SDK\345\272\224\347\224\250\345\274\200\345\217\221.md" @@ -86,7 +86,7 @@ cmake .. make ``` -把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述使能共享文件系统场景。 +把编译好的hello程序拷贝到openEuler Embedded系统的/tmp/某个目录下(例如/tmp/myfiles/)。如何拷贝可以参考前文所述[使能共享文件系统场景](./安装与运行.html#使能共享文件系统场景)。 3. **运行用户态程序** @@ -101,7 +101,16 @@ cd /tmp/myfiles/ ### 使用SDK编译内核模块样例 -1. **准备代码** +1. **准备环境** + +在设置好SDK环境的基础之上,编译内核模块还需准备相应环境,但只需要准备一次即可。运行如下命令会创建相应的内核模块编译环境: + +``` +cd /sysroots/-openeuler-linux/usr/src/kernel +make module_prepare +``` + +2. **准备代码** 以编译一个内核模块为例,运行在openEuler Embedded内核中。 @@ -147,7 +156,7 @@ MODULE_LICENSE(GPL); `KERNEL_SRC_DIR` 为SDK中内核源码树的目录,该变量在安装SDK后会被自动设置。 -2. **编译生成内核模块** +3. **编译生成内核模块** 进入hello.c文件所在目录,使用工具链编译,命令如下: @@ -155,9 +164,9 @@ MODULE_LICENSE(GPL); 将编译好的hello.ko拷贝到openEuler Embedded系统的目录下。 -如何拷贝可以参考前文所述使能共享文件系统场景。 +如何拷贝可以参考前文所述[使能共享文件系统场景](./安装与运行.html#使能共享文件系统场景)。 -3. **插入内核模块** +4. **插入内核模块** 在openEuler Embedded系统中插入内核模块: diff --git "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" index 3fd5a5328..915644291 100644 --- "a/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" +++ "b/docs/zh/docs/Embedded/openEuler Embedded 22.03\345\217\221\350\241\214\350\257\264\346\230\216.md" @@ -12,19 +12,19 @@ openEuler Embedded 22.03是openEuler Embedded第一次正式发布,包含的 ## 软件包 -- 支持80+软件包,详见[openEuler Embedded所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) +- 支持80+软件包,详见[当前所支持的软件包](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html) ## 亮点特性 - 多OS混合部署框架的初步实现,支持openEuler Embedded和Zephyr的混合部署,详见[多OS混合部署框架](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html) - 分布式软总线的初步集成,详见[分布式软总线](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html) -- 安全加固指导,详见[openEuler Embedded的安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) -- 基于Preempt-RT的软实时,详见[openEuler Embedded软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) +- 安全加固指导,详见[安全加固说明](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html) +- 基于Preempt-RT的软实时,详见[软实时系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html) ## 南向生态 -- 新增树莓派4B支持,详见[openEuler Embedded树莓派系统介绍](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) +- 新增树莓派4B支持,详见[树莓派4B的支持](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html) ## 构建系统 diff --git "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" index c8d5dfe0a..e7cd05ef7 100644 --- "a/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" +++ "b/docs/zh/docs/Embedded/\345\256\211\350\243\205\344\270\216\350\277\220\350\241\214.md" @@ -17,8 +17,8 @@ 当前发布的已构建好的镜像,只支持arm和aarch64两种架构,且只支持qemu中ARM virt-4.0平台,您可以通过如下链接获得相应的镜像: -- [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm):32位arm架构,ARM Cortex A15处理器 -- [qemu_aarch64](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-aarch64):64位aarch64架构,ARM Cortex A57处理器 +- [qemu_arm](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm32/arm-std/):32位arm架构,ARM Cortex A15处理器 +- [qemu_aarch64](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm64/aarch64-std/):64位aarch64架构,ARM Cortex A57处理器 只要相应环境支持qemu仿真器(版本5.0以上),您可以将提供的openEuler Embedded镜像部署在物理裸机、云环境、容器或虚拟机上。 @@ -27,18 +27,16 @@ 所下载的镜像,由以下几部分组成: - 内核镜像**zImage**: 基于openEuler社区Linux 5.10代码构建得到。相应的内核配置可通过如下链接获取: - - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) + - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm/defconfig-kernel) + - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm64/defconfig-kernel),针对aarch64架构,额外增加了镜像自解压功能,可以参见相应的[patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch) -- 根文件系统镜像(依据具体需求,以下二选一) +- 根文件系统镜像 - - **initrd_tiny**:极简根文件系统镜像,只包含基本功能。包含 busybox 和基本的 glibc 库。该镜像功能简单,但内存消耗很小,适合探索 Linux内核相关功能。 - - - **initrd**:标准根文件系统镜像,在极简根文件系统镜像的基础上,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器软件包。该镜像适合进行更加丰富的功能探索。 + - **openeuler-image-qemu-xxx.cpio.gz**:标准根文件系统镜像,进行了必要安全加固,增加了audit、cracklib、OpenSSH、Linux PAM、shadow、iSula容器所支持的软件包。 - SDK(Software Development Kit)工具 - - **openeuler\*.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 + - **openeuler-glibc-x86_64-xxxxx.sh**:openEuler Embedded SDK自解压安装包,SDK包含了进行开发(用户态程序、内核模块等)所必需的工具、库和头文件等。 ## 运行镜像 @@ -48,16 +46,12 @@ **注意事项** -- 建议使用qemu 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在qemu中使能,则运行时可能会产生错误,此时可能需要从源码重新编译qemu。 +- 建议使用QEMU 5.0以上版本运行镜像,由于一些额外功能(网络、共享文件系统)需要依赖QEMU的virtio-net, virtio-fs等特性,如未在QEMU中使能,则运行时可能会产生错误,此时可能需要从源码重新编译QEMU。 - 运行镜像时,建议把内核镜像和根文件系统镜像放在同一目录下。 ->![](./public_sys-resources/icon-note.gif) **说明:** -> ->后续说明以标准根文件系统为例(initrd)。 - --- -qemu的下载与安装可以参考[qemu官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: +QEMU的下载与安装可以参考[QEMU官方网站](https://www.qemu.org/download/#linux) , 或者下载[源码](https://www.qemu.org/download/#source)单独编译安装。安装好后可以运行如下命令确认: ``` qemu-system-aarch64 --version @@ -65,9 +59,9 @@ qemu-system-aarch64 --version ### 极简运行场景 -该场景下,qemu未使能网络和共享文件系统,适合快速的功能体验。 +该场景下,QEMU未使能网络和共享文件系统,适合快速的功能体验。 -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -83,21 +77,20 @@ qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initr >![](./public_sys-resources/icon-note.gif) **说明:** > ->- 由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 ->- 当使用极简根文件系统镜像时,系统会自动登录, 无需输入用户名和密码。 +>由于标准根文件系统镜像进行了安全加固,因此第一次启动时,需要为登录用户名root设置密码,且密码强度有相应要求, 需要数字、字母、特殊字符组合最少8位,例如openEuler@2021。 2. **检查运行是否成功** -qemu运行成功并登录后,将会呈现openEuler Embedded的Shell。 +QEMU运行成功并登录后,将会呈现openEuler Embedded的Shell。 ### 使能共享文件系统场景 -通过共享文件系统,可以使得运行qemu仿真器的宿主机和openEuler Embedded共享文件,这样在宿主机上交叉编译的程序,拷贝到共享目录中,即可在openEuler Embedded上运行。 +通过共享文件系统,可以使得运行QEMU仿真器的宿主机和openEuler Embedded共享文件,这样在宿主机上交叉编译的程序,拷贝到共享目录中,即可在openEuler Embedded上运行。 假设将宿主机的/tmp目录作为共享目录,并事先在其中创建了名为hello_openeuler.txt的文件,使能共享文件系统功能的操作指导如下: -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -136,9 +129,9 @@ ls ### 使能网络场景 -通过qemu的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler embedded之间的网络通信。 +通过QEMU的virtio-net和宿主机上的虚拟网卡,可以实现宿主机和openEuler Embedded之间的网络通信。除了通过virtio-fs实现文件共享外,还可以通过网络的方式,例如 **scp** 命令,实现宿主机和 openEuler Embedded传输文件。 -1. **启动qemu** +1. **启动QEMU** 针对arm(ARM Cortex A15),运行如下命令: @@ -169,9 +162,9 @@ chmod a+x qemu-ifup 通过qemu-ifup脚本,宿主机上将创建名为tap0的虚拟网卡,地址为192.168.10.1。 -3. **配置openEuler embedded网卡** +3. **配置openEuler Embedded网卡** -openEuler Embedded登陆后,执行如下命令: +openEuler Embedded登录后,执行如下命令: ``` ifconfig eth0 192.168.10.2 diff --git "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 7b7fe2d22..7d08267df 100644 --- "a/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\256\271\345\231\250\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -145,7 +145,7 @@ bitbake openeuler-image | filename | description | | ---------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | +| Image-\* | openEuler Embedded image | | openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | | openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | | zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 1080d7193..2d29dcbed 100644 --- "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -57,10 +57,13 @@ yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过下方链接可以获得: + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持, 通过如下方式可以获得: - - [ARM 32位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) - - [ARM 64位工具链](https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + - 下载rpm包: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` + - 解压rpm包: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` + - 解压后可以看到当前路径下会有tmp目录,编译链存放于该目录下 + - ARM 32位工具链: openeuler_gcc_arm32le.tar.xz + - ARM 64位工具链: openeuler_gcc_arm64le.tar.xz ### 已安装好工具的构建容器 @@ -136,7 +139,7 @@ openEuler Embedded整个构建工程的文件布局如下,假设openeuler\_emb | filename | description | | ---------------------------------------------------------- | ----------------------------------- | -| Image-5.10.0 | openEuler Embedded image | +| Image-\* | openEuler Embedded image | | openeuler-glibc-x86\_64-openeuler-image-\*-toolchain-\*.sh | openEuler Embedded sdk toolchain | | openeuler-image-qemu-aarch64-\*.rootfs.cpio.gz | openEuler Embedded file system | | zImage | openEuler Embedded compressed image | \ No newline at end of file diff --git "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" index 4582e5abb..a2869c4bb 100644 --- "a/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" +++ "b/docs/zh/docs/Releasenotes/\345\205\263\351\224\256\347\211\271\346\200\247.md" @@ -70,7 +70,7 @@ eggo是openEuler云原生Sig组K8S集群部署管理项目,提供高效稳定 ## 嵌入式镜像 - **轻量化能力**,开放yocto小型化构建裁剪框架,支撑OS镜像轻量化定制,提供OS镜像 < 5M,以及<5S快速启动等能力。 - **多硬件支持**,新增支持树莓派4B作为嵌入式场景通用硬件。 -- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延<8us。 +- **软实时内核**,基于linux5.10内核提供软实时能力,软实时中断响应时延微秒级。 - **混合关键性部署**,实现soc内实时和非实时多平面混合部署,并支持zephyr实时内核。 - **分布式软总线基础能力**,集成鸿蒙的分布式软总线,实现欧拉嵌入式设备之间互联互通。 - **嵌入式软件包支持**,新增80+嵌入式领域常用软件包的构建。 diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index d013e5af0..8436fea53 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -109,6 +109,7 @@ openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03
+ **表 4** 嵌入式镜像列表 | 名称 | 描述 | -- Gitee From 8c359e75b4a61f67d1ef36d1fa30678478cda72e Mon Sep 17 00:00:00 2001 From: hwyytw Date: Mon, 11 Apr 2022 10:09:45 +0800 Subject: [PATCH 025/130] =?UTF-8?q?=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC=20=E5=8E=BB=E6=8E=89=E5=A4=9A=E4=BD=99?= =?UTF-8?q?=E7=A9=BA=E6=A0=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: hwyytw --- ...37\346\236\204\345\273\272\346\214\207\345\257\274.markdown" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index 2d29dcbed..d5d41a8bc 100644 --- "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -57,7 +57,7 @@ yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex Yocto可以构建出交叉编译所需的交叉工具链和C库,但整个流程复杂且耗时,不亚于内核乃至镜像的构建,而且除了第一次构建,后面很少会再涉及。同时,绝大部分开发者都不会直接与工具链和C库构建打交道。所以为了简化该流程,openEuler Embedded采取的策略是采用预编译的交叉工具链和库,会专门维护和发布相应的带有C库的工具链。 - 目前我们提供了对arm32位和aarch64位两种架构的工具链支持, 通过如下方式可以获得: + 目前我们提供了对arm32位和aarch64位两种架构的工具链支持,通过如下方式可以获得: - 下载rpm包: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` - 解压rpm包: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` -- Gitee From 17c9ae4dbff0d2dea8cfcbd3d30dca325cfba580 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Mon, 11 Apr 2022 14:20:10 +0800 Subject: [PATCH 026/130] =?UTF-8?q?imageTailor=20=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=8C=87=E5=8D=97=20=E7=AE=80=E4=BB=8B=E9=83=A8=E5=88=86?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=E6=8F=8F=E8=BF=B0=E9=9C=80=E8=A6=81?= =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...lor \344\275\277\347\224\250\346\214\207\345\215\227.md" | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" index 3902c6e0b..10cfe8d67 100644 --- "a/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/imageTailor \344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -36,9 +36,9 @@ 因此,openEuler 提供了 imageTailor 镜像裁剪定制工具。用户可以根据需求裁剪操作系统镜像中不需要的外围包,或者添加所需的业务包或文件。该工具主要提供了以下功能: -- 系统包裁剪:根据需要选择安装的 RPM 包列表,裁剪系统命令、库、驱动。 -- 系统配置修改:配置主机名、启动服务、时区/UTC、网络、分区、加载驱动、内核版本号。 -- 软件包增加:将用户的 RPM 包安装到系统中或者将用户文件添加到系统中。 +- 系统包裁剪定制:用户可以选择默认安装以及裁剪的rpm,也支持用户裁剪定制系统命令、库、驱动。 +- 系统配置定制:用户可以配置主机名、启动服务、时区、网络、分区、加载驱动、版本号等。 +- 用户文件定制:支持用户添加定制文件到系统镜像中。 -- Gitee From ea7ca9de179f93fcd366e1b46482bbdc6b005493 Mon Sep 17 00:00:00 2001 From: zhangsong Date: Tue, 12 Apr 2022 11:43:14 +0800 Subject: [PATCH 027/130] =?UTF-8?q?docs:=20=E6=B7=BB=E5=8A=A0rubik?= =?UTF-8?q?=E6=B7=B7=E9=83=A8=E9=9A=94=E7=A6=BB=E7=A4=BA=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangsong --- ...24\347\246\273\347\244\272\344\276\213.md" | 233 ++++++++++++++++++ docs/zh/menu/index.md | 1 + 2 files changed, 234 insertions(+) create mode 100644 "docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" diff --git "a/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" new file mode 100644 index 000000000..48895ccce --- /dev/null +++ "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" @@ -0,0 +1,233 @@ +## 混部隔离示例 + +### 环境准备 + +查看内核是否支持混部隔离功能 + +```bash +# 查看/boot/config-系统配置是否开启混部隔离功能 +# 若CONFIG_QOS_SCHED=y则说明使能了混部隔离功能,例如: +cat /boot/config-5.10.0-60.18.0.50.oe2203.x86_64 | grep CONFIG_QOS +CONFIG_QOS_SCHED=y +``` + +安装docker容器引擎 + +```bash +yum install -y docker-engine +docker version +# 如下为docker version显示结果 +Client: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Wed Mar 30 05:07:38 2022 + OS/Arch: linux/amd64 + Experimental: false + +Server: + Engine: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 (minimum version 1.12) + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Tue Mar 22 00:00:00 2022 + OS/Arch: linux/amd64 + Experimental: false +``` + +### 混部业务 + +**在线业务(clickhouse)** + +使用clickhouse-benmark测试工具进行性能测试,统计出QPS/P50/P90/P99等相关性能指标,用法参考:https://clickhouse.com/docs/zh/operations/utilities/clickhouse-benchmark/ + +**离线业务(stress)** + +stress是一个CPU密集型测试工具,可以通过指定--cpu参数启动多个并发CPU密集型任务给系统环境加压 + +### 使用说明 + +1)启动一个clickhouse容器(在线业务)。 + +2)进入容器内执行clickhouse-benchmark命令,设置并发线程数为10个、查询10000次、查询总时间30s。 + +3)同时启动一个stress容器(离线业务),并发执行10个CPU密集型任务对环境进行加压。 + +4)clickhouse-benchmark执行完后输出一个性能测试报告。 + +混部隔离测试脚本(**test_demo.sh**)如下: + +```bash +#!/bin/bash + +with_offline=${1:-no_offline} +enable_isolation=${2:-no_isolation} +stress_num=${3:-10} +concurrency=10 +timeout=30 +output=/tmp/result.json +online_container= +offline_container= + +exec_sql="echo \"SELECT * FROM system.numbers LIMIT 10000000 OFFSET 10000000\" | clickhouse-benchmark -i 10000 -c $concurrency -t $timeout" + +function prepare() +{ + echo "Launch clickhouse container." + online_container=$(docker run -itd \ + -v /tmp:/tmp:rw \ + --ulimit nofile=262144:262144 \ + -p 34424:34424 \ + yandex/clickhouse-server) + + sleep 3 + echo "Clickhouse container lauched." +} + +function clickhouse() +{ + echo "Start clickhouse benchmark test." + docker exec $online_container bash -c "$exec_sql --json $output" + echo "Clickhouse benchmark test done." +} + +function stress() +{ + echo "Launch stress container." + offline_container=$(docker run -itd joedval/stress --cpu $stress_num) + echo "Stress container launched." + + if [ $enable_isolation == "enable_isolation" ]; then + echo "Set stress container qos level to -1." + echo -1 > /sys/fs/cgroup/cpu/docker/$offline_container/cpu.qos_level + fi +} + +function benchmark() +{ + if [ $with_offline == "with_offline" ]; then + stress + sleep 3 + fi + clickhouse + echo "Remove test containers." + docker rm -f $online_container + docker rm -f $offline_container + echo "Finish benchmark test for clickhouse(online) and stress(offline) colocation." + echo "===============================clickhouse benchmark==================================================" + cat $output + echo "===============================clickhouse benchmark==================================================" +} + +prepare +benchmark +``` + +### 测试结果 + +单独执行clickhouse在线业务 + +```bash +sh test_demo.sh no_offline no_isolation +``` + +得到在线业务的QoS(QPS/P50/P90/P99等指标)**基线数据**如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8853412284364512, +...... +}, +"query_time_percentiles": { +...... +"50": 0.484905256, +"60": 0.519641313, +"70": 0.570876148, +"80": 0.632544937, +"90": 0.728295525, +"95": 0.808700418, +"99": 0.873945121, +...... +} +} +} +``` + +启用stress离线业务,未开启混部隔离功能下,执行test_demo.sh测试脚本 + +```bash +# with_offline参数表示启用stress离线业务 +# no_isolation参数表示未开启混部隔离功能 +sh test_demo.sh with_offline no_isolation +``` + +**未开启混部隔离的情况下**,clickhouse业务QoS数据(QPS/P80/P90/P99等指标)如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 0.9424028693636205, +...... +}, +"query_time_percentiles": { +...... +"50": 0.840476774, +"60": 1.304607373, +"70": 1.393591017, +"80": 1.41277543, +"90": 1.430316688, +"95": 1.457534764, +"99": 1.555646855, +...... +} +} +``` + +启用stress离线业务,开启混部隔离功能下,执行test_demo.sh测试脚本 + +```bash +# with_offline参数表示启用stress离线业务 +# enable_isolation参数表示开启混部隔离功能 +sh test_demo.sh with_offline enable_isolation +``` + +**开启混部隔离功能的情况下**,clickhouse业务QoS数据(QPS/P80/P90/P99等指标)如下: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8825798759270718, +...... +}, +"query_time_percentiles": { +...... +"50": 0.485725185, +"60": 0.512629901, +"70": 0.55656488, +"80": 0.636395956, +"90": 0.734695906, +"95": 0.804118275, +"99": 0.887807409, +...... +} +} +} +``` + +从上面的测试结果整理出一个表格如下: + +| 业务部署方式 | QPS | P50 | P90 | P99 | +| -------------------------------------- | ------------- | ------------- | ------------- | ------------- | +| 单独运行clickhouse在线业务(基线) | 1.885 | 0.485 | 0.728 | 0.874 | +| clickhouse+stress(未开启混部隔离功能) | 0.942(-50%) | 0.840(-42%) | 1.430(-49%) | 1.556(-44%) | +| clickhouse+stress(开启混部隔离功能) | 1.883(-0.11%) | 0.486(-0.21%) | 0.735(-0.96%) | 0.888(-1.58%) | + +在未开启混部隔离功能的情况下,在线业务clickhouse的QPS从1.9下降到0.9,同时业务的响应时延(P90)也从0.7s增大到1.4s,在线业务QoS下降了50%左右;而在开启混部隔离功能的情况下,不管是在线业务的QPS还是响应时延(P50/P90/P99)相比于基线值下降不到2%,在线业务QoS基本没有变化。 diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index cee7bf5e0..0ba65f344 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -213,6 +213,7 @@ headless: true - [云原生混合部署rubik用户指南]({{< relref "./docs/rubik/overview.md" >}}) - [安装与部署]({{< relref "./docs/rubik/安装与部署.md" >}}) - [http接口文档]({{< relref "./docs/rubik/http接口文档.md" >}}) + - [混部隔离示例]({{< relref "./docs/rubik/混部隔离示例.md" >}}) - [镜像裁剪定制工具使用指南]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut 使用指南]({{< relref "./docs/TailorCustom/isocut使用指南.md" >}}) - [imageTailor 使用指南]({{< relref "./docs/TailorCustom/imageTailor 使用指南.md" >}}) -- Gitee From b1f834c97157f4b0e3574b57077fc267289edecb Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Sat, 16 Apr 2022 17:49:41 +0800 Subject: [PATCH 028/130] added rubik docs and modified index.md --- .../public_sys-resources/hosttools.png | Bin 0 -> 210345 bytes ...-isolation-for-hybrid-deployed-services.md | 233 ++++++++++++++++++ docs/en/docs/rubik/http-apis.md | 67 +++++ .../docs/rubik/installation-and-deployment.md | 199 +++++++++++++++ docs/en/docs/rubik/overview.md | 17 ++ docs/en/menu/index.md | 4 + 6 files changed, 520 insertions(+) create mode 100644 docs/en/docs/Embedded/public_sys-resources/hosttools.png create mode 100644 docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md create mode 100644 docs/en/docs/rubik/http-apis.md create mode 100644 docs/en/docs/rubik/installation-and-deployment.md create mode 100644 docs/en/docs/rubik/overview.md diff --git a/docs/en/docs/Embedded/public_sys-resources/hosttools.png b/docs/en/docs/Embedded/public_sys-resources/hosttools.png new file mode 100644 index 0000000000000000000000000000000000000000..1b154b40fc76ead162cdd7c7d32303f581d9cfa8 GIT binary patch literal 210345 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%0DZr)O$%pOkgk_wGDUlaEp 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%0DJ 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®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 system configuration. +# If **CONFIG_QOS_SCHED=y**, the function is enabled. Example: +cat /boot/config-5.10.0-60.18.0.50.oe2203.x86_64 | grep CONFIG_QOS +CONFIG_QOS_SCHED=y +``` + +Install the Docker engine. + +```bash +yum install -y docker-engine +docker version +# The following shows the output of docker version. +Client: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Wed Mar 30 05:07:38 2022 + OS/Arch: linux/amd64 + Experimental: false + +Server: + Engine: + Version: 18.09.0 + EulerVersion: 18.09.0.300 + API version: 1.39 (minimum version 1.12) + Go version: go1.17.3 + Git commit: aa1eee8 + Built: Tue Mar 22 00:00:00 2022 + OS/Arch: linux/amd64 + Experimental: false +``` + +### Hybrid Deployed Services + +**Online Service ClickHouse** + +Use the clickhouse-benchmark tool to test the performance and collect statistics on performance metrics such as QPS, P50, P90, and P99. For details, see https://clickhouse.com/docs/en/operations/utilities/clickhouse-benchmark/. + +**Offline Service Stress** + +Stress is a CPU-intensive test tool. You can specify the **--cpu** parameter to start multiple concurrent CPU-intensive tasks to increase the stress on the system. + +### Usage + +1) Start a ClickHouse container (online service). + +2) Access the container and run the **clickhouse-benchmark** command. Set the number of concurrent threads to 10, the number of query times to 10000, and the total query time to 30s. + +3) Start a Stress container (offline service) at the same time and concurrently execute 10 CPU-intensive tasks to increase the stress on the environment. + +4) After the **clickhouse-benchmark** command is executed, a performance test report is generated. + +The **test_demo.sh** script for the isolation test for hybrid deployed services is as follows: + +```bash +#!/bin/bash + +with_offline=${1:-no_offline} +enable_isolation=${2:-no_isolation} +stress_num=${3:-10} +concurrency=10 +timeout=30 +output=/tmp/result.json +online_container= +offline_container= + +exec_sql="echo \"SELECT * FROM system.numbers LIMIT 10000000 OFFSET 10000000\" | clickhouse-benchmark -i 10000 -c $concurrency -t $timeout" + +function prepare() +{ + echo "Launch clickhouse container." + online_container=$(docker run -itd \ + -v /tmp:/tmp:rw \ + --ulimit nofile=262144:262144 \ + -p 34424:34424 \ + yandex/clickhouse-server) + + sleep 3 + echo "Clickhouse container lauched." +} + +function clickhouse() +{ + echo "Start clickhouse benchmark test." + docker exec $online_container bash -c "$exec_sql --json $output" + echo "Clickhouse benchmark test done." +} + +function stress() +{ + echo "Launch stress container." + offline_container=$(docker run -itd joedval/stress --cpu $stress_num) + echo "Stress container launched." + + if [ $enable_isolation == "enable_isolation" ]; then + echo "Set stress container qos level to -1." + echo -1 > /sys/fs/cgroup/cpu/docker/$offline_container/cpu.qos_level + fi +} + +function benchmark() +{ + if [ $with_offline == "with_offline" ]; then + stress + sleep 3 + fi + clickhouse + echo "Remove test containers." + docker rm -f $online_container + docker rm -f $offline_container + echo "Finish benchmark test for clickhouse(online) and stress(offline) colocation." + echo "===============================clickhouse benchmark==================================================" + cat $output + echo "===============================clickhouse benchmark==================================================" +} + +prepare +benchmark +``` + +### Test Results + +Independently execute the online service ClickHouse. + +```bash +sh test_demo.sh no_offline no_isolation +``` + +The QoS **baseline data** (QPS/P50/P90/P99) of the online service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8853412284364512, +...... +}, +"query_time_percentiles": { +...... +"50": 0.484905256, +"60": 0.519641313, +"70": 0.570876148, +"80": 0.632544937, +"90": 0.728295525, +"95": 0.808700418, +"99": 0.873945121, +...... +} +} +} +``` + +Start the offline service Stress, disable isolation of hybrid deployed services, and execute the **test_demo.sh** script. + +```bash +# **with_offline** indicates that the offline service Stress is enabled. +# **no_isolation** indicates that isolation of hybrid deployed services is disabled. +sh test_demo.sh with_offline no_isolation +``` + +**When isolation of hybrid deployed services is disabled**, the QoS data (QPS/P80/P90/P99) of the ClickHouse service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 0.9424028693636205, +...... +}, +"query_time_percentiles": { +...... +"50": 0.840476774, +"60": 1.304607373, +"70": 1.393591017, +"80": 1.41277543, +"90": 1.430316688, +"95": 1.457534764, +"99": 1.555646855, +...... +} +} +``` + +Start the offline service Stress, enable isolation of hybrid deployed services, and execute the **test_demo.sh** script. + +```bash +# **with_offline** indicates that the offline service Stress is enabled. +# **enable_isolation** indicates that isolation of hybrid deployed services is enabled. +sh test_demo.sh with_offline enable_isolation +``` + +**When isolation of hybrid deployed services is enabled**, the QoS data (QPS/P80/P90/P99) of the ClickHouse service is as follows: + +```json +{ +"localhost:9000": { +"statistics": { +"QPS": 1.8825798759270718, +...... +}, +"query_time_percentiles": { +...... +"50": 0.485725185, +"60": 0.512629901, +"70": 0.55656488, +"80": 0.636395956, +"90": 0.734695906, +"95": 0.804118275, +"99": 0.887807409, +...... +} +} +} +``` + +The following table lists the test results. + +| Service Deployment Mode | QPS | P50 | P90 | P99 | +| -------------------------------------- | ------------- | ------------- | ------------- | ------------- | +| ClickHouse (baseline) | 1.885 | 0.485 | 0.728 | 0.874 | +| ClickHouse + Stress (isolation disabled)| 0.942 (-50%) | 0.840 (-42%) | 1.430 (-49%) | 1.556 (-44%) | +| ClickHouse + Stress (isolation enabled) | 1.883 (-0.11%) | 0.486 (-0.21%) | 0.735 (-0.96%) | 0.888 (-1.58%) | + +When isolation of hybrid deployed services is disabled, the QPS of ClickHouse decreases from approximately 1.9 to 0.9, the service response delay (P90) increases from approximately 0.7s to 1.4s, and the QoS decreases by about 50%. When isolation of hybrid deployed services is enabled, the QPS and response delay (P50/P90/P99) of ClickHouse decrease by less than 2% compared with the baseline, and the QoS remains unchanged. diff --git a/docs/en/docs/rubik/http-apis.md b/docs/en/docs/rubik/http-apis.md new file mode 100644 index 000000000..e5d315a0a --- /dev/null +++ b/docs/en/docs/rubik/http-apis.md @@ -0,0 +1,67 @@ +# HTTP APIs + +## Overview + +The open APIs of Rubik are all HTTP APIs, including the API for setting or updating the pod priority, API for detecting the Rubik availability, and API for querying the Rubik version. + +## APIs + +### API for Setting or Updating the Pod Priority + +Rubik provides the function of setting or updating the pod priority. External systems can call this API to send pod information. Rubik sets the priority based on the received pod information to isolate resources. The API calling format is as follows: + +```bash +HTTP POST /run/rubik/rubik.sock +{ + "Pods": { + "podaaa": { + "CgroupPath": "kubepods/burstable/podaaa", + "QosLevel": 0 + }, + "podbbb": { + "CgroupPath": "kubepods/burstable/podbbb", + "QosLevel": -1 + } + } +} +``` + +In the **Pods** settings, specify information about the pods whose priorities need to be set or updated. At least one pod must be specified for each HTTP request, and **CgroupPath** and **QosLevel** must be specified for each pod. The meanings of **CgroupPath** and **QosLevel** are as follows: + +| Item | Value Type| Value Range| Description | +| ---------- | ---------- | ------------ | ------------------------------------------------------- | +| QosLevel | Integer | 0, -1 | pod priority. The value **0** indicates that the service is an online service, and the value **-1** indicates that the service is an offline service. | +| CgroupPath | String | Relative path | cgroup subpath of the pod (relative path in the cgroup subsystem)| + +The following is an example of calling the API: + +```sh +curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POST --data '{"Pods": {"podaaa": {"CgroupPath": "kubepods/burstable/podaaa","QosLevel": 0},"podbbb": {"CgroupPath": "kubepods/burstable/podbbb","QosLevel": -1}}}' --unix-socket /run/rubik/rubik.sock http://localhost/ +``` + +### API for Detecting Availability + +As an HTTP service, Rubik provides an API for detecting whether Rubik is running. + +API format: HTTP/GET /ping + +The following is an example of calling the API: + +```sh +curl -XGET --unix-socket /run/rubik/rubik.sock http://localhost/ping +``` + +If **ok** is returned, the Rubik service is running. + +### API for Querying Version Information + +Rubik allows you to query the current Rubik version number through an HTTP request. + +API format: HTTP/GET /version + +The following is an example of calling the API: + +```sh +curl -XGET --unix-socket /run/rubik/rubik.sock http://localhost/version +{"Version":"0.0.1","Release":"1","Commit":"29910e6","BuildTime":"2021-05-12"} +``` diff --git a/docs/en/docs/rubik/installation-and-deployment.md b/docs/en/docs/rubik/installation-and-deployment.md new file mode 100644 index 000000000..6a713ec22 --- /dev/null +++ b/docs/en/docs/rubik/installation-and-deployment.md @@ -0,0 +1,199 @@ +# Installation and Deployment + +## Overview + +This document describes how to install and deploy the Rubik component. + +## Software and Hardware Requirements + +### Hardware + +* Architectures: x86 and AArch64 +* Drive: 1 GB or more +* Memory: 100 MB or more + +### Software + +* OS: openEuler 22.03-LTS +* Kernel: openEuler 22.03-LTS kernel + +### Environment Preparation + +* Install the openEuler OS. For details, see the _openEuler 22.03-LTS Installation Guide_. +* Install and deploy Kubernetes. For details, see the _Kubernetes Cluster Deployment Guide_. +* Install the Docker or iSulad container engine. If the iSulad container engine is used, you need to install the isula-build container image building tool. + +## Installing Rubik + +Rubik is deployed on each Kubernetes node as a DaemonSet. Therefore, you need to perform the following steps to install the Rubik RPM package on each node. + +1. Configure the Yum repositories openEuler 22.03-LTS and openEuler 22.03-LTS:EPOL (Rubik component is available only in the EPOL repository). + + ``` + # openEuler 22.03-LTS officially released repository + name=openEuler22.03 + baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/everything/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=https://repo.openeuler.org/openEuler-22.03-LTS/everything/RPM-GPG-KEY-openEuler + ``` + + ``` + # openEuler 22.03-LTS:EPOL officially released repository + name=Epol + baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/$basearch/ + enabled=1 + gpgcheck=0 + ``` + +2. Install Rubik as the **root** user. + + ```shell + sudo yum install -y rubik + ``` + + +> ![](D:\Typora-image\icon-note.gif)**Note**: +> +> Files related to the Rubik tool are installed in the **/var/lib/rubik** directory. + +## Deploying Rubik + +Rubik runs as a container in a Kubernetes cluster in hybrid deployment scenarios. It is used to isolate and restrict resources for services with different priorities to prevent offline services from interfering with online services, improving the overall resource utilization and ensuring the service quality of online services. Currently, Rubik supports isolation and restriction of CPU and memory resources, which must be used together with the openEuler 22.03-LTS kernel. To enable the memory priority feature (that is, to implement memory resource tiering for services with different priorities), you need to set **/proc/sys/vm/memcg_qos_enable**. The value can be **0** or **1**. The default value **0** indicates that the feature is disabled, and the value **1** indicates that the feature is enabled. + +```bash +sudo echo 1 > /proc/sys/vm/memcg_qos_enable +``` + +### Deploying Rubik DaemonSet + +1. Use the Docker or isula-build engine to build Rubik images. Because Rubik is deployed as a DaemonSet, each node requires a Rubik image. After building an image on a node, use the `docker save/load` command to load the Rubik image to each node of Kubernetes. Alternatively, build a Rubik image on each node. The following uses isula-build as an example. The command is as follows: + +```sh +isula-build ctr-img build -f /var/lib/rubik/Dockerfile --tag rubik:0.1.0 . +``` + +2. On the Kubernetes master node, change the Rubik image name in the `/var/lib/rubik/rubik-daemonset.yaml` file to the name of the image built in the previous step. + +```yaml +... +containers: +- name: rubik-agent + image: rubik:0.1.0 # The image name must be the same as the Rubik image name built in the previous step. + imagePullPolicy: IfNotPresent +... +``` + +3. On the Kubernetes master node, run the `kubectl` command to deploy the Rubik DaemonSet. Rubik is automatically deployed on all Kubernetes nodes. + +```sh +kubectl apply -f /var/lib/rubik/rubik-daemonset.yaml +``` + +4. Run the `kubectl get pods -A` command to check whether Rubik has been deployed on each node in the cluster. (The number of rubik-agents is the same as the number of nodes and all rubik-agents are in the Running state.) + +```sh +[root@localhost rubik]# kubectl get pods -A +NAMESPACE NAME READY STATUS RESTARTS AGE +... +kube-system rubik-agent-76ft6 1/1 Running 0 4s +... +``` + +## Common Configuration Description + +The Rubik deployed using the preceding method is started with the default configuration. You can modify the Rubik configuration as required by modifying the **config.json** section in the **rubik-daemonset.yaml** file and then redeploy the Rubik DaemonSet. + +This section describes common configurations of **config.json**. + +### Configuration Item Description + +```yaml +# The configuration items are in the **config.json** section of the **rubik-daemonset.yaml** file. +{ + "autoConfig": true, + "autoCheck": false, + "logDriver": "stdio", + "logDir": "/var/log/rubik", + "logSize": 1024, + "logLevel": "info", + "cgroupRoot": "/sys/fs/cgroup" +} +``` + +| Item | Value Type| Value Range | Description | +| ---------- | ---------- | ------------------ | ------------------------------------------------------------ | +| autoConfig | Boolean | **true** or **false** | **true**: enables automatic pod awareness.
**false**: disables automatic pod awareness.| +| autoCheck | Boolean | **true** or **false** | **true**: enables pod priority check.
**false**: disables pod priority check.| +| logDriver | String | **stdio** or **file** | **stdio**: prints logs to the standard output. The scheduling platform collects and dumps logs.
**file**: prints files to the log directory specified by **logDir**.| +| logDir | String | Absolute path | Directory for storing logs. | +| logSize | Integer | [10,1048576] | Total size of logs, in MB. If the total size of logs reaches the upper limit, the earliest logs will be discarded.| +| logLevel | String | **error**, **info**, or **debug**| Log level. | +| cgroupRoot | String | Absolute path | cgroup mount point. | + +### Automatic Configuration of Pod Priorities + +If **autoConfig** is set to **true** in the Rubik configuration to enable automatic pod awareness, you only need to specify the priority in **annotation** in the YAML file when deploying the service pod. After the deployment, Rubik automatically detects the creation and update of the pods on the current node, and sets the pod priorities based on the configured priorities. + +### Pod Priority Configuration Depending on kubelet + +The automatic configuration of the pod priority depends on the event notification created by **api-server pod**, which has a certain delay. The pod priority cannot be configured before the process is started. As a result, the service performance may fluctuate. You can disable the automatic priority configuration option by modifying the kubelet source code. After the container cgroup is created and before the container process is started, call the Rubik HTTP API to configure the pod priorities. For details about how to use the HTTP API, see [HTTP APIs](./http-apis.md). + +### Automatic Verification of Pod Priorities + +Rubik supports consistency check on the pod QoS priority configurations of the current node during startup. It checks whether the configuration in the Kubernetes cluster is consistent with the pod priority configuration of Rubik. This function is disabled by default. You can enable or disable it using the **autoCheck** option. If this function is enabled, Rubik automatically verifies and corrects the pod priority configuration of the current node when it is started or restarted. + +## Example of Configuring Rubik for Offline Services + +After Rubik is successfully deployed, you can modify the YAML file of a service based on the following configuration example to specify the offline service. Then Rubik can configure the priority of the service after the service is deployed to isolate resources. + +The following is an example of deploying the online service Nginx: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx + namespace: qosexample + annotations: + volcano.sh/preemptable: "false" # If **volcano.sh/preemptable** is set to **true**, the service is an offline service. If it is set to **false**, the service is an online service. The default value is **false**. +spec: + containers: + - name: nginx + image: nginx + resources: + limits: + memory: "200Mi" + cpu: "1" + requests: + memory: "200Mi" + cpu: "1" +``` + +## Restrictions + +- The maximum number of concurrent HTTP requests that Rubik can receive is 1,000 QPS. If the number of concurrent HTTP requests exceeds the upper limit, an error is reported. + +- The maximum number of pods in a single request received by Rubik is 100. If the number of pods exceeds the threshold, an error is reported. + +- Only one Rubik can be deployed on each Kubernetes node. Multiple Rubiks may conflict with each other. + +- Rubik does not provide port access and can communicate only through sockets. + +- Rubik accepts only valid HTTP request paths and network protocols: http://localhost/ (POST), http://localhost/ping (GET), and http://localhost/version (GET). For details about the functions of HTTP requests, see HTTP APIs(./http-apis.md). + +- Rubik drive requirement: 1 GB or more. + +- Rubik memory requirement: 100 MB or more. + +- Services cannot be switched from a low priority (offline services) to a high priority (online services). For example, if service A is set to an offline service and then to an online service, Rubik reports an error. + +- When a container is mounted to a directory, the service side must ensure that the minimum permission on the Rubik local socket directory **/run/Rubik** is 700. + +- When the Rubik server is available, the timeout interval of a single request is 120s. If the Rubik process enters the T (suspended or tracing) or D (uninterruptible sleep) state, the server becomes unavailable. In this case, the Rubik service does not respond to any request. To avoid this problem, set the timeout interval on the client to avoid infinite waiting. + +- If hybrid deployment is used, the original **cgroup cpu share** function has the following restrictions: + + If both online and offline tasks are running on the CPU, the CPU share configuration of offline tasks cannot take effect. + + If the current CPU has only online or offline tasks, the CPU share configuration takes effect. diff --git a/docs/en/docs/rubik/overview.md b/docs/en/docs/rubik/overview.md new file mode 100644 index 000000000..bcf79fc62 --- /dev/null +++ b/docs/en/docs/rubik/overview.md @@ -0,0 +1,17 @@ +# Rubik User Guide + +## Overview + +Low server resource utilization has always been a recognized challenge in the industry. With the development of cloud native technologies, hybrid deployment of online (high-priority) and offline (low-priority) services becomes an effective means to improve resource utilization. + +In hybrid service deployment scenarios, Rubik container scheduling properly schedules resources based on QoS levels to greatly improve resource utilization while ensuring the quality of online services. + +Rubik supports the following features: + +- Pod CPU priority configuration +- Pod memory priority configuration + +This document is intended for community developers, open source enthusiasts, and partners who use the openEuler system and want to learn and use Rubik. Users must: + +* Know basic Linux operations. +* Be familiar with basic operations of Kubernetes and Docker/iSulad. diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 74ce94a24..ecdfd3f66 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -198,5 +198,9 @@ headless: true - [About KubeOS]({{< relref "./docs/KubeOS/about-kubeos.md" >}}) - [Installation and Deployment]({{< relref "./docs/KubeOS/installation-and-deployment.md" >}}) - [Usage Instructions]({{< relref "./docs/KubeOS/usage-instructions.md" >}}) +- [Rubik User Guide]({{< relref "./docs/rubik/overview.md" >}}) + - [Installation and Deployment]({{< relref "./docs/rubik/installation-and-deployment.md" >}}) + - [HTTP APIs]({{< relref "./docs/rubik/http-apis.md" >}}) + - [Example of Isolation for Hybrid Deployed Services]({{< relref "./docs/rubik/example-of-isolation-for-hybrid-deployed-services.md" >}}) - [Image Tailoring and Customization Tool]({{< relref "./docs/TailorCustom/overview.md" >}}) - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) \ No newline at end of file -- Gitee From 2a39fcda4c31e883bbf279d2751d39c7225739f4 Mon Sep 17 00:00:00 2001 From: gomico Date: Mon, 18 Apr 2022 15:05:19 +0800 Subject: [PATCH 029/130] =?UTF-8?q?update=20translation=20for=20some=20zh?= =?UTF-8?q?=20docs=20desktop/kubesphere.md=20at=20ab6f97b=20Embedded/SDK?= =?UTF-8?q?=E5=BA=94=E7=94=A8=E5=BC=80=E5=8F=91.md=20at=20f676f4b=20Embedd?= =?UTF-8?q?ed/=E5=AE=B9=E5=99=A8=E6=9E=84=E5=BB=BA=E6=8C=87=E5=AF=BC.markd?= =?UTF-8?q?own=20at=20f676f4b=20Embedded/embedded.md=20at=20d4a93eb=20Embe?= =?UTF-8?q?dded/=E5=AE=89=E8=A3=85=E4=B8=8E=E8=BF=90=E8=A1=8C.md=20at=20f6?= =?UTF-8?q?76f4b=20Embedded/openEuler=20Embedded=2022.03=E5=8F=91=E8=A1=8C?= =?UTF-8?q?=E8=AF=B4=E6=98=8E.md=20at=20f676f4b=20Embedded/openEuler=20Emb?= =?UTF-8?q?edded=E6=9E=84=E5=BB=BA=E6=8C=87=E5=AF=BC.markdown=20at=20625c9?= =?UTF-8?q?3d=20Embedded/=E5=BF=AB=E9=80=9F=E6=9E=84=E5=BB=BA=E6=8C=87?= =?UTF-8?q?=E5=AF=BC.markdown=20at=208c359e7=20Gazelle/Gazelle.md=20at=206?= =?UTF-8?q?d66100=20KubeEdge/KubeEdge=E9=83=A8=E7=BD=B2=E6=8C=87=E5=8D=97.?= =?UTF-8?q?md=20at=202c8ef7e=20NestOS/=E5=8A=9F=E8=83=BD=E7=89=B9=E6=80=A7?= =?UTF-8?q?=E6=8F=8F=E8=BF=B0.md=20at=202888031=20NestOS/=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E4=B8=8E=E9=83=A8=E7=BD=B2.md=20at=202888031=20NestOS?= =?UTF-8?q?/overview.md=20at=202888031=20NestOS/=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=B9=E6=B3=95.md=20at=202888031=20Releasenotes/=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E5=AE=89=E8=A3=85.md=20at=20f676f4b=20Releasenotes/?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E7=89=B9=E6=80=A7.md=20at=20f676f4b=20Tailor?= =?UTF-8?q?Custom/imageTailor=20=E4=BD=BF=E7=94=A8=E6=8C=87=E5=8D=97.md=20?= =?UTF-8?q?at=2017c9ae4=20thirdparty=5Fmigration/OpenStack-train.md=20at?= =?UTF-8?q?=205fe3a40=20thirdparty=5Fmigration/OpenStack-wallaby.md=20at?= =?UTF-8?q?=205fe3a40?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application-development-using-sdk.md | 172 + .../en/docs/Embedded/container-build-guide.md | 151 + docs/en/docs/Embedded/embedded.md | 186 +- .../docs/Embedded/installation-and-running.md | 166 + .../openEuler-Embedded-22.03-release-notes.md | 32 + .../openEuler-Embedded-build-guide.md | 7 + .../public_sys-resources/icon-caution.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-danger.gif | Bin 0 -> 580 bytes .../public_sys-resources/icon-note.gif | Bin 0 -> 394 bytes .../public_sys-resources/icon-notice.gif | Bin 0 -> 406 bytes .../public_sys-resources/icon-tip.gif | Bin 0 -> 253 bytes .../public_sys-resources/icon-warning.gif | Bin 0 -> 580 bytes docs/en/docs/Embedded/quick-build-guide.md | 146 + docs/en/docs/Gazelle/Gazelle.md | 263 ++ .../KubeEdge/kubeedge-deployment-guide.md | 6 +- docs/en/docs/NestOS/feature-description.md | 98 + .../NestOS/installation-and-deployment.md | 128 + docs/en/docs/NestOS/overview.md | 3 + docs/en/docs/NestOS/usage.md | 489 +++ .../en/docs/Releasenotes/installing-the-os.md | 21 +- docs/en/docs/Releasenotes/key-features.md | 26 +- .../docs/TailorCustom/figures/flowchart.png | Bin 0 -> 19918 bytes .../TailorCustom/imageTailor-user-guide.md | 928 ++++++ ...tion.md => virtualization-installation.md} | 0 docs/en/docs/desktop/kubesphere.md | 2 +- .../thirdparty_migration/OpenStack-train.md | 2961 +++++++++++++++++ .../OpenStack-victoria.md | 1832 ---------- .../thirdparty_migration/OpenStack-wallaby.md | 566 +++- docs/en/docs/userguide/patch-tracking.md | 2 +- docs/en/menu/index.md | 49 +- 30 files changed, 6160 insertions(+), 2074 deletions(-) create mode 100644 docs/en/docs/Embedded/application-development-using-sdk.md create mode 100644 docs/en/docs/Embedded/container-build-guide.md create mode 100644 docs/en/docs/Embedded/installation-and-running.md create mode 100644 docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md create mode 100644 docs/en/docs/Embedded/openEuler-Embedded-build-guide.md create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-caution.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-danger.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-note.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-notice.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-tip.gif create mode 100644 docs/en/docs/Embedded/public_sys-resources/icon-warning.gif create mode 100644 docs/en/docs/Embedded/quick-build-guide.md create mode 100644 docs/en/docs/Gazelle/Gazelle.md create mode 100644 docs/en/docs/NestOS/feature-description.md create mode 100644 docs/en/docs/NestOS/installation-and-deployment.md create mode 100644 docs/en/docs/NestOS/overview.md create mode 100644 docs/en/docs/NestOS/usage.md create mode 100644 docs/en/docs/TailorCustom/figures/flowchart.png create mode 100644 docs/en/docs/TailorCustom/imageTailor-user-guide.md rename docs/en/docs/Virtualization/{installation-to-virtualization.md => virtualization-installation.md} (100%) create mode 100644 docs/en/docs/thirdparty_migration/OpenStack-train.md delete mode 100644 docs/en/docs/thirdparty_migration/OpenStack-victoria.md diff --git a/docs/en/docs/Embedded/application-development-using-sdk.md b/docs/en/docs/Embedded/application-development-using-sdk.md new file mode 100644 index 000000000..c2ae831dc --- /dev/null +++ b/docs/en/docs/Embedded/application-development-using-sdk.md @@ -0,0 +1,172 @@ +# Application Development Using openEuler Embedded SDK + +In addition to the basic functions of openEuler Embedded, you can also develop applications, that is, running your own programs on openEuler Embedded. This chapter describes how to develop applications using openEuler Embedded SDK. + + +- [Application Development Using openEuler Embedded SDK](#application-development-using-openeuler-embedded-sdk) + - [Installing the SDK](#installing-the-sdk) + - [Using the SDK to Build a Hello World Example](#using-the-sdk-to-build-a-hello-world-example) + - [Using the SDK to Build a Kernel Module Example](#using-the-sdk-to-build-a-kernel-module-example) + + +### Installing the SDK + +1. **Run the self-extracting installation script of the SDK.** + +Run the following command: + +``` +sh openeuler-glibc-x86_64-openeuler-image-aarch64-qemu-aarch64-toolchain-22.03.sh +``` + +Enter the installation path of the toolchain as prompted. The default path is **/opt/openeuler/\/**. You can also set the path to a relative or absolute path. + +The following is an example: + +``` +sh ./openeuler-glibc-x86_64-openeuler-image-armv7a-qemu-arm-toolchain-22.03.sh`` +openEuler embedded(openEuler Embedded Reference Distro) SDK installer version 22.03 +================================================================ +Enter target directory for SDK (default: /opt/openeuler/22.03): sdk +You are about to install the SDK to "/usr1/openeuler/sdk". Proceed [Y/n]? y +Extracting SDK...............................................done +Setting it up...SDK has been successfully set up and is ready to be used. +Each time you wish to use the SDK in a new shell session, you need to source the environment setup script e.g. +$ . /usr1/openeuler/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +2. **Set the environment variable of the SDK.** + +Run the `source` command. The `source` command is displayed in the output of the previous step. Run the command. + +``` +. /usr1/openeuler/myfiles/sdk/environment-setup-armv7a-openeuler-linux-gnueabi +``` + +3. **Check whether the installation is successful.** + +Run the following command to check whether the installation and environment configuration are successful: + +``` +arm-openeuler-linux-gnueabi-gcc -v +``` + +### Using the SDK to Build a Hello World Example + +1. **Prepare the code.** + +The following describes how to build a hello world program that runs in the image of the openEuler Embedded root file system. + +Create a **hello.c** file. The source code is as follows: + +``` c +#include + +int main(void) +{ + printf("hello world\n"); +} +``` + +Compose a **CMakelist.txt** file as follows and place it in the same directory as the **hello.c** file. + +``` +project(hello C) + +add_executable(hello hello.c) +``` + +2. **Compile and generate a binary file.** + +Go to the directory where the **hello.c** file is stored and run the following commands to compile the file using the toolchain: + +``` +cmake .. +make +``` + +Copy the compiled **hello** program to a sub-directory of **/tmp/** (for example, **/tmp/myfiles/**) on openEuler Embedded. For details about how to copy the file, see [Shared File System Enabled Scenario](./installation-and-running.md#shared-file-system-enabled-scenario). + +3. **Run the user-mode program.** + +Run the **hello** program on openEuler Embedded. + +``` +cd /tmp/myfiles/ +./hello +``` + +If the running is successful, the message **hello world** is displayed. + +### Using the SDK to Build a Kernel Module Example + +1. **Prepare the environment.** + +After setting up the SDK, you need to prepare the environment for compiling the kernel module. Run the following commands to create the corresponding kernel module compilation environment: + +``` +cd /sysroots/-openeuler-linux/usr/src/kernel +make module_prepare +``` + +2. **Prepare the code.** + +The following describes how to build a kernel module that runs in the kernel of openEuler Embedded. + +Create a **hello.c** file. The source code is as follows: + +```c +#include +#include + +static int hello_init(void) +{ + printk("Hello, openEuler Embedded!\r\n"); + return 0; +} + +static void hello_exit(void) +{ + printk("Byebye!"); +} + +module_init(hello_init); +module_exit(hello_exit); + +MODULE_LICENSE(GPL); +``` + +Compose a Makefile as follows and place it in the same directory as the **hello.c** file. + +``` + KERNELDIR := ${KERNEL_SRC_DIR} + CURRENT_PATH := $(shell pwd) + + target := hello + obj-m := $(target).o + + build := kernel_modules + + kernel_modules: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules + clean: + $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean +``` + +`KERNEL_SRC_DIR` indicates the directory of the kernel source tree. This variable is automatically configured after the SDK is installed. + +3. **Compile and generate a kernel module.** + +Go to the directory where the **hello.c** file is stored and run the following command to compile the file using the toolchain: + + make + +Copy the compiled **hello.ko** file to a directory on openEuler Embedded. For details about how to copy the file, see the [Shared File System Enabled Scenario](./installation-and-running.md#shared-file-system-enabled-scenario). + +4. **Insert the kernel module.** + +Insert the kernel module to openEuler Embedded: + + insmod hello.ko + +If the running is successful, the message **Hello, openEuler Embedded!** is output to the kernel logs. \ No newline at end of file diff --git a/docs/en/docs/Embedded/container-build-guide.md b/docs/en/docs/Embedded/container-build-guide.md new file mode 100644 index 000000000..ee6e8e6af --- /dev/null +++ b/docs/en/docs/Embedded/container-build-guide.md @@ -0,0 +1,151 @@ +Container Build Guide +============================== + +The openEuler Embedded build process is based on the openEuler OS, and requires many system tools and build tools to be installed. To help developers quickly set up a build environment, the operating system and tools on which the build process depends are encapsulated into a container. In this way, developers can avoid the time-consuming environment preparation process and focus on development. + + + + - [Environment Preparation](#environment-preparation) + - [Installing Docker](#installing-docker) + - [Obtaining the Container Image](#obtaining-the-container-image) + - [Preparing the Container Build Environment](#preparing-the-container-build-environment) + - [Version Build](#version-build) + - [Downloading Source Code](#downloading-source-code) + - [Compiling the build](#compiling-the-build) + - [Build Result](#build-result) + + +## Environment Preparation + +Use Docker to create a container environment. The software and hardware requirements of Docker are as follows: + +- OS: Ubuntu, Debian, and RHEL (CentOS and Fedora) are recommended. +- Kernel: Linux 3.8 or later is recommended. +- Driver: The kernel must include a proper storage driver, for example, Device Mapper, AUFS, vfs, btrfs, or ZFS. +- Architecture: 64-bit architecture (x86-64 or AMD64). + +### Installing Docker + +------------- + +1. Check whether Docker has been installed in the current environment. + +Run the following command. If the Docker version is displayed, Docker has been installed in the current environment. You can use it directly. + +``` {.sourceCode .console} +docker version +``` + +1. If Docker is not installed, install it by referring to the [official document](http://docs.docker.com/engine/install/). + +Install Docker on openEuler by referring to the installation guide for CentOS. + +For example, run the following command to install Docker on openEuler: + +``` +sudo yum install docker +``` + +### Obtaining the Container Image + +--------------- + +Run the `docker pull` command to pull the image from Huawei Cloud to the host machine: + +``` +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +``` + +### Preparing the Container Build Environment + +------------------- + +#### 1. Start a container. + +Run the docker run command to start the container. To ensure that the container can run in the background and access the Internet after being started, you are advised to run the following command to start the container: + +``` +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +``` + +Parameter description: + +- -i: keeps the standard input open. +- -d: starts a container in daemon mode in the background. +- -t: allocates a pseudo-tty and binds it to the standard input of the container. +- \--network: connects the container to the network of the host machine. +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest (image_name:image_version) +- bash: method for accessing a container. + +#### 2. Check the ID of the started container. + +``` +docker ps +``` + +#### 3. Enter the container. + +``` +docker exec -it bash +``` + +After the build environment is ready, you can build in the container. + +## Version Build + +### Downloading Source Code + +1. Obtain the source code download script. + +``` +git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v /usr1/openeuler/src/yocto-meta-openeuler +``` + +2. Download the source code using the script. + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +sh download_code.sh /usr1/openeuler/src +``` + +### Compiling the build + +- Compilation architecture: aarch64-std, aarch64-pro, arm-std or raspberrypi4-64 +- Build directory: **/usr1/build** +- Source code directory: **/usr1/openeuler/src** +- Path of the compiler: **/usr1/openeuler/gcc/openeuler\_gcc\_arm64le** + +>![](./public_sys-resources/icon-note.gif) **NOTE** +>- Use different compilers for different compilation architectures. aarch64-std, aarch64-pro, and raspberrypi4-64 use the openeuler\_gcc\_arm64le compiler, and arm-std uses the openeuler\_gcc\_arm32le compiler. +>- The following uses the aarch64-std architecture as an example. + +1. Change the owner group of the **/usr1** directory to openeuler. Otherwise, permission issues may occur when switching to the **openeuler** user. + +``` +chown -R openeuler:users /usr1 +``` + +2. Switch to the **openeuler** user. + +``` +su openeuler +``` + +3. Go to the path where the compilation script is stored and run the script. + +``` +cd /usr1/openeuler/src/yocto-meta-openeuler/scripts +source compile.sh aarch64-std /usr1/build /usr1/openeuler/gcc/openeuler_gcc_arm64le +bitbake openeuler-image +``` + +### Build Result + +By default, the files are generated in the **output** directory of the build directory. For example, the built files of the aarch64-std example are generated in the **/usr1/build/output** directory, as shown in the following table: + +| Filename | Description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-\* | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded SDK toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | diff --git a/docs/en/docs/Embedded/embedded.md b/docs/en/docs/Embedded/embedded.md index b4aa274ed..5c0af0196 100644 --- a/docs/en/docs/Embedded/embedded.md +++ b/docs/en/docs/Embedded/embedded.md @@ -1,185 +1,5 @@ -# openEuler Embedded Usage Guide +# openEuler Embedded User Guide -openEuler Embedded is a Linux version for embedded scenarios based on the openEuler community version. The embedded system applications are restricted by multiple factors, such as resources, power consumption, and diversity. Therefore, the server-oriented Linux versions and the corresponding build systems can hardly satisfy the requirements of embedded scenarios. The [Yocto](https://www.yoctoproject.org/) is widely used to customize and build embedded Linux. Currently, openEuler Embedded is also built using Yocto, but has the same source code as other openEuler versions. For details about the build method, see the related code repository in [SIG-Yocto](https://gitee.com/openeuler/community/tree/master/sig/sig-Yocto). +openEuler Embedded is a Linux distribution for embedded scenarios based on the openEuler community version aiming to build a high-quality Linux-centric embedded software platform. openEuler Embedded will keep consistent with other openEuler versions in terms of kernel and software versions, with kernel configurations, software package combinations and configurations, and feature patches optimized for embedded scenarios. -This document describes how to obtain pre-built images, run the images, and develop basic embedded Linux applications based on the images. - -## Obtaining the Image -The released pre-built images support only the ARM and AArch64 architectures, and are compatible only with the ARM virt-4.0 platform of QEMU. You can obtain the images through the following links: - -- [qemu_arm](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-arm) for ARM Cortex A15 processor of 32-bit ARM architecture. -- [qemu_aarch64](https://repo.openeuler.org/openEuler-21.09/embedded_img/qemu-aarch64) for ARM Cortex A57 processor of 64-bit AArch64 architecture. - -You can deploy an openEuler Embedded image on a physical bare-metal server, cloud server, container, or VM as long as the environment supports QEMU emulator version 5.0 or later. - -## Image Content - -The downloaded image consists of the following parts: - -- Kernel image **zImage**, which is built based on Linux 5.10 of the openEuler community. You can obtain the kernel configurations through the following links: - - [arm(cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm/defconfig-kernel) - - [arm(cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/config/arm64/defconfig-kernel) for the AArch64 architecture. The image provides the image self-decompression function in addition. For details, see the corresponding [patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-21.09/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch). - -- Root file system image (select one of the following as required): - - **initrd_tiny**, which is the image of the simplified root file system with only basic functions. It contains the BusyBox and basic glibc library. The image is simple and consumes little memory. It is suitable for exploring Linux kernel functions. - - **initrd**, which is the image of the standard root file system. In addition to the content of the simplified root file system image, the standard image has received necessary security hardening and includes various software packages, such as audit, cracklib, OpenSSH, Linux PAM, shadow and iSula containers. This image is suitable for exploring more functions. - -## Executing the Image - -You can run the image to experience the functions of openEuler Embedded, and develop basic embedded Linux applications. - ---- -**_Note_** - -- You are advised to use QEMU 5.0 or later to run the image. Some additional functions (the network and shared file system) depend on the virtio-net and virtio-fs features of QEMU. If these features are not enabled in QEMU, errors may occur during image running. In this case, you may need to recompile QEMU from the source code. - -- When running the image, you are advised to place the kernel image and root file system image in the same directory. The following uses the standard root file system image (initrd) as an example. - ---- - - -### Simplified Running Scenario - -In this scenario, the network and shared file system are not enabled in QEMU. You can use this scenario to experience the functions. - -For ARM architecture (ARM Cortex A15), run the following command: -```shell -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```shell -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -``` - -The standard root file system image is securely hardened and requires you to set a password for the root user during the first startup. The password must contain at least eight characters, including digits, letters, and special characters, for example, openEuler@2021. For systems running the simplified root file system image, you can log in without the user name and password. - -After you successfully run QEMU and log in to the system, the Shell of openEuler Embedded is displayed. - -### Shared File System Enabled Scenario - -Shared file system allows the host machine of QEMU emulator to share files with openEuler Embedded. In this way, programs that are cross-compiled on the host machine can run on openEuler Embedded after being copied to the shared directory. - -Assume that the `/tmp` directory of the host machine is used as the shared directory, and a `hello_openeuler.txt` file is created in the directory in advance. To enable the shared file system function, perform the following steps: - -1. **Start QEMU.** - -For ARM architecture (ARM Cortex A15), run the following command: -```sh -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```sh -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp -``` - -2. **Mount the file system.** - -After you start and log in to openEuler Embedded, run the following commands to mount the shared file system: -```shell -cd /tmp -mkdir host -mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host -``` -The shared file system is mounted to the `/tmp/host` directory of openEuler Embedded. - -3. **Check whether the file system is shared successfully.** - -In openEuler Embedded, run the following commands: - -```shell -cd /tmp/host -ls -``` -If `hello_openeuler.txt` is discovered, the file system is shared successfully. - -### Network Enabled Scenario - -The virtio-net of QEMU and the virtual NIC of the host machine allow for the network communication between the host machine and openEuler Embedded. -1. **Start QEMU.** - -For ARM architecture (ARM Cortex A15), run the following command: -```shell -qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup -``` -For AArch64 architecture (ARM Cortex A57), run the following command: -```shell -qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup -``` -2. **Create the vNIC on the host machine.** - -You can use the `/etc/qemu-ifup` script to create a **tap0** vNIC on the host machine. **root** permission is required for running the script. The script details are as follows: - -```sh -#!/bin/bash -ifconfig $1 192.168.10.1 up -``` -Use the `qemu-ifup` script to create a **tap0** vNIC on the host machine. The IP address of the vNIC is 192.168.10.1. - -3. **Configure the NIC of openEuler Embedded.** - -Log in to openEuler Embedded and run the following command: -```shell -ifconfig eth0 192.168.10.2 -``` - -4. **Check whether the network connection is normal.** - -In openEuler Embedded, run the following command: -```shell -ping 192.168.10.1 -``` - -If the IP address can be pinged, the network connection between the host machine and openEuler Embedded is normal. - ---- -**_Note_** - -If you need openEuler Embedded to access the Internet through the host machine, create a bridge on the host machine. For details, see the related documents. - ---- - -## User-Mode Application Development Based on openEuler Embedded - -In addition to the basic functions of openEuler Embedded, you can also use the released images for the basic development of user-mode applications, that is, running your own programs on openEuler Embedded. - - -1. **Prepare the environment.** - -The current images are built using the Linaro ARM/AArch64 GCC 7.3.1 toolchains. It is recommended that the same toolchains are used for application development. You can obtain the toolchains from the following links: -- [linaro arm](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabi/gcc-linaro-7.3.1-2018.05-x86_64_arm-linux-gnueabi.tar.xz) -- [linrao arm sysroot](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/arm-linux-gnueabi/sysroot-glibc-linaro-2.25-2018.05-arm-linux-gnueabi.tar.xz) -- [linaro aarch64](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu.tar.xz) -- [linrao aarch64 sysroot](https://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/sysroot-glibc-linaro-2.25-2018.05-aarch64-linux-gnu.tar.xz) - -Download and decompress the required packages to a specified directory, for example, `/opt/openEuler_toolchain`. - -2. **Create and compile a user-mode program.** - -The following uses a `hello openEuler` program as an example to describe how to build a program that runs on the AArch64 standard root file system image. - -Create a `hello.c` file on the host machine. The source code is as follows: -```c -#include - -int main(void) -{ - printf("hello openEuler\r\n"); -} -``` - -On the host machine, run the following commands to compile using the corresponding toolchain: -```shell -export PATH=$PATH:/opt/openEuler_toolchain/gcc-linaro-7.3.1-2018.05-x86_64_aarch64-linux-gnu/bin -aarch64-linux-gnu-gcc --sysroot= hello.c -o hello -mv hello /temp -``` -Copy the cross-compiled hello program to the `/tmp` directory, and enable openEuler Embedded to access the directory on the host machine by referring to the description in **Shared File System Enabled Scenario**. - -3. **Run the user-mode program.** - -In openEuler Embedded, run the following commands to run the hello program: -```shell -cd /tmp/host -./hello -``` -If the program runs successfully, **hello openEuler** is displayed in the Shell of openEuler Embedded. +This document describes how to obtain pre-built images, run the images, develop basic embedded Linux applications based on the images, and build openEuler Embedded. diff --git a/docs/en/docs/Embedded/installation-and-running.md b/docs/en/docs/Embedded/installation-and-running.md new file mode 100644 index 000000000..7eeb26cd6 --- /dev/null +++ b/docs/en/docs/Embedded/installation-and-running.md @@ -0,0 +1,166 @@ +# Installation and Running + +This chapter describes how to obtain a pre-built image and how to run an image. + + + +- [Installation and Running](#installation-and-running) + - [Obtaining the Image](#obtaining-the-image) + - [Image Content](#image-content) + - [Running the Image](#running-the-image) + - [Simplified Running Scenario](#simplified-running-scenario) + - [Shared File System Enabled Scenario](#shared-file-system-enabled-scenario) + - [Network Enabled Scenario](#network-enabled-scenario) + + +## Obtaining the Image +The released pre-built images support only the ARM and AArch64 architectures, and are compatible only with the ARM virt-4.0 platform of QEMU. You can obtain the images through the following links: + +- [qemu_arm](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm32/arm-std/) for ARM Cortex A15 processor of 32-bit ARM architecture. +- [qemu_aarch64](https://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/arm64/aarch64-std/) for ARM Cortex A57 processor of 64-bit AArch64 architecture. + +You can deploy an openEuler Embedded image on a physical bare-metal server, cloud server, container, or VM as long as the environment supports QEMU emulator version 5.0 or later. + +## Image Content + +The downloaded image consists of the following parts: + +- Kernel image **zImage**, which is built based on Linux 5.10 of the openEuler community. You can obtain the kernel configurations through the following links: + - [ARM(Cortex a15)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm/defconfig-kernel) + - [ARM(Cortex a57)](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/config/arm64/defconfig-kernel) for the AArch64 architecture. The image provides the image self-decompression function in addition. For details, see the corresponding [patch](https://gitee.com/openeuler/yocto-embedded-tools/blob/openEuler-22.03-LTS/patches/arm64/0001-arm64-add-zImage-support-for-arm64.patch). + +- Root file system image: + - **openeuler-image-qemu-xxx.cpio.gz**, which is the image of the standard root file system. It has received necessary security hardening and includes various software packages, such as audit, cracklib, OpenSSH, Linux PAM, shadow and software packages supported by iSula. + +- Software Development Kit (SDK) + + - **openeuler-glibc-x86_64-xxxxx.sh**: The self-extracting installation package of openEuler Embedded SDK. The SDK contains tools, libraries, and header files for developing user mode applications and kernel modules. + +## Running the Image + +You can run the image to experience the functions of openEuler Embedded, and develop basic embedded Linux applications. + +--- +**Precautions** + +- You are advised to use QEMU 5.0 or later to run the image. Some additional functions (the network and shared file system) depend on the virtio-net and virtio-fs features of QEMU. If these features are not enabled in QEMU, errors may occur during image running. In this case, you may need to recompile QEMU from the source code. + +- When running the image, you are advised to place the kernel image and root file system image in the same directory. + +--- + +Download and install QEMU by referring to the [QEMU official website](https://www.qemu.org/download/#linux), or download and build from [source](https://www.qemu.org/download/#source). Use the following command to verify the installation: + +``` +qemu-system-aarch64 --version +``` + +### Simplified Running Scenario + +In this scenario, the network and shared file system are not enabled in QEMU. You can use this scenario to experience the functions. + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd +``` + +>![](./public_sys-resources/icon-note.gif) **Note:** +>The standard root file system image is securely hardened and requires you to set a password for the **root** user during the first startup. The password must contain at least eight characters, including digits, letters, and special characters, for example, **openEuler@2021**. + + +2. **Check whether QEMU is started successfully.** + +The shell of openEuler Embedded will be displayed after QEMU is successfully started and logged in. + +### Shared File System Enabled Scenario + +Shared file system allows the host machine of QEMU emulator to share files with openEuler Embedded. In this way, programs that are cross-compiled on the host machine can run on openEuler Embedded after being copied to the shared directory. + +Assume that the **/tmp** directory of the host machine is used as the shared directory, and a **hello_openeuler.txt** file is created in the directory in advance. To enable the shared file system function, perform the following steps: + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-9p-device,fsdev=fs1,mount_tag=host -fsdev local,security_model=passthrough,id=fs1,path=/tmp +``` + +2. **Mount the file system.** + +After you start and log in to openEuler Embedded, run the following commands to mount the shared file system: +``` +cd /tmp +mkdir host +mount -t 9p -o trans=virtio,version=9p2000.L host /tmp/host +``` +The shared file system is mounted to the **/tmp/host** directory of openEuler Embedded. + +3. **Check whether the file system is shared successfully.** + +In openEuler Embedded, run the following commands: + +``` +cd /tmp/host +ls +``` +If **hello_openeuler.txt** is discovered, the file system is shared successfully. + +### Network Enabled Scenario + +The virtio-net of QEMU and the virtual NIC of the host machine allow for the network communication between the host machine and openEuler Embedded. In addition to sharing files using virtio-fs, you can transfer files between the host machine and openEuler Embedded using the network, for example, the **scp** command. + +1. **Start QEMU.** + +For ARM architecture (ARM Cortex A15), run the following command: +``` +qemu-system-arm -M virt-4.0 -cpu cortex-a15 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup +``` +For AArch64 architecture (ARM Cortex A57), run the following command: +``` +qemu-system-aarch64 -M virt-4.0 -cpu cortex-a57 -nographic -kernel zImage -initrd initrd -device virtio-net-device,netdev=tap0 -netdev tap,id=tap0,script=/etc/qemu-ifup +``` +2. **Create a vNIC on the host machine.** + +You can create a **/qemu-ifup** script in the **/etc** directory and run the script to create a **tap0** vNIC on the host machine. The script details are as follows: + +``` +#!/bin/bash +ifconfig $1 192.168.10.1 up +``` +**root** permissions are required for running the script. + +``` +chmod a+x qemu-ifup +``` + +Use the **qemu-ifup** script to create a **tap0** vNIC on the host machine. The IP address of the vNIC is **192.168.10.1**. + +3. **Configure the NIC of openEuler Embedded.** + +Log in to openEuler Embedded and run the following command: +``` +ifconfig eth0 192.168.10.2 +``` + +4. **Check whether the network connection is normal.** + +In openEuler Embedded, run the following command: +``` +ping 192.168.10.1 +``` + +If the IP address can be pinged, the network connection between the host machine and openEuler Embedded is normal. + +--- +>![](./public_sys-resources/icon-note.gif) **Note:** + >If you need openEuler Embedded to access the Internet through the host machine, create a bridge on the host machine. For details, see the related documents. diff --git a/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md b/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md new file mode 100644 index 000000000..3c4d340c1 --- /dev/null +++ b/docs/en/docs/Embedded/openEuler-Embedded-22.03-release-notes.md @@ -0,0 +1,32 @@ +# openEuler Embedded 22.03 Release Notes + +openEuler Embedded 22.03 is the first official release of openEuler Embedded. This section describes the main features of this version. + +## Kernel + +- The kernel is upgraded to 5.10.0-60.17.0. + +- The kernel supports Preempt-RT patches. + +- The kernel supports Raspberry Pi 4B patches. + +## Software Packages + +- More than 80 software packages are supported. For details, see [Supported Software Packages](https://openeuler.gitee.io/yocto-meta-openeuler/features/software_package_description.html). + +## Feature Highlights + +- The multi-OS hybrid deployment framework supports hybrid deployment of openEuler Embedded and Zephyr. For details, see [Multi-OS Hybrid Deployment Framework](https://openeuler.gitee.io/yocto-meta-openeuler/features/mcs.html). +- The distributed soft bus is preliminarily integrated. For details, see [Distributed Soft Bus](https://openeuler.gitee.io/yocto-meta-openeuler/features/distributed_soft_bus.html). + +- For details about security hardening, see [Security Hardening Description](https://openeuler.gitee.io/yocto-meta-openeuler/security_hardening/index.html). +- Preempt-RT-based soft real-time. For details, see [Soft Real-Time System Introduction](https://openeuler.gitee.io/yocto-meta-openeuler/features/preempt_rt.html). + +## Southbound Ecosystem + +- Added support for Raspberry Pi 4B. For details, see [Support for Raspberry Pi 4B](https://openeuler.gitee.io/yocto-meta-openeuler/features/raspberrypi.html). + +## Build System + +- openEuler Embedded build system is preliminarily implemented. For details, see [Quick Build Guide](./quick-build-guide.md). +- Containerized build. For details, see [Container Build Guide](./container-build-guide.md). diff --git a/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md b/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md new file mode 100644 index 000000000..5c8f74c6d --- /dev/null +++ b/docs/en/docs/Embedded/openEuler-Embedded-build-guide.md @@ -0,0 +1,7 @@ +openEuler Embedded Build Guide +===================== + +This document provides two methods for preparing a building environment and describes the building process in details. Choose one of the methods as required. + +- To build openEuler Embedded, see [Quick Build Guide](./quick-build-guide.md) +- For containerized build, see [Container Build Guide](./container-build-guide.md) \ No newline at end of file diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-caution.gif b/docs/en/docs/Embedded/public_sys-resources/icon-caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-danger.gif b/docs/en/docs/Embedded/public_sys-resources/icon-danger.gif new file mode 100644 index 0000000000000000000000000000000000000000..6e90d7cfc2193e39e10bb58c38d01a23f045d571 GIT binary patch literal 580 zcmV-K0=xZ3Nk%w1VIu$?0Hp~4{QBgqmQ+MG9K51r{QB&)np^||1PlfQ%(86!{`~yv zv{XhUWKt}AZaiE{EOcHp{O-j3`t;<+eEiycJT4p@77X;(jQsMfB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-note.gif b/docs/en/docs/Embedded/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/public_sys-resources/icon-notice.gif b/docs/en/docs/Embedded/public_sys-resources/icon-notice.gif new file mode 100644 index 0000000000000000000000000000000000000000..86024f61b691400bea99e5b1f506d9d9aef36e27 GIT binary patch literal 406 zcmV;H0crk6Nk%w1VIu$@0J8u9|NsB@_xJDb@8;&_*4Ea}&d#;9wWXz{jEszHYim+c zQaU<1At50E0000000000A^8Le000gEEC2ui03!e%000R7038S%NU)&51O^i-Tu6`s z0)`MFE@;3YqD6xSC^kTNu_J>91{PH8XfZ(p1pp2-SU@u3#{mEUC}_}tg3+I#{z}{Ok@D_ZUDg- zt0stin4;pC8M{WLSlRH*1pzqEw1}3oOskyNN?j;7HD{BBZ*OEcv4HK!6Bk6beR+04 z&8}k>SkTusVTDmkyOz#5fCA$JTPGJVQvr3uZ?QzzPQFvD0rGf_PdrcF`pMs}p^BcF zKtKTd`0wipR%nKN&Wj+V}pX;WC3SdJV!a_8Qi zE7z`U*|Y^H0^}fB$R?oG%6hQ z+MMLZbQBH@)Vg&1^3?qHb(5!%>3r0+`eq=&V&E}0Dypi0000000000 z00000A^8LW000R9EC2ui03!e$000L5z=Uu}ED8YtqjJd<+B}(9bIOb$3-31_h|V>=0A{ z1Hh0#H30>fNT})^fRU_83uewx9oRr{f{Sx1Ml`t)EQ zGkHZ67&~y{W5Jpq4H_WfuLxp*3<7O}GEl;1ESe36fLNs=B0&LQM1Buf(R)qg(BRd`t1OPjI1m_q4 literal 0 HcmV?d00001 diff --git a/docs/en/docs/Embedded/quick-build-guide.md b/docs/en/docs/Embedded/quick-build-guide.md new file mode 100644 index 000000000..0f9625d64 --- /dev/null +++ b/docs/en/docs/Embedded/quick-build-guide.md @@ -0,0 +1,146 @@ +Quick Build Guide +===================== + +This chapter describes how to build openEuler Embedded. + + + - [Environment Preparation](#environment-preparation) + - [Using Host Machine Commands in Yocto](#using-host-machine-commands-in-yocto) + - [Tools Required for Building openEuler Embedded](#tools-required-for-building-openeuler-embedded) + - [Build Container with Tools Installed](#build-container-with-tools-installed) + - [Version Build](#version-build) + - [Downloading Build Code](#downloading-build-code) + - [Compiling the Build](#compiling-the-build) + - [Build Result](#build-result) + + +Environment Preparation +-------------- + +### Using Host Machine Commands in Yocto + +Yocto, or BitBake, is a group of Python programs. The minimum environment requirements are as follows: + +- Python3 \> 3.6.0 +- Git \> 1.8.3.1 +- Tar \> 1.28 + +Yocto can build other tools required in the build process based on the corresponding software package recipes so that Yocto is self-contained. During this process, Yocto installs dedicated Yocto patches for corresponding tools (such as DNF and RPM) as required. These host tools are built from the source code in the first build. Therefore, the first build of Yocto can be time-consuming. + +To accelerate the building process, especially for the first build, openEuler Embedded preferentially uses the pre-built native tools on the host. This requires that the software package management tools (such as APT, DNF, Yum, and Zypper) be installed in advance. + +Yocto uses the **HOSTTOOLS** variable to introduce host tools and creates a soft link for each tool listed in **HOSTTOOLS**. To prevent host contamination, Yocto prepares an environment that is independent from the host, for example, the **PATH** variable. Therefore, if a command that depends on the host is added, the command must be added to **HOSTTOOLS**. Otherwise, even if the command exists on the host, an error message will be displayed during Yocto building, indicating that the corresponding tool cannot be found. The following figure shows the process. + +![](./public_sys-resources/hosttools.png) + +The host tools required by openEuler Embedded are defined in **HOSTTOOLS** in the **local.conf.sample** file by default. The tools include: + +| Tool| Description | +| ------ | ------------- | +| cmake | CMake build tool| +| ninjia | Ninja build system| + +### Tools Required for Building openEuler Embedded + +- Operating system. + + [openEuler-20.03-LTS-SP2](https://repo.openeuler.org/openEuler-20.03-LTS-SP2/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +- Additional tools. + +``` +yum -y install tar cmake gperf sqlite-devel chrpath gcc-c++ patch rpm-build flex autoconf automake m4 bison bc libtool gettext-devel createrepo\_c rpcgen texinfo hostname python meson dosfstools mtools parted ninja-build autoconf-archive libmpc-devel gmp-devel +``` + +- Pre-built cross-compilation toolchain and library. + + Yocto can build the cross-compilation toolchains and C libraries required for cross-compilation. However, the process is complex and time-consuming and is performed only in the first build. At the same time, most developers do not build toolchains and C libraries themselves. To simplify the process, openEuler Embedded uses pre-built cross-compilation toolchains and libraries maintained by the openEuler community. + + Currently, the toolchains for the ARM32 and AArch64 architectures are provided. You can download the toolchains by performing the following methods: + + - [ARM32 Toolchain] (https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003463/download/openeuler_gcc_arm32le.tar.xz) + - [AArch64 Toolchain] (https://gitee.com/openeuler/yocto-embedded-tools/attach_files/1003462/download/openeuler_gcc_arm64le.tar.xz) + - Download the RPM package: `wget https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/x86_64/Packages/gcc-cross-1.0-0.oe2203.x86_64.rpm` + - Decompress the RPM package: `rpm2cpio gcc-cross-1.0-0.oe2203.x86_64.rpm | cpio -id` + - After the decompression, a **/tmp** directory containing the toolchain is generated in the current directory. + - Toolchain for the ARM 32-bit architecture: openeuler_gcc_arm32le.tar.xz + - Toolchain for the ARM 64-bit architecture: openeuler_gcc_arm64le.tar.xz + +### Build Container with Tools Installed + +A large number of host tools are used during the build of openEuler Embedded. To accelerate the build process, openEuler Embedded uses the tools installed on the host in advance. However, the tool versions vary depending on the host environment. For example, CMake 1.9 or later is required for the build, but the version on the host is CMake 1.8. To solve this problem, openEuler Embedded provides a dedicated build container to provide a unified build environment. + +You can obtain the container images for the build from the following link: + +​ [Basic Build Container Image for openEuler Embedded](https://repo.openeuler.org/openEuler-21.03/docker_img/x86_64/openEuler-docker.x86_64.tar.xz) + +For details, see the [Container Build Guide](./container-build-guide.html). + +## Version Build + +### Downloading Build Code + +The file layout of the openEuler Embedded build project is as follows. Assume that **openeuler\_embedded** is the top-level directory. + +> +>├── src Source code directory, including all software package code, kernel code, and Yocto build code +>├── build openEuler Embedded build directory. The generated images are stored in this directory. + +1. Obtain the source code download script. + + Download the script to a specified directory, for example, **src/yocto-meta-openeuler**. + + ``` + git clone https://gitee.com/openeuler/yocto-meta-openeuler.git -b openEuler-22.03-LTS -v src/yocto-meta-openeuler + ``` + + The script **src/yocto-meta-openeuler/scripts/download\_code.sh** has the following parameters: + + - 1. Path to download the source code. By default, the source code is downloaded relative to the script location. For example, in the preceding example, the code repository is downloaded to the **src/** directory. + - 2. Branch to be downloaded. See the script for the default value. Determine the branch based on the version. + - 3. XML file for downloading the code, which is in the standard manifest format. The code is downloaded based on the XML configurations. + +2. Download the source code using the script. + + - To download the latest code: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh + ``` + + - To download the code of a specified version: + + ``` + sh src/yocto-meta-openeuler/scripts/download_code.sh "" "" "manifest.xml" + ``` + + Obtain the **manifest.xml** file for specifying the version of the openEuler Embedded code from the openEuler Embedded release directory **embedded\_img/source-list/**. + +### Compiling the Build + +Run the one-click compilation script **src/yocto-meta-openeuler/scripts/compile.sh**. For details, see the script content. + +The process of the compilation script is as follows: + +1. Adds the paths of the additional tools to **PATH**. +2. Sets the **TEMPLATECONF** variable to include the paths of configuration files such as **local.conf.sample**. +3. Invokes `oe-init-build-env` of the Poky repository to perform initial configuration. +4. Sets the **MACHINE** variable in the **conf/local.conf** file in the compilation directory to add layers as required. +5. Runs the `bitbake openeuler-image` command in the compilation directory to build the image and SDK of openEuler Embedded. +6. The files are generated in the **output** directory of the compilation directory. + +Run the compilation script. The following uses the standard ARM architecture as an example to describe the compilation method: + + source src/yocto-meta-openeuler/scripts/compile.sh arm-std + bitbake openeuler-image # You will be prompted to run the bitbake command after the source command is executed + +### Build Result + +By default, the files are generated in the **output** directory of the build directory. For example, the built files of the ARM example are generated in the **/usr1/build/output** directory, as shown in the following table: + +| filename | description | +| --------------------------------------------------------- | ----------------------------------- | +| Image-\* | openEuler Embedded image | +| openeuler-glibc-x86\_64-openeuler-image-*-toolchain-**.sh | openEuler Embedded sdk toolchain | +| openeuler-image-qemu-aarch64-*.rootfs.cpio.gz | openEuler Embedded file system | +| zImage | openEuler Embedded compressed image | diff --git a/docs/en/docs/Gazelle/Gazelle.md b/docs/en/docs/Gazelle/Gazelle.md new file mode 100644 index 000000000..380a8876b --- /dev/null +++ b/docs/en/docs/Gazelle/Gazelle.md @@ -0,0 +1,263 @@ +# Gazelle User Guide + +## Introduction + +Gazelle is a high-performance user-mode protocol stack. It directly reads and writes NIC packets in user mode based on DPDK and transmit the packets through shared hugepage memory, and uses the LwIP protocol stack. Gazelle greatly improves the network I/O throughput of applications and accelerates the network for the databases, such as MySQL and Redis. +- High Performance +Zero-copy and lock-free packets that can be flexibly scaled out and scheduled adaptively. +- Universality +Compatible with POSIX without modification, and applicable to different types of applications. + +In the single-process scenario where the NIC supports multiple queues, **liblstack.so** is used to shorten the packet path. In other scenarios, the ltran process is used to distribute packets to each thread. + +## Installation +Configure the Yum source of openEuler and run the`yum` command to install Gazelle. +```sh +#dpdk >= 21.11-2 +yum install dpdk +yum install libconfig +yum install numactl +yum install libboundscheck +yum install libpcap +yum install gazelle +``` + +## Usage +To configure the running environment and use Gazelle to accelerate applications, perform the following steps: +### 1. Installing the .ko File as the **root** User +Install the .ko files based on the site requirements to enable the virtual network ports and bind NICs to the user-mode driver. +To enable the virtual network port function, use **rte_kni.ko**. +``` sh +modprobe rte_kni carrier="on" +``` +Bind the NIC from the kernel driver to the user-mode driver. Choose one of the following .ko files based on the site requirements. +``` sh +#If the IOMMU is available +modprobe vfio-pci + +#If the IOMMU is not available and the VFIO supports the no-IOMMU mode +modprobe vfio enable_unsafe_noiommu_mode=1 +modprobe vfio-pci + +#Other cases +modprobe igb_uio +``` + + +### 2. Binding the NIC Using DPDK +Bind the NIC to the driver selected in Step 1 to provide an interface for the user-mode NIC driver to access the NIC resources. +``` sh +# Using vfio-pci +dpdk-devbind -b vfio-pci enp3s0 + +# Using igb_uio +dpdk-devbind -b igb_uio enp3s0 +``` + +### 3. Configuring Memory Huge Pages +Gazelle uses hugepage memory to improve efficiency. You can configure any size for the memory huge pages reserved by the system using the **root** permissions. Each memory huge page requires a file descriptor. If the memory is large, you are advised to use 1 GB huge pages to avoid occupying too many file descriptors. +Select a page size based on the site requirements and configure sufficient memory huge pages. Run the following commands to configure huge pages: +``` sh +# Configuring 1024 2 MB huge pages on node0. Total memory is 2 GB. +echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages + +# Configuring 5 1 GB huge pages on node0. Total memory is 5 GB. +echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages + +# Viewing configuration results. +grep Huge /proc/meminfo +``` + +### 4. Mounting Memory Huge Pages +Create two directories for the lstack and ltran processes to access the memory huge pages. Run the following commands: +``` sh +mkdir -p /mnt/hugepages +mkdir -p /mnt/hugepages-2M +chmod -R 700 /mnt/hugepages +chmod -R 700 /mnt/hugepages-2M +mount -t hugetlbfs nodev /mnt/hugepages +mount -t hugetlbfs nodev /mnt/hugepages-2M +``` + +### 5. Enabling Gazelle for an Application +Enable Gazelle for an application using either of the following methods as required. +- Recompiling the application to link the Gazelle library. +Modify the makefile of the application to link to **liblstack.so**. The following is an example: +``` +# Add the Makefile of Gazelle to the application makefile. +-include /etc/gazelle/lstack.Makefile + +# Add the LSTACK_LIBS variable when compiling the source code. +gcc test.c -o test ${LSTACK_LIBS} +``` + +- Using the **LD_PRELOAD** environment variable to load the Gazelle library. +Use the **GAZELLE_BIND_PROCNAME** environment variable to specify the process name, and **LD_PRELOAD** to specify the Gazelle library path. +``` +GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test +``` + +### 6. Configuring Gazelle +- The **lstack.conf** file is used to specify the startup parameters of lstack. The default path is **/etc/gazelle/lstack.conf**. The parameters in the configuration file are as follows: + +|Parameter|Value|Description| +|:---|:---|:---| +|dpdk_args|--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-type (mandatory)
--legacy-mem
--map-perfect
|DPDK initialization parameter. For details, see the DPDK description.| +|use_ltran| 0/1 | Whether to use ltran.| +|num_cpus|"0,2,4 ..."|IDs of the CPUs bound to the lstack threads. The number of IDs is the number of lstack threads (less than or equal to the number of NIC queues). You can select CPUs by NUMA nodes.| +|num_wakeup|"1,3,5 ..."|IDs of the CPUs bound to the wakeup threads. The number of IDs is the number of wakeup threads, which is the same as the number of lstack threads. Select CPUs of the same NUMA nodes of the num_cpus parameter respectively. If this parameter is not set, the wakeup thread is not used.| +|low_power_mode|0/1|Whether to enable the low-power mode. This parameter is not supported currently.| +|kni_swith|0/1|Whether to enable the rte_kni module. The default value is 0. This module can be enabled only when ltran is not used.| +|host_addr|"192.168.xx.xx"|IP address of the protocol stack, which must be consistent with the **bind** field in the redis-server configuration file.| +|mask_addr|"255.255.xx.xx"|Subnet mask.| +|gateway_addr|"192.168.xx.1"|Gateway IP address.| +|devices|"aa:bb:cc:dd:ee:ff"|MAC address for NIC communication. The value must be the same as that of **bond_macs** in the **ltran.conf** file.| + + +**lstack.conf** example: +``` conf +dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-2M", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] + +use_ltran=1 +kni_switch=0 + +low_power_mode=0 + +num_cpus="2,22" +num_wakeup="3,23" + +host_addr="192.168.1.10" +mask_addr="255.255.255.0" +gateway_addr="192.168.1.1" +devices="aa:bb:cc:dd:ee:ff" +``` + +- The **ltran.conf** file is used to specify ltran startup parameters. The default path is **/etc/gazelle/ltran.conf**. To enable ltran, set **use_ltran=1** in the **lstack.conf** file. The configuration parameters are as follows: + +|**Function**|Parameter|Value|Description| +|:---|:---|:---|:---| +|kit|forward_kit|"dpdk"|Specifies the transceiver module of an NIC.
This field is reserved and is not used currently.| +||forward_kit_args|-l
--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-TYPE (mandatory)
--legacy-mem (mandatory)
--map-perfect (mandatory)
|DPDK initialization parameter. For details, see the DPDK description.
Note: **--map-perfect** is an extended feature. It is used to prevent the DPDK from occupying excessive address space and ensure that extra address space is available for lstack.| +|kni|kni_switch|0/1|Whether to enable the rte_kni module. The default value is 0.| +|dispatcher|dispatch_max_clients|n|Maximum number of clients supported by ltran.
1. In the multi-process single-thread scenario, the number of lstack instances cannot exceed 32. Each lstack instance has one network thread.
2. In the single-process multi-thread scenario, one lstack instance is supported. The number of network threads of the lstack instance cannot exceed 32.| +||dispatch_subnet|192.168.xx.xx|Subnet mask, which is the subnet segment of the IP addresses that can be identified by ltran. The value is an example. Set the subnet based on the site requirements.| +||dispatch_subnet_length|n|Length of the Subnet that can be identified by ltran. For example, if the value of length is 4, the value ranges from 192.168.1.1 to 192.168.1.16.| +|bond|bond_mode|n|Bond mode. Currently, only Active Backup (Mode1) is supported. The value is 1.| +||bond_miimon|n|Bond link monitoring time. The unit is millisecond. The value ranges from 1 to 2^64 - 1 - (1000 x 1000).| +||bond_ports|"0xaa"|DPDK NIC to be used. The value 0x1 indicates the first NIC.| +||bond_macs|"aa:bb:cc:dd:ee:ff"|MAC address of the bound NIC, which must be the same as the MAC address of the KNI.| +||bond_mtu|n|Maximum transmission unit. The default and maximum value is 1500. The minimum value is 68.| + +**ltran.conf** example: +``` conf +forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages --proc-type primary --legacy-mem --map-perfect --syslog daemon" +forward_kit="dpdk" + +kni_switch=0 + +dispatch_max_clients=30 +dispatch_subnet="192.168.1.0" +dispatch_subnet_length=8 + +bond_mode=1 +bond_mtu=1500 +bond_miimon=100 +bond_macs="aa:bb:cc:dd:ee:ff" +bond_ports="0x1" + +tcp_conn_scan_interval=10 +``` +### 7. Starting an Application +- Start the ltran process. +If there is only one process and the NIC supports multiple queues, the NIC multi-queue is used to distribute packets to each thread. You do not need to start the ltran process. Set the value of **use_ltran** in the **lstack.conf** file to **0**. +If you do not use `-config-file` to specify a configuration file when starting ltran, the default configuration file path **/etc/gazelle/ltran.conf** is used. +``` sh +ltran --config-file ./ltran.conf +``` +- Start the application. +If the environment variable **LSTACK_CONF_PATH** is not used to specify the configuration file before the application is started, the default configuration file path **/etc/gazelle/lstack.conf** is used. +``` sh +export LSTACK_CONF_PATH=./lstack.conf +LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf +``` + +### 8. APIs +Gazelle wraps the POSIX interfaces of the application. The code of the application does not need to be modified. + +### 9. Commissioning Commands +- If ltran is not used, the `gazellectl ltran xxx` and `lstack -r` commands are not supported. +``` +Usage: gazellectl [-h | help] + or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] + or: gazellectl lstack show {ip} [LSTACK_OPTIONS] [time] + + quit ltran process exit + + where LTRAN_OPTIONS := + show ltran all statistics + -r, rate show ltran statistics per second + -i, instance show ltran instance register info + -b, burst show ltran NIC packet len per second + -l, latency show ltran latency + + where LSTACK_OPTIONS := + show lstack all statistics + -r, rate show lstack statistics per second + -s, snmp show lstack snmp + -c, connetct show lstack connect + -l, latency show lstack latency + + [time] measure latency time default 1S +``` + +### 10. Precautions +#### 1. Location of the DPDK Configuration File +For the **root** user, the configuration file is stored in the **/var/run/dpdk** directory after the DPDK is started. +For a non-root user, the path of the DPDK configuration file is determined by the environment variable **XDG_RUNTIME_DIR**. +- If **XDG_RUNTIME_DIR** is not set, the DPDK configuration file is stored in **/tmp/dpdk**. +- If **XDG_RUNTIME_DIR** is set, the DPDK configuration file is stored in in the path specified by **XDG_RUNTIME_DIR**. +- Note that **XDG_RUNTIME_DIR** is set by default on some servers. + +## Restrictions + +Restrictions of Gazelle are as follows: +#### Function Restrictions +- Blocking **accept()** or **connect()** is not supported. +- A maximum of 1500 TCP connections are supported. +- Currently, only TCP, ICMP, ARP, and IPv4 are supported. +- When a peer end pings Gazelle, the specified packet length must be less than or equal to 14,000 bytes. +- Transparent huge pages are not supported. +- ltran does not support the hybrid bonding of multiple types of NICs. +- The active/standby mode (bond1 mode) of ltran supports active/standby switchover only when a fault occurs at the link layer (for example, the network cable is disconnected), but does not support active/standby switchover when a fault occurs at the physical layer (for example, the NIC is powered off or removed). +- VM NICs do not support multiple queues. +#### Operation Constraints +- By default, the command lines and configuration files provided by Gazelle requires **root** permissions. Privilege escalation and changing of file owner are required for non-root users. +- To bind the NIC from user-mode driver back to the kernel driver, you must exit Gazelle first. +- Memory huge pages cannot be remounted to subdirectories created in the mount point. +- The minimum huge page memory required by ltran is 1 GB. +- The minimum hugepage memory of each application instance protocol stack thread is 800 MB. +- Gazelle supports only 64-bit OSs. +- The `-march=native` option is used when building the x86 version of Gazelle to optimize Gazelle based on the CPU instruction set of the build environment (Intel® Xeon® Gold 5118 CPU @ 2.30GHz). Therefore, the CPU of the running environment must support the SSE4.2, AVX, AVX2, and AVX-512 instruction set extensions. +- The maximum number of IP fragments is 10 (the maximum ping packet length is 14,790 bytes). TCP does not use IP fragments. +- You are advised to set the **rp_filter** parameter of the NIC to 1 using the `sysctl` command. Otherwise, the Gazelle protocol stack may not be used as expected. Instead, the kernel protocol stack is used. +- If ltran is not used, the KNI cannot be configured to be used only for local communication. In addition, you need to configure the NetworkManager not to manage the KNI network adapter before starting Gazelle. +- The IP address and MAC address of the virtual KNI must be the same as those in the **lstack.conf** file. + +## Risk Warning +Gazelle may have the following security risks. You need to evaluate the risks based on the application scenario. + +Shared memory +- Current situation: + The memory huge pages are mounted to the **/mnt/hugepages-2M** directory. During the initialization of a process that links to **liblstack.so**, files are created in the **/mnt/hugepages-2M** directory. Each file corresponds to a 2 MB memory huge page, and the mmap function is performed on the files. After receiving the registration information of lstask, ltran also perform the mmap function on the file in the directory based on the huge page memory configuration information to implement shared huge page memory. + The procedure also applies to the files in the **/mnt/hugepages** directory. +- Current Mitigation Measures + The huge page file permission is **600**. Only the owner can access the files. The default owner is the **root** user. Other users can be configured. + Huge page files are locked by DPDK and cannot be directly written or mapped. +- Risks: + Malicious processes belonging to the same user imitate the DPDK implementation logic to share huge page memory using huge page files and perform write operations to damage the huge page memory. As a result, the Gazelle program crashes. It is recommended that the processes of a user belong to the same trust domain. + +**Traffic Limit**: +Gazelle does not limit the traffic. Users can send packets at the maximum NIC line rate to the network, which may congest the network. + +**Process spoofing**: +If two lstack processes A and B are legitimately registered with ltran, A can impersonate B to send spoofing messages to ltran and modify the ltran forwarding control information. As a result, the communication of B becomes abnormal, and information leakage occurs when packets for B are sent to A. Ensure that all lstack processes are trusted. diff --git a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md index e35d2bd77..dac3ec162 100644 --- a/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md +++ b/docs/en/docs/KubeEdge/kubeedge-deployment-guide.md @@ -20,9 +20,9 @@ iSulad is a lightweight container runtime daemon designed for IoT and cloud infr | Component | Version | | ---------- | --------------------------------- | -| OS | openEuler 21.09 | +| OS | openEuler 22.03 | | Kubernetes | 1.20.2-4 | -| iSulad | 2.0.9-20210625.165022.git5a088d9c | +| iSulad | 2.0.11 | | KubeEdge | v1.8.0 | ### Node Planning Example @@ -66,7 +66,7 @@ Deploy Kubernetes by referring to the [Kubernetes Cluster Deployment Guide](http > Note: Preferentially, use `kubeadm` to deploy Kubernetes if the cloud node has access to the Internet. The procedure is as follows: ```bash -$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.11 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock +$ kubeadm init --apiserver-advertise-address=[cloud_node_IP_address] --kubernetes-version v1.20.15 --pod-network-cidr=10.244.0.0/16 --upload-certs --cri-socket=/var/run/isulad.sock ... Your Kubernetes control-plane has initialized successfully! ... diff --git a/docs/en/docs/NestOS/feature-description.md b/docs/en/docs/NestOS/feature-description.md new file mode 100644 index 000000000..10bc35f33 --- /dev/null +++ b/docs/en/docs/NestOS/feature-description.md @@ -0,0 +1,98 @@ +# Feature Description + +## Container Technology + +NestOS provides computing resources for applications using a containerized computing environment. Applications share a system kernel and resources, but are invisible to each other. This means that applications are no longer directly installed in the OS. Instead, they run in containers through Docker. This greatly reduces the coupling among the OS, applications, and running environment. Compared with the traditional application deployment mode, the NestOS cluster provides more flexible and convenient application deployment, less interference between application running environments , and the easier maintenance of OSs. + +## rpm-ostree + +### System Upgrade + +rpm-ostree is a hybrid image/package system that combines RPM and OSTree. It provides RPM-based software package installation and management, and OSTree-based OS update and upgrade. rpm-ostree sees the two operations as updates to the OS. Each update to the system is similar to a transaction submitted by rpm-ostree. This ensures that the update completely succeeds or fails completely and allows the system to be rolled back to the status before the update. + +When updating the OS, rpm-ostree keeps two bootable deployments: one before the update and one after the update. The update takes effect only after the OS is restarted. If an error occurs during software installation or upgrade, the rpm-ostree rollback allows NestOS to revert to the previous deployment. The **/ostree/** and **/boot/** directories of NestOS are the OSTree repository environment and show which OSTree deployment is booted into. + +### File System + +In the rpm-ostree file system layout, only the **/etc** and **/var** directories are writable. Any data in the **/var** directory is not touched and is shared across upgrades. During the system upgrade, rpm-ostree takes the new default **/etc** and adds the changes on the top. This means that the upgrades will receive new default files in **/etc**, which is a critical feature. + +OSTree is designed to parallel-install multiple versions of multiple independent operating systems. OSTree relies on a new top-level **ostree** directory; it can in fact parallel install inside an existing OS or distribution occupying the physical **/root**. On each client machine, there is an OSTree repository stored in **/ostree/repo**, and a set of deployments stored in **/ostree/deploy/$STATEROOT/$CHECKSUM**. Each deployment is primarily composed of a set of hard links into the repository. This means each version is deduplicated; an upgrade process only costs disk space proportional to the new files, plus some constant overhead. + +The model OSTree emphasizes is that the OS read-only content is kept in **/usr**; it comes with code to create a Linux read-only bind mount to prevent inadvertent corruption. There is exactly one **/var** writable directory shared between each deployment for a given OS. The OSTree core code does not touch content in this directory; it is up to the code in each operating system for how to manage and upgrade state. + +### OS Extensions + +NestOS keeps the base image as simple and small as possible for security and maintainability reasons. However, in some cases it is necessary to add software to the base OS itself. For example, drivers or VPN software are potential candidates because they are harder to containerize. These software packages extend the functionality of the base OS rather than providing runtimes for user applications. For this reason, rpm-ostree treats these packages as extensions. That said, there are no restrictions on which packages you can actually install. By default, packages are downloaded from the openEuler repositories. + +To layer a software package, you need to write a systemd unit that executes the `rpm-ostree` command to install the wanted package. The changes are added to a new deployment, which takes effect after restart. + +## nestos-installer + +nestos-installer helps with NestOS installation. It provides the following functions: + +(1) Installing the OS to a target disk, optionally customizing it with an Ignition configuration or first-boot kernel parameters (`nestos-installer install`) + +(2) Downloading and verify an OS image for various cloud, virtualization, or bare metal platforms (`nestos-installer download`) + +(3) Listing NestOS images available for download (`nestos-installer list-stream`) + +(4) Embed an Ignition configuration in a live ISO image to customize the running system that boots from it (`nestos-installer iso ignition`) + +(5) Wrap an Ignition configuration in an initrd image that can be appended to the live PXE initramfs to customize the running system that boots from it (`nestos-installer pxe ignition`) + +## zincati + +Zincati is an auto-update agent for NestOS hosts. It works as a client for Cincinnati and rpm-ostree, taking care of automatically updating/rebooting machines. Zincati has the following features: + +(1) Agent for continuous automatic updates, with support for phased rollouts + +(2) Runtime customization via TOML dropins, allowing users to overwrite the default configuration. + +(3) Multiple update strategies + +(4) Local maintenance windows on a weekly schedule for planned upgrades + +(5) Tracks and exposes Zincati internal metrics to Prometheus to ease monitoring tasks across a large fleet of nodes + +(6) Logging with configurable priority levels + +(7) Support for complex update-graphs via Cincinnati protocol + +(8) Support for cluster-wide reboot orchestration, via an external lock-manager + +## System Initialization (Ignition) + +Ignition is a distribution-agnostic provisioning utility that not only installs, but also reads configuration files (in JSON format) to provision NestOS. Configurable components include storage and file systems, systemd units, and users. + +Ignition runs only once during the first boot of the system (while in the initramfs). Because Ignition runs so early in the boot process, it can re-partition disks, format file systems, create users, and write files before the userspace begins to boot. As a result, systemd services are already written to disk when systemd starts, speeding the time to boot. + +(1) Ignition runs only on the first boot +Ignition is designed to be used as a provisioning tool, not as a configuration management tool. Ignition encourages immutable infrastructure, in which machine modification requires that users discard the old node and re-provision the machine. + +(2) Ignition produces the machine specified or no machine at all +Ignition does what it needs to make the system match the state described in the Ignition configuration. If for any reason Ignition cannot deliver the exact machine that the configuration asked for, Ignition prevents the machine from booting successfully. For example, if the user wanted to fetch the document hosted at **https://example.com/foo.conf** and write it to disk, Ignition would prevent the machine from booting if it were unable to resolve the given URL. + +(3) Ignition configurations are declarative +Ignition configurations describe the state of a system. Ignition configurations do not list a series of steps that Ignition should take. +Ignition configurations do not allow users to provide arbitrary logic (including scripts for Ignition to run). Users describe which file systems must exist, which files must be created, which users must exist, and more. Any further customization must use systemd services, created by Ignition. + +(4) Ignition configurations should not be written by hand +Ignition configurations were designed to be human readable, but difficult to write, to discourage users from attempting to write configs by hand. Use Butane, or a similar tool, to generate Ignition configurations. + +## Afterburn + +Afterburn is a one-shot agent for cloud-like platforms which interacts with provider-specific metadata endpoints. It is typically used in conjunction with Ignition. + +Afterburn comprises several modules which may run at different times during the lifecycle of an instance. Depending on the specific platform, the following services may run in the initramfs on first boot: + + - setting local hostname + + - injecting network command-line arguments + +The following features are conditionally available on some platforms as systemd service units: + + - installing public SSH keys for local system users + + - retrieving attributes from instance metadata + + - checking in to the provider in order to report a successful boot or instance provisioning diff --git a/docs/en/docs/NestOS/installation-and-deployment.md b/docs/en/docs/NestOS/installation-and-deployment.md new file mode 100644 index 000000000..0bce37b22 --- /dev/null +++ b/docs/en/docs/NestOS/installation-and-deployment.md @@ -0,0 +1,128 @@ +# Installation and Deployment + +## Deploying NestOS on VMware + +This guide describes how to configure latest NestOS in VMware. + +Currently, NestOS supports only the x86_64 architecture. + +### Before You Start + +​ Before deploying NestOS, make the following preparations: + +- Downloading the NestOS ISO +- Preparing the **config.bu** File +- Configuring the Butane Tool (on Linux or Windows 10) +- A host machine with VMware installed + +### Initial Installation and Startup + +#### Starting NestOS + +When NestOS is started for the first time, Ignition is not installed. You can use the nestos-installer component to install Ignition as prompted. + +### Producing an Ignition File + +#### Obtaining Butane + +You can use Butane to convert a .bu file into an Ignition file. Ignition configurations were designed to be human readable, but difficult to write, to +discourage users from attempting to write configs by hand. +Butane supports multiple environments. You can use Butane in a Linux or Windows host machines or in container environments. + +``` +docker pull quay.io/coreos/butane:release +``` + +#### Generating a Login Password + +Run the following command on the host machine and enter the password: + +``` +# openssl passwd -1 -salt yoursalt +Password: +$1$yoursalt$1QskegeyhtMG2tdh0ldQN0 +``` + +#### Generating an SSH Key Pair + +Run the following command on the host machine to obtain the public key and private key for SSH login: + +``` +# ssh-keygen -N '' -f ./id_rsa +Generating public/private rsa key pair. +Your identification has been saved in ./id_rsa +Your public key has been saved in ./id_rsa.pub +The key fingerprint is: +SHA256:4fFpDDyGHOYEd2fPaprKvvqst3T1xBQuk3mbdon+0Xs root@host-12-0-0-141 +``` + +``` +The key's randomart image is: ++---[RSA 3072]----+ +| ..= . o . | +| * = o * . | +| + B = * | +| o B O + . | +| S O B o | +| * = . . | +| . +o . . | +| +.o . .E | +| o*Oo ... | ++----[SHA256]-----+ +``` + +You can view the **id_rsa.pub** public key in the current directory. + +``` +# cat id_rsa.pub +ssh-rsa +AAAAB3NzaC1yc2... +``` + +#### Compiling a .bu File + +Perform a simple initial configuration. For more details, see the description of Ignition. +A simple **config.bu** file is as follows: + +``` +variant: fcos +version: 1.1.0 +passwd: + users: + - name: nest + password_hash: "$1$yoursalt$1QskegeyhtMG2tdh0ldQN0" + ssh_authorized_keys: + - "ssh-rsa + AAAAB3NzaC1yc2EAAA..." +``` + +#### Generating an Ignition File + +Use the Butane tool to convert the **config.bu** file to a **config.ign** file in the container environment. + +``` +# docker run --interactive --rm quay.io/coreos/butane:release \ +--pretty --strict < your_config.bu > transpiled_config.ign +``` + +### Installing NestOS + +Use SCP to copy the **config.ign** file generated by the host machine to NestOS that is initially started, which is not installed to the disk and runs in the memory. + +``` +sudo -i +scp root@your_ipAddress:/root/config.ign /root +``` + +Run the following command and complete the installation as prompted: + +``` +nestos-installer install /dev/sda --ignition-file config.ign +``` + +After the installation is complete, restart NestOS. + +``` +systemctl reboot +``` +Complete. diff --git a/docs/en/docs/NestOS/overview.md b/docs/en/docs/NestOS/overview.md new file mode 100644 index 000000000..e6072c28f --- /dev/null +++ b/docs/en/docs/NestOS/overview.md @@ -0,0 +1,3 @@ +# NestOS User Guide + +This document describes the installation, deployment, features, and usage of the NestOS cloud-based operating system. NestOS integrates mainstream container platforms, such as iSulad, Docker, and PodMan. It eliminates unreliable issues during upgrades caused by modification to the system, dependency of user services on system components, and unstable intermediate states of software packages. NestOS is provided as a lightweight and customizable OS for easy cluster deployment. To download NestOS images, visit the [NestOS Repository](https://gitee.com/openeuler/NestOS). diff --git a/docs/en/docs/NestOS/usage.md b/docs/en/docs/NestOS/usage.md new file mode 100644 index 000000000..76f64e3ca --- /dev/null +++ b/docs/en/docs/NestOS/usage.md @@ -0,0 +1,489 @@ +# Setting Up Kubernetes and iSulad + +**Perform the following steps on both the master and node.** This tutorial uses the master as an example. + +## Before You Start + +Prepare **NestOS-22.03-date.x86_64.iso** and two hosts as the master and node. + +## Downloading the Components + +Open the repo source file to add the Alibaba Cloud source of Kubernetes. + +``` +vi /etc/yum.repos.d/openEuler.repo +``` + +Add the following content: + +``` +[kubernetes] +name=Kubernetes +baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/ +enabled=1 +gpgcheck=1 +repo_gpgcheck=1 +gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg +``` + +Downloads the Kubernetes components and the components for synchronizing the system time. + +``` +rpm-ostree install kubelet kubeadm kubectl ntp ntpdate wget +``` + +Restart the system to use the components. + +``` +systemctl reboot +``` + +Select the latest version branch and enter the system. + +## Configuring the Environment + +### Change the Host Name of the Master + +``` +hostnamectl set-hostname k8s-master +sudo -i +``` + +Open the **/etc/hosts** file. + +``` +vi /etc/hosts +``` + +Add the IP addresses of the hosts. + +``` +192.168.237.133 k8s-master +192.168.237.135 k8s-node01 +``` + +### Synchronizing the System Time + +``` +ntpdate time.windows.com +systemctl enable ntpd +``` + +``` +Disable the swap partition, firewall, and SELinux. +``` + +By default, the NestOS does not have the swap partition and the firewall is disabled. +Run the following command to disable SELinux: + +``` +vi /etc/sysconfig/selinux +Change the value of SELINUX to disabled. +``` + +### Enabling Forwarding Mechanisms + +Create a configuration file. + +``` +vi /etc/sysctl.d/k8s.conf +``` + +Add the following content: + +``` +net.bridge.bridge-nf-call-iptables=1 +net.bridge.bridge-nf-call-ip6tables=1 +net.ipv4.ip_forward=1 +``` + +Make the configuration take effect. + +``` +modprobe br_netfilter +sysctl -p /etc/sysctl.d/k8s.conf +``` + +## Configuring iSula + +Check the OS image required by Kubernetes. Pay attention to the version number of the pause container. + +``` +kubeadm config images list +``` + +Modify the **daemon.json** configuration file. + +``` +vi /etc/isulad/daemon.json +``` + +``` +## Description of the added items ## +Set registry-mirrors to "docker.io". +Set insecure-registries to "rnd-dockerhub.huawei.com". +Set pod-sandbox-image to "registry.aliyuncs.com/google_containers/pause:3.5". (The Alibaba Cloud source is used. The pause version is obtained in the previous step.) +Set network-plugin to "cni". +Set cni-bin-dir to "/opt/cni/bin". +Set cni-conf-dir to "/etc/cni/net.d". +``` + +The modified file is as follows: + +``` +{"group": "isula", +"default-runtime": "lcr", +"graph": "/var/lib/isulad", +"state": "/var/run/isulad", +"engine": "lcr", +"log-level": "ERROR", +"pidfile": "/var/run/isulad.pid", +"log-opts": { +"log-file-mode": "0600", +"log-path": "/var/lib/isulad", +"max-file": "1", +"max-size": "30KB" +}, +"log-driver": "stdout", +"container-log": { +"driver": "json-file" +}, +"hook-spec": "/etc/default/isulad/hooks/default.json", +"start-timeout": "2m", +"storage-driver": "overlay2", +"storage-opts": [ +"overlay2.override_kernel_check=true" +], +"registry-mirrors": [ +"docker.io" +], +"insecure-registries": [ +"rnd-dockerhub.huawei.com" +], +"pod-sandbox-image": "registry.aliyuncs.com/google_containers/pause:3.5", +"native.umask": "secure", +"network-plugin": "cni", +"cni-bin-dir": "/opt/cni/bin", +"cni-conf-dir": "/etc/cni/net.d", +"image-layer-check": false, +"use-decrypted-key": true, +"insecure-skip-verify-enforce": false +} +``` + +Start the services. + +``` +systemctl restart isulad +systemctl enable isulad +systemctl enable kubelet +``` + +**Perform the preceding steps on both the master and node.** + +## Initializing the Master + +**Perform this step only on the master.** +Run the following command and wait for the host to pull the image. You can also manually pull the image before performing this step. + +``` +kubeadm init --kubernetes-version=1.22.2 --apiserver-advertise- +address=192.168.237.133 --cri-socket=/var/run/isulad.sock --image-repository +registry.aliyuncs.com/google_containers --service-cidr=10.10.0.0/16 --pod- +network-cidr=10.122.0.0/16 +``` + +``` +## Description of initialization parameters ## +kubernetes-version indicates the version to be installed. +apiserver-advertise-address indicates the IP address of the master. +cri-socket specifies the iSulad engine. +image-repository specifies that the image source is Alibaba Cloud. You do not need to modify the tag. +service-cidr specifies the IP address range allocated to the service. +pod-network-cidr specifies the IP address range allocated to the Pod network. +``` + +After the initialization is successful, copy the `kubeadm join` command that is output by `kubeadm init` for subsequent node joining. + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +**Note**: `--cri-socket=/var/run/isulad.sock` specifies that iSulad is used as the container engine. +View the downloaded image. + +``` +isula images +``` + +Configure the cluster based on the output of the initialization command. + +``` +mkdir -p $HOME/.kube +cp -i /etc/kubernetes/admin.conf $HOME/.kube/config +chown $(id -u):$(id -g) $HOME/.kube/config +export KUBECONFIG=/etc/kubernetes/admin.conf +source /etc/profile +``` + +Check the health status. + +``` +kubectl get cs +``` + +The status of **controller-manager** and **scheduler** may be **unhealthy**. To rectify the fault, perform the following steps: +Edit the configuration file. + +``` +vi /etc/kubernetes/manifests/kube-controller-manager.yaml +``` + +``` +Comment out the following content: +--port=0 +Modify hostpath: +Change all /usr/libexec/kubernetes/kubelet-plugins/volume/exec to /opt/libexec/... +``` + +``` +vi /etc/kubernetes/manifests/kube-scheduler.yaml +``` + +``` +Comment out the following content: +--port=0 +``` + +After the modification is complete, check the health status again. + +## Configuring the Network Plugin + +Configure the network plugin only on the master. However, you need to pull images on all hosts in advance. The commands for pulling images are as follows: + +``` +isula pull calico/node:v3.19.3 +isula pull calico/cni:v3.19.3 +isula pull calico/kube-controllers:v3.19.3 +isula pull calico/pod2daemon-flexvol:v3.19.3 +``` + +**Perform the following steps only on the master.** +Obtain the configuration file. + +``` +wget https://docs.projectcalico.org/v3.19/manifests/calico.yaml +``` + +Edit **calico.yaml** and change all **/usr/libexec/...** to **/opt/libexec/...**. +Run the following command to install Calico: + +``` +kubectl apply -f calico.yaml +``` + +Run the `kubectl get pod -n kube-system` command to check whether Calico is successfully installed. +Run the `kubectl get pod -n kube-system` command to check whether all Pods are in the** running** status. + +## Joining the Node to the Cluster + +Run the following command on the node to join the node to the cluster: + +``` +kubeadm join 192.168.237.133:6443 --token j7kufw.yl1gte0v9qgxjzjw --discovery- +token-ca-cert-hash +sha256:73d337f5edd79dd4db997d98d329bd98020b712f8d7833c33a85d8fe44d0a4f5 --cri- +socket=/var/run/isulad.sock +``` + +Run the `kubectl get node` command to check whether the master and node statuses are **ready**. + +If yes, Kubernetes is successfully deployed. + +# Using rpm-ostree + +## Installing Software Packages Using rpm-ostree + +Install wget. + +``` +rpm-ostree install wget +``` + +Restart the system. During the startup, use the up and down arrow keys on the keyboard to enter system before or after the RPM package installation. **ostree:0** indicates the version after the installation. + +``` +systemctl reboot +``` + +Check whether wget is successfully installed. + +``` +rpm -qa | grep wget +``` + +## Manually Upgrading NestOS Using rpm-ostree + +Run the following command in NestOS to view the current rpm-ostree status and version: + +``` +rpm-ostree status +``` + +Run the check command to check whether a new version is available. + +``` +rpm-ostree upgrade --check +``` + +Preview the differences between the versions. + +``` +rpm-ostree upgrade --preview +``` + +In the latest version, the nano package is imported. +Run the following command to download the latest ostree and RPM data without performing the deployment. + +``` +rpm-ostree upgrade --download-only +``` + +Restart NestOS. After the restart, the old and new versions of the system are available. Enter the latest version. + +``` +rpm-ostree upgrade --reboot +``` + +## Comparing NestOS Versions + +Check the status. Ensure that two versions of ostree exist: **LTS.20210927.dev.0** and **LTS.20210928.dev.0**. + +``` +rpm-ostree status +``` + +Compare the ostree versions based on commit IDs. + +``` +rpm-ostree db diff 55eed9bfc5ec fe2408e34148 +``` + +## Rolling Back the System + +When a system upgrade is complete, the previous NestOS deployment is still stored on the disk. If the upgrade causes system problems, you can roll back to the previous deployment. + +### Temporary Rollback + +To temporarily roll back to the previous OS deployment, hold down **Shift** during system startup. When the boot load menu is displayed, select the corresponding branch from the menu. + +### Permanent Rollback + +To permanently roll back to the previous OS deployment, log in to the target node and run the `rpm-ostree rollback` command. This operation sets the previous OS deployment as the default deployment to boot into. +Run the following command to roll back to the system before the upgrade: + +``` +rpm-ostree rollback +``` + + +## Switching Versions + +NestOS is rolled back to an older version. You can run the following command to switch the rpm-ostree version used by NestOS to a newer version. + +``` +rpm-ostree deploy -r 22.03.20220325.dev.0 +``` + +After the restart, check whether NestOS uses the latest ostree version. + + +# Using Zincati for Automatic Update + +Zincati automatically updates NestOS. Zincati uses the Cincinnati backend to check whether a new version is available. If a new version is available, Zincati downloads it using rpm-ostree. + +Currently, the Zincati automatic update service is disabled by default. You can modify the configuration file to set the automatic startup upon system startup for Zincati. + +``` +vi /etc/zincati/config.d/95-disable-on-dev.toml +``` + +Set **updates.enabled** to true. +Create a configuration file to specify the address of the Cincinnati backend. + +``` +vi /etc/zincati/config.d/update-cincinnati.toml +``` + +Add the following content: + +``` +[cincinnati] +base_url="http://nestos.org.cn:8080" +``` + +Restart the Zincati service. + +``` +systemctl restart zincati.service +``` + +When a new version is available, Zincati automatically detects the new version. Check the rpm-ostree status. If the status is **busy**, the system is being upgraded. + +After a period of time, NestOS automatically restarts. Log in to NestOS again and check the rpm-ostree status. If the status changes to **idle** and the current version is **20220325**, rpm-ostree has been upgraded. + +View the zincati service logs to check the upgrade process and system restart logs. In addition, the information "auto-updates logic enabled" in the logs indicates that the update is automatic. + +# Customizing NestOS + +You can use the nestos-installer tool to customize the original NestOS ISO file and package the Ignition file to generate a customized NestOS ISO file. The customized NestOS ISO file can be used to automatically install NestOS after the system is started for easy installation. + +Before customizing NestOS, make the following preparations: + +- Downloading the NestOS ISO. +- Preparing a **config.ign** File. + +## Generating a Customized NestOS ISO File + +### Setting Parameter Variables + +``` +$ export COREOS_ISO_ORIGIN_FILE=nestos-22.03.20220324.x86_64.iso +$ export COREOS_ISO_CUSTOMIZED_FILE=my-nestos.iso +$ export IGN_FILE=config.ign +``` + +### Checking the ISO File + +Ensure that the original NestOS ISO file does not contain the Ignition configuration. + +``` +$ nestos-installer iso ignition show $COREOS_ISO_ORIGIN_FILE + +Error: No embedded Ignition config. +``` + +### Generating a Customized NestOS ISO File + +Package the Ignition file into the original NestOS ISO file to generate a customized NestOS ISO file. + +``` +$ nestos-installer iso ignition embed $COREOS_ISO_ORIGIN_FILE --ignition-file $IGN_FILE $COREOS_ISO_ORIGIN_FILE --output $COREOS_ISO_CUSTOMIZED_FILE +``` + +### Checking the ISO File + +Ensure that the customized NestOS ISO file contains the Ignition configuration. + +``` +$ nestos-installer iso ignition show $COREOS_ISO_CUSTOMIZED_FILE +``` + +The previous command displays the Ignition configuration. + +## Installing the Customized NestOS ISO File + +The customized NestOS ISO file can be used to directly boot the installation. NestOS is automatically installed based on the Ignition configuration. After the installation is complete, you can use **nest/password** to log in to NestOS on the VM console. diff --git a/docs/en/docs/Releasenotes/installing-the-os.md b/docs/en/docs/Releasenotes/installing-the-os.md index 80f737499..5b608c0d8 100644 --- a/docs/en/docs/Releasenotes/installing-the-os.md +++ b/docs/en/docs/Releasenotes/installing-the-os.md @@ -2,7 +2,7 @@ ## Release Files -The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. +The openEuler release files include [ISO release packages](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/), [VM images](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/), [container images](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/), [embedded images](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/), and [repo sources](http://repo.openeuler.org/openEuler-22.03-LTS/). The following tables describe those files respectively. Table 1 ISO release packages @@ -34,7 +34,19 @@ Table 3 Container images | openEuler-docker.aarch64.tar.xz | Container image of openEuler in the AArch64 architecture. | | openEuler-docker.x86_64.tar.xz | Container image of openEuler in the x86_64 architecture. | -Table 4 Repo sources +Table 4 Embedded images + +| Name | Description | +| -------------------------------------- | ------------------------------- | +| arm64/aarch64-std/zImage | Kernel image that supports QEMU in the AArch64 architecture. | +| arm64/aarch64-std/\*toolchain-22.03.sh | Development and compilation toolchain in the AArch64 architecture. | +| arm64/aarch64-std/\*rootfs.cpio.gz | File system that supports QEMU in the AArch64 architecture. | +| arm32/arm-std/zImage | Kernel image that supports QEMU in the ARM architecture. | +| arm32/arm-std/\*toolchain-22.03.sh | Development and compilation toolchain in the ARM architecture. | +| arm32/arm-std/\*rootfs.cpio.gz | File system that supports QEMU in the ARM architecture. | +| source-list/manifest.xml | Manifest of source code used for building. | + +Table 5 Repo sources | Name | Description | | ------------------- | ------------------------------------------ | @@ -43,6 +55,7 @@ Table 4 Repo sources | debuginfo | Stores debugging package sources. | | docker_img | Stores container images. | | virtual_machine_img | Stores VM images. | +| embedded_img | Stores embedded images. | | everything | Stores full software package sources. | | extras | Stores extended software package sources. | | source | Stores source code software package. | @@ -53,7 +66,7 @@ Table 4 Repo sources The following table lists the minimum hardware specifications for openEuler 22.03 LTS. -Table 1 Minimum hardware requirements +Table 6 Minimum hardware requirements | Component | Minimum Hardware Specification | | ---------- | --------------------------------------------------- | @@ -65,7 +78,7 @@ Table 1 Minimum hardware requirements The following table describes the servers and configurations supported by openEuler. openEuler will support more servers in the future. Partners and developers are welcome to participate in the contribution and verification. For details about the servers supported by openEuler, see the [Compatibility List](https://www.openeuler.org/en/compatibility/). -Table 1 Supported servers and configurations +Table 7 Supported servers and configurations diff --git a/docs/en/docs/Releasenotes/key-features.md b/docs/en/docs/Releasenotes/key-features.md index 648020be1..f49f40a02 100644 --- a/docs/en/docs/Releasenotes/key-features.md +++ b/docs/en/docs/Releasenotes/key-features.md @@ -83,24 +83,26 @@ Unified edge-cloud synergy framework KubeEdge+ is provided, implementing basic c ## Embedded Image -Basic capabilities, such as lightweight, security hardening, and lightweight containers, are provided, and the ARM32 and ARM64 chip architectures are supported. - -- **Lightweight capability**: The OS image size can be less than 5 MB, the background noise can be less than 15 MB, and the startup time can be less than 5s. -- **Security hardening**: Security hardening is performed on resources such as account passwords and file permissions. OS security is enabled by default. -- **Lightweight containers**: Standard container images can be deployed and run in lightweight containers in embedded scenarios. -- **Multi-architecture support**: The ARM32 and ARM64 chip architectures are supported. -- **Hybrid deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. -- **Small-scale tailoring**: Small-scale tailoring based on the Yocto build package is supported. ARM Cross Compilation -- **ARM cross compilation tool**: The ARM cross compilation tool chain is provided based on GCC 10.3 of the community. +- ** Lightweight models**: The Yocto small-scale build tailoring framework allows you to customize system items into compressed, lightweight models. For example, OS images can be reduced to less than 5 MB, memory overhead to under 15 MB, and startup to under 5s. +- **Support for multiple types of hardware**: Raspberry Pi 4B is supported as the universal hardware for embedded scenarios. +- **Soft real-time kernel**: The soft real-time capabilities based on the Linux 5.10 kernel allow for microsecond-level soft real-time interrupt response latency. +- **Hybrid critical deployment**: Hybrid deployment of real-time and non-real-time planes in the SOC is supported. Zephyr real-time kernel is also supported. - **Distributed soft bus (DSoftBus)**: The DSoftBus of HarmonyOS is integrated to implement interconnection and interworking between embedded devices running on openEuler. +- **Embedded software package support**: More than 80 common embedded software packages can be built using openEuler. ## secPaver - secPaver is an SELinux policy development tool used to assist developers in developing security policies for applications. - - **Policy management**: provides a high-level configuration language and generates SELinux policy files based on the policy configuration file to reduce the threshold for using SELinux. +## NestOS +NestOS is a cloud-based OS provided by the CloudNative SIG of the openEuler community. It is dedicated to providing optimal container hosts for securely running containerized workloads on a large scale. +- **Out-of-the-box container platforms**: Mainstream basic container platforms such as iSulad, Docker, PodMan, and CRI-O are included. +- **Easy-to-use installation and configuration**: Ignition is used to provide personalized configuration. +- **Secure and reliable package management**: rpm-ostree is used for package management. +- **User-friendly and controllable automatic update agent**: Zincati provides insensible upgrade. +- **Dual-partition system**: The dual-partition design ensures system security. + ## Third-party Application Support - **KubeSphere**: It is an application-centric and open-source container platform built based on Kubernetes. It is initiated by Beijing Qingyun Technology Co., Ltd. and supported and maintained by SIG-KubeSphere of the openEuler community. @@ -114,4 +116,4 @@ More desktop environments are provided to ensure better development experience. - **DDE** is upgraded and supports drawing board, music, and cinema applications. - **UKUI** is upgraded and supports the Chinese input method and multimedia. - **kiran-desktop** is supported. -- **GNOME** is supported. \ No newline at end of file +- **GNOME** is supported. diff --git a/docs/en/docs/TailorCustom/figures/flowchart.png b/docs/en/docs/TailorCustom/figures/flowchart.png new file mode 100644 index 0000000000000000000000000000000000000000..d3a71e8bfdb886222151cea3b2a3c0e8d8eae64a GIT binary patch literal 19918 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 literal 0 HcmV?d00001 diff --git a/docs/en/docs/TailorCustom/imageTailor-user-guide.md b/docs/en/docs/TailorCustom/imageTailor-user-guide.md new file mode 100644 index 000000000..2ad4ae701 --- /dev/null +++ b/docs/en/docs/TailorCustom/imageTailor-user-guide.md @@ -0,0 +1,928 @@ +# ImageTailor User Guide + + - [Introduction](#introduction) + - [Installation](#installation) + - [Software and Hardware Requirements](#software-and-hardware-requirements) + - [Obtaining the Installation Package](#obtaining-the-installation-package) + - [Installing imageTailor](#installing-imagetailor) + - [Directory Description](#directory-description) + - [Image Customization](#image-customization) + - [Overall Process](#overall-process) + - [Customizing Service Packages](#customizing-service-packages) + - [Setting a Local Repo Source](#setting-a-local-repo-source) + - [Adding Files](#adding-files) + - [Adding RPM Packages](#adding-rpm-packages) + - [Adding Hook Scripts](#adding-hook-scripts) + - [Configuring System Parameters](#configuring-system-parameters) + - [Configuring Host Parameters](#configuring-host-parameters) + - [Configuring Initial Passwords](#configuring-initial-passwords) + - [Configuring Partitions](#configuring-partitions) + - [Configuring the Network](#configuring-the-network) + - [Configuring Kernel Parameters](#configuring-kernel-parameters) + - [Creating an Image](#creating-an-image) + - [Command Description](#command-description) + - [Image Creation Guide](#image-creation-guide) + - [Tailoring Time Zones](#tailoring-time-zones) + - [Customization Example](#customization-example) + + + +## Introduction + +In addition to the kernel, an operating system contains various peripheral packages. These peripheral packages provide functions of a general-purpose operating system but also cause the following problems: + +- A large number of resources (such as memory, disks, and CPUs) are occupied, resulting in low system performance. +- Unnecessary functions increase the development and maintenance costs. + +To address these problems, openEuler provides the imageTailor tool for tailoring and customization images. You can tailor unnecessary peripheral packages in the OS image or add service packages or files as required. This tool includes the following functions: + +- System package tailoring: Tailors system commands, libraries, and drivers based on the list of RPM packages to be installed. +- System configuration modification: Configures the host name, startup services, time zone, network, partitions, drivers to be loaded, and kernel version. +- Software package addition: Adds custom RPM packages or files to the system. + + + +## Installation + +This section uses openEuler 22.03 LTS in the AArch64 architecture as an example to describe the installation method. + +### Software and Hardware Requirements + +The software and hardware requirements of imageTailor are as follows: + +- The architecture is x86_64 or AArch64. + +- The OS is openEuler 22.03 LTS (the kernel version is 5.10 and the Python version is 3.9, which meet the tool requirements). + +- The root directory **/** of the host to run the tool have at least 40 GB space. + +- The Python version is 3.9 or later. + +- The kernel version is 5.10 or later. + +- The SElinux service is disabled. + + ```shell + $ sudo setenforce 0 + $ getenforce + Permissive + ``` + + + +### Obtaining the Installation Package + +Download the openEuler release package to install and use imageTailor. + +1. Obtain the ISO image file and the corresponding verification file. + + The image must be an everything image. Assume that the image is to be stored in the **root** directory. Run the following commands: + + ```shell + $ cd /root/temp + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +3. Obtain the verification value in the sha256sum verification file. + + ```shell + $ cat openEuler-22.03-LTS-everything-aarch64-dvd.iso.sha256sum + ``` + +4. Calculate the verification value of the ISO image file. + + ```shell + $ sha256sum openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +5. Compare the verification value in the sha256sum file with that of the ISO image. If they are the same, the file integrity is verified. Otherwise, the file integrity is damaged. You need to obtain the file again. + +### Installing imageTailor + +The following uses openEuler 22.03 LTS in AArch64 architecture as an example to describe how to install imageTailor. + +1. Ensure that openEuler 22.03 LTS (or a running environment that meets the requirements of imageTailor) has been installed on the host. + + ```shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. Create a **/etc/yum.repos.d/local.repo** file to configure the Yum source. The following is an example of the configuration file. **baseurl** indicates the directory for mounting the ISO image. + + ```shell + [local] + name=local + baseurl=file:///root/imageTailor_mount + gpgcheck=0 + enabled=1 + ``` + +3. Run the following commands as the **root** user to mount the image to the **/root/imageTailor_mount** directory as the Yum source (ensure that the value of **baseurl** is the same as that configured in the repo file and the disk space of the directory is greater than 20 GB): + + ```shell + $ mkdir /root/imageTailor_mount + $ sudo mount -o loop /root/temp/openEuler-22.03-LTS-everything-aarch64-dvd.iso /root/imageTailor_mount/ + ``` + +4. Make the Yum source take effect. + + ```shell + $ yum clean all + $ yum makecache + ``` + +5. Install the imageTailor tool as the **root** user. + + ```shell + $ sudo yum install -y imageTailor + ``` + +6. Run the following command as the **root** user to verify that the tool has been installed successfully: + + ```shell + $ cd /opt/imageTailor/ + $ sudo ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + Usage: mkdliso -p product_name -c configpath [--minios yes|no|force] [-h] [--sec] + Options: + -p,--product Specify the product to make, check custom/cfg_yourProduct. + -c,--cfg-path Specify the configuration file path, the form should be consistent with custom/cfg_xxx + --minios Make minios: yes|no|force + --sec Perform security hardening + -h,--help Display help information + + Example: + command: + ./mkdliso -p openEuler -c custom/cfg_openEuler --sec + + help: + ./mkdliso -h + ------------------------------------------------------------------------------------------------------------- + ``` + +### Directory Description + +After imageTailor is installed, the directory structure of the tool package is as follows: + +```shell +[imageTailor] + |-[custom] + |-[cfg_openEuler] + |-[usr_file] // Stores files to be added. + |-[usr_install] //Stores hook scripts to be added. + |-[all] + |-[conf] + |-[hook] + |-[cmd.conf] // Configures the default commands and libraries used by an ISO image. + |-[rpm.conf] // Configures the list of RPM packages and drivers installed by default for an ISO image. + |-[security_s.conf] // Configures security hardening policies. + |-[sys.conf] // Configures ISO image system parameters. + |-[kiwi] // Basic configurations of imageTailor. + |-[repos] //RPM sources for obtaining the RPM packages required for creating an ISO image. + |-[security-tool] // Security hardening tool. + |-mkdliso // Executable script for creating an ISO image. +``` + +## Image Customization + +This section describes how to use the imageTailor tool to package the service RPM packages, custom files, drivers, commands, and libraries to the target ISO image. + +### Overall Process + +The following figure shows the process of using imageTailor to customize an image. + +![](./figures/flowchart.png) + +The steps are described as follows: + +- Check software and hardware environment: Ensure that the host for creating the ISO image meets the software and hardware requirements. + +- Customize service packages: Add RPM packages (including service RPM packages, commands, drivers, and library files) and files (including custom files, commands, drivers, and library files). + + - Adding service RPM packages: Add RPM packages to the ISO image as required. For details, see [Installation](#installation). + - Adding custom files: If you want to perform custom operations such as hardware check, system configuration check, and driver installation when the target ISO system is installed or started, you can compile custom files and package them to the ISO image. + - Adding drivers, commands, and library files: If the RPM package source of openEuler does not contain the required drivers, commands, or library files, you can use imageTailor to package the corresponding drivers, commands, or library files into the ISO image. + +- Configure system parameters: + + - Configuring host parameters: To ensure that the ISO image is successfully installed and started, you need to configure host parameters. + - Configuring partitions: You can configure service partitions based on the service plan and adjust system partitions. + - Configuring the network: You can set system network parameters as required, such as the NIC name, IP address, and subnet mask. + - Configuring the initial password: To ensure that the ISO image is successfully installed and started, you need to configure the initial passwords of the **root** user and GRUB. + - Configuring kernel parameters: You can configure the command line parameters of the kernel as required. + +- Configure security hardening policies. + + ImageTailor provides default security hardening policies. You can modify **security_s.conf** (in the ISO image customization phase) to perform secondary security hardening on the system based on service requirements. For details, see the [Security Hardening Guide](https://docs.openeuler.org/en/docs/22.03_LTS/docs/SecHarden/secHarden.html). + +- Create an ISO image: + + Use the imageTailor tool to create an ISO image. + +### Customizing Service Packages + +You can pack service RPM packages, custom files, drivers, commands, and library files into the target ISO image as required. + +#### Setting a Local Repo Source + +To customize an ISO image, you must set a repo source in the **/opt/imageTailor/repos/euler_base/** directory. This section describes how to set a local repo source. + +1. Download the ISO file released by openEuler. (The RPM package of the everything image released by the openEuler must be used.) + ```shell + $ cd /opt + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + ``` + +2. Create a mount directory **/opt/openEuler_repo** and mount the ISO file to the directory. + ```shell + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + ``` + +3. Copy the RPM packages in the ISO file to the **/opt/imageTailor/repos/euler_base/** directory. + ```shell + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +#### Adding Files + +You can add files to an ISO image as required. The file types include custom files, drivers, commands, or library file. Store the files to the **/opt/imageTailor/custom/cfg_openEuler/usr_file** directory. + +##### Precautions + +- The commands to be packed must be executable. Otherwise, imageTailor will fail to pack the commands into the ISO. + +- The file stored in the **/opt/imageTailor/custom/cfg_openEuler/usr_file** directory will be generated in the root directory of the ISO. Therefore, the directory structure of the file must be a complete path starting from the root directory so that imageTailor can place the file in the correct directory. + + For example, if you want **file1** to be in the **/opt** directory of the ISO, create an **opt** directory in the **usr_file** directory and copy **file1** to the **opt** directory. For example: + + ```shell + $ pwd + /opt/imageTailor/custom/cfg_openEuler/usr_file + + $ tree + . + ├── etc + │   ├── default + │   │   └── grub + │   └── profile.d + │   └── csh.precmd + └── opt + └── file1 + + 4 directories, 3 files + ``` + +- The paths in **/opt/imageTailor/custom/cfg_openEuler/usr_file** must be real paths. For example, the paths do not contain soft links. You can run the `realpath` or `readlink -f` command to query the real path. + +- If you need to invoke a custom script in the system startup or installation phase, that is, a hook script, store the file in the **hook** directory. + +#### Adding RPM Packages + +##### Procedure + +To add RPM packages (drivers, commands, or library files) to an ISO image, perform the following steps: + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- The **rpm.conf** and **cmd.conf** files are stored in the **/opt/imageTailor/custom/cfg_openEuler/** directory. +>- The RPM package tailoring granularity below indicates **sys_cut='no'**. For details about the cutout granularity, see [Configuring Host Parameters](#configuring-host-parameters). +>- If no local repo source is configured, configure a local repo source by referring to [Setting a Local Repo Source](#setting-a-local-repo-source). +> + +1. Check whether the **/opt/imageTailor/repos/euler_base/** directory contains the RPM package to be added. + + - If yes, go to step 2. + - If no, go to step 3. +2. Configure the RPM package information in the **\** section in the **rpm.conf** file. + - For the RPM package tailoring granularity, no further action is required. + - For other tailoring granularities, go to step 4. +3. Obtain the RPM package and store it in the **/opt/imageTailor/custom/cfg_openEuler/usr_rpm** directory. If the RPM package depends on other RPM packages, store the dependency packages to this directory because the added RPM package and its dependent RPM packages must be packed into the ISO image at the same time. + - For the RPM package tailoring granularity, go to step 4. + - For other tailoring granularities, no further action is required. +4. Configure the drivers, commands, and library files to be retained in the RPM package in the **rpm.conf** and **cmd.conf** files. If there are common files to be tailored, configure them in the **\\** section in the **cmd.conf** file. + + +##### Configuration File Description + +| Operation | Configuration File| Section | +| :----------- | :----------- | :----------------------------------------------------------- | +| Adding drivers | rpm.conf | \
\
\

Note: The **driver_name** is the relative path of **/lib/modules/{kernel_version_number}/kernel/**.| +| Adding commands | cmd.conf | \
\
\
| +| Adding library files | cmd.conf | \
\
\
| +| Deleting other files| cmd.conf | \
\
\

Note: The file name must be an absolute path.| + +**Example** + +- Adding drivers + + ```shell + + + + + ...... + + ``` + +- Adding commands + + ```shell + + + + + ...... + + ``` + +- Adding library files + + ```shell + + + + + + ``` + +- Deleting other files + + ```shell + + + + + + ``` + +#### Adding Hook Scripts + +A hook script is invoked by the OS during startup and installation to execute the actions defined in the script. The directory for storing hook scripts of imageTailor is **custom/cfg_openEuler/usr_install/hook directory**, which has different subdirectories. Each subdirectory represents an OS startup or installation phase. Store the scripts based on the phases in which the scripts are invoked. + +##### Script Naming Rule + +The script name must start with **S+number** (the number must be at least two digits). The number indicates the execution sequence of the hook script. Example: **S01xxx.sh** + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>The scripts in the **hook** directory are executed using the `source` command. Therefore, exercise caution when using the `exit` command in the scripts because the entire installation script exits after the `exit` command is executed. + + + +##### Description of hook Subdirectories + +| Subdirectory | Script Example | Time for Execution | Description | +| :-------------------- | :---------------------| :------------------------------- | :----------------------------------------------------------- | +| insmod_drv_hook | N/A | After OS drivers are loaded | N/A | +| custom_install_hook | S01custom_install.sh | After the drivers are loaded, that is, after **insmod_drv_hook** is executed| You can customize the OS installation process by using a custom script.| +| env_check_hook | S01check_hw.sh | Before the OS installation initialization | The script is used to check hardware specifications and types before initialization.| +| set_install_ip_hook | S01set_install_ip.sh | When network configuration is being performed during OS installation initialization. | You can customize the network configuration by using a custom script.| +| before_partition_hook | S01checkpart.sh | Before partitioning | You can check correctness of the partition configuration file by using a custom script.| +| before_setup_os_hook | N/A | Before the repo file is decompressed | You can customize partition mounting.
If the decompression path of the installation package is not the root partition specified in the partition configuration, customize partition mounting and assign the decompression path to the input global variable.| +| before_mkinitrd_hook | S01install_drv.sh | Before the `mkinitrd` command is run | The hook script executed before running the `mkinitrd` command when **initrd** is saved to the disk. You can add and update driver files in **initrd**.| +| after_setup_os_hook | N/A | After OS installation | After the installation is complete, you can perform custom operations on the system files, such as modifying **grub.cfg**.| +| install_succ_hook | N/A | When the OS is successfully installed | The scripts in this subdirectory are used to parse the installation information and send information of whether the installation succeeds.**install_succ_hook** cannot be set to **install_break**.| +| install_fail_hook | N/A | When the OS installation fails | The scripts in this subdirectory are used to parse the installation information and send information of whether the installation succeeds.**install_fail_hook** cannot be set to **install_break**.| + +### Configuring System Parameters + +Before creating an ISO image, you need to configure system parameters, including host parameters, initial passwords, partitions, network, compilation parameters, and system command line parameters. + +#### Configuring Host Parameters + + The **\ \** section in the **/opt/imageTailor/custom/cfg_openEuler/sys.conf** file is used to configure common system parameters, such as the host name and kernel boot parameters. + +The default configuration provided by openEuler is as follows. You can modify the configuration as required. + +```shell + + sys_service_enable='ipcc' + sys_service_disable='cloud-config cloud-final cloud-init-local cloud-init' + sys_utc='yes' + sys_timezone='' + sys_cut='no' + sys_usrrpm_cut='no' + sys_hostname='Euler' + sys_usermodules_autoload='' + sys_gconv='GBK' + +``` + +The parameters are described as follows: + +- sys_service_enable + + This parameter is optional. Services enabled by the OS by default. Separate multiple services with spaces. If you do not need to add a system service, use the default value **ipcc**. Pay attention to the following during the configuration: + + - Default system services cannot be deleted. + - You can configure service-related services, but the repo source must contain the service RPM package. + - By default, only the services configured in this parameter are enabled. If a service depends on other services, you need to configure the depended services in this parameter. + +- sys_service_disable + + This parameter is optional. Services that are not allowed to automatically start upon system startup. Separate multiple services with spaces. If no system service needs to be disabled, leave this parameter blank. + +- sys_utc + + (Mandatory) Indicates whether to use coordinated universal time (UTC) time. The value can be **yes** or **no**. The default value is **yes**. + +- sys_timezone + + This parameter is optional. Sets the time zone. The value can be a time zone supported by openEuler, which can be queried in the **/usr/share/zoneinfo/zone.tab** file. + +- sys_cut + + (Mandatory) Indicates whether to tailor the RPM packages. The value can be **yes**, **no**, or **debug**.**yes** indicates that the RPM packages are tailored. **no** indicates that the RPM packages are not tailored (only the RPM packages in the **rpm.conf** file is installed). **debug** indicates that the RPM packages are tailored but the `rpm` command is retained for customization after installation. The default value is **no**. + + >![](./public_sys-resources/icon-note.gif) NOTE: + > + > - imageTailor installs the RPM package added by the user, deletes the files configured in the **\** section of the **cmd.conf** file, and then deletes the commands, libraries, and drivers that are not configured in **cmd.conf** or **rpm.conf**. + > - When **sys_cut='yes'** is configured, imageTailor does not support the installation of the `rpm` command. Even if the `rpm` command is configured in the **rpm.conf** file, the configuration does not take effect. + +- sys_usrrpm_cut + + (Mandatory) Indicates whether to tailor the RPM packages added by users to the **/opt/imageTailor/custom/cfg_openEuler/usr_rpm** directory. The value can be **yes** or **no**. The default value is **no**. + + - **sys_usrrpm_cut='yes'**: imageTailor installs the RPM packages added by the user, deletes the file configured in the **\** section in the **cmd.conf** file, and then deletes the commands, libraries, and drivers that are not configured in **cmd.conf** or **rpm.conf**. + + - **sys_usrrpm_cut='no'**: imageTailor installs the RPM packages added by the user but does not delete the files in the RPM packages. + +- sys_hostname + + (Mandatory) Host name. After the OS is deployed in batches, you are advised to change the host name of each node to ensure that the host name of each node is unique. + + The host name must be a combination of letters, digits, and hyphens (-) and must start with a letter or digit. Letters are case sensitive. The value contains a maximum of 63 characters. The default value is **Euler**. + +- sys_usermodules_autoload + + (Optional) Driver loaded during system startup. When configuring this parameter, you do not need to enter the file extension **.ko**. If there are multiple drivers, separate them by space. By default, this parameter is left blank, indicating that no additional driver is loaded. + +- sys_gconv + + (Optional) This parameter is used to tailor **/usr/lib/gconv** and **/usr/lib64/gconv**. The options are as follows: + + - **null**/**NULL**: indicates that this parameter is not configured. If **sys_cut='yes'** is configured, **/usr/lib/gconv** and **/usr/lib64/gconv** will be deleted. + - **all**/**ALL**: keeps **/usr/lib/gconv** and **/usr/lib64/gconv**. + - **xxx,xxx**: keeps the corresponding files in the **/usr/lib/gconv** and **/usr/lib64/gconv** directories. If multiple files need to be kept, use commas (,) to separate them. + +- sys_man_cut + + (Optional) Indicates whether to tailor the man pages. The value can be **yes** or **no**. The default value is **yes**. + + + +>![](./public_sys-resources/icon-note.gif) NOTE: +> +> If both **sys_cut** and **sys_usrrpm_cut** are configured, **sys_cut** is used. The following rules apply: +> +> - sys_cut='no' +> +> No matter whether **sys_usrrpm_cut** is set to **yes** or **no**, the system RPM package tailoring granularity is used. That is, imageTailor installs the RPM packages in the repo source and the RPM packages in the **usr_rpm** directory, however, the files in the RPM package are not deleted. Even if some files in the RPM packages are not required, imageTailor will delete them. +> +> - sys_cut='yes' +> +> - sys_usrrpm_cut='no' +> +> System RPM package tailoring granularity: imageTailor deletes files in the RPM packages in the repo sources as configured. +> +> - sys_usrrpm_cut='yes' +> +> System and user RPM package tailoring granularity: imageTailor deletes files in the RPM packages in the repo sources and the **usr_rpm** directory as configured. +> + + + +#### Configuring Initial Passwords + +The **root** and GRUB passwords must be configured during OS installation. Otherwise, you cannot log in to the OS as the **root** user after the OS is installed using the tailored ISO image. This section describes how to configure the initial passwords. + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> You must configure the initial **root** and GRUB passwords manually. + +##### Configuring the Initial Password of the root User + +###### Introduction + +The initial password of the **root** user is stored in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file. You can modify this file to set the initial password of the **root** user. + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- If the `--minios yes/force` parameter is required when you run the `mkdliso` command to create an ISO image, you need to enter the corresponding information in the **/opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf** file. + +The default configuration of the initial password of the **root** user in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file is as follows. Add a password of your choice. + +``` + + + +``` + +The parameters are described as follows: + +- **group**: group to which the user belongs. +- **pwd**: ciphertext of the initial password. The encryption algorithm is SHA-512. Replace **${pwd}** with the actual ciphertext. +- **home**: home directory of the user. +- **name**: name of the user to be configured. + +###### Modification Method + +Before creating an ISO image, you need to change the initial password of the **root** user. The following describes how to set the initial password of the **root** user (**root** permissions are required): + +1. Add a user for generating a password, for example, **testUser**. + + ```shell + $ sudo useradd testUser + ``` + +2. Set the password of **testUser**. Run the following command and set the password as prompted: + + ```shell + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. View the **/etc/shadow** file. The content following **testUser** (string between two colons) is the ciphertext of the password. + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:$6$YkX5uFDGVO1VWbab$jvbwkZ2Kt0MzZXmPWy.7bJsgmkN0U2gEqhm9KqT1jwQBlwBGsF3Z59heEXyh8QKm3Qhc5C3jqg2N1ktv25xdP0:19052:0:90:7:35:: + ``` + +4. Copy and paste the ciphertext to the **pwd** field in the **/opt/imageTailor/custom/cfg_openEuler/rpm.conf** file. + ``` shell script + + + + ``` + +5. If the `--minios yes/force` parameter is required when you run the `mkdliso` command to create an ISO image, configure the **pwd** field of the corresponding user in **/opt/imageTailor/kiwi/minios/cfg_minios/rpm.conf**. + + ``` shell script + + + + ``` + +##### Configuring the Initial GRUB Password + +The initial GRUB password is stored in the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file. Modify this file to configure the initial GRUB password. If the initial GRUB password is not configured, the ISO image will fail to be created. + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The **root** permissions are required for configuring the initial GRUB password. +> - The default user corresponding to the GRUB password is **root**. +> +> - The `grub2-set-password` command must exist in the system. If the command does not exist, install it in advance. + +1. Run the following command and set the GRUB password as prompted: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. After the command is executed, the **user.cfg** file is generated in the current directory. The content starting with **grub.pbkdf2.sha512** is the encrypted GRUB password. + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615 + ``` + +3. Copy the preceding ciphertext and add the following configuration to the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file: + + ```shell + GRUB_PASSWORD="grub.pbkdf2.sha512.10000.CE285BE1DED0012F8B2FB3DEA38782A5B1040FEC1E49D5F602285FD6A972D60177C365F1 + B5D4CB9D648AD4C70CF9AA2CF9F4D7F793D4CE008D9A2A696A3AF96A.0AF86AB3954777F40D324816E45DD8F66CA1DE836DC7FBED053DB02 + 4456EE657350A27FF1E74429546AD9B87BE8D3A13C2E686DD7C71D4D4E85294B6B06E0615" + ``` + + +#### Configuring Partitions + +If you want to adjust system partitions or service partitions, modify the **\** section in the **/opt/imageTailor/custom/cfg_openEuler/sys.conf** file. + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- System partition: partition for storing the OS. +>- Service partition: partition for service data. +>- The type of a partition is determined by the content it stores, not the size, mount path, or file system. +>- Partition configuration is optional. You can manually configure partitions after OS installation. + + The format of **\** is as follows: + +disk_ID mount _path partition _size partition_type file_system [Secondary formatting flag] + +The default configuration is as follows: + +``` shell script + +hd0 /boot 512M primary ext4 yes +hd0 /boot/efi 200M primary vfat yes +hd0 / 30G primary ext4 +hd0 - - extended - +hd0 /var 1536M logical ext4 +hd0 /home max logical ext4 + +``` + +The parameters are described as follows: + +- disk_ID: + ID of a disk. Set this parameter in the format of **hd***x*, where *x* indicates the *x*th disk. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >Partition configuration takes effect only when the disk can be recognized. + +- mount_path: + Mount path to a specified partition. You can configure service partitions and adjust the default system partition. If you do not mount partitions, set this parameter to **-**. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >- You must configure the mount path to **/**. You can adjust mount paths to other partitions according to your needs. + >- When the UEFI boot mode is used, the partition configuration in the x86_64 architecture must contain the mount path **/boot**, and the partition configuration in the AArch64 architecture must contain the mount path **/boot/efi**. + +- partition_size: + The value types are as follows: + + - G/g: The unit of a partition size is GB, for example, 2G. + - M/m: The unit of a partition size is MB, for example, 300M. + - T/t: The unit of a partition size is TB, for example, 1T. + - MAX/max: The rest space of a hard disk is used to create a partition. This value can only be assigned to the last partition. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** +> + >- A partition size value cannot contain decimal numbers. If there are decimal numbers, change the unit of the value to make the value an integer. For example, 1.5 GB should be changed to 1536 MB. + >- When the partition size is set to **MAX**/**max**, the size of the remaining partition cannot exceed the limit of the supported file system type (the default file system type is **ext4**, and the maximum size is **16T**). + +- partition_type: + The values of partition types are as follows: + + - primary: primary partitions + - extended: extended partition (configure only *disk_ID* for this partition) + - logical: logical partitions + +- file_system: + Currently, **ext4** and **vfat** file systems are supported. + +- [Secondary formatting flag]: + Indicates whether to format the disk during secondary installation. This parameter is optional. + + - The value can be **yes** or **no**. The default value is **no**. + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >Secondary formatting indicates that openEuler has been installed on the disk before this installation. If the partition table configuration (partition size, mount point, and file type) used in the previous installation is the same as that used in the current installation, this flag can be used to configure whether to format the previous partitions, except the **/boot** and **/** partitions. If the target host is installed for the first time, this flag does not take effect, and all partitions with specified file systems are formatted. + +#### Configuring the Network + +The system network parameters are stored in **/opt/imageTailor/custom/cfg_openEuler/sys.conf**. You can modify the network parameters of the target ISO image, such as the NIC name, IP address, and subnet mask, by configuring **\\** in this file. + +The default network configuration in the **sys.conf** file is as follows. **netconfig-0** indicates the **eth0** NIC. If you need to configure an additional NIC, for example, **eth1**, add **\\** to the configuration file and set the parameters of **eth1**. + +```shell + +BOOTPROTO="dhcp" +DEVICE="eth0" +IPADDR="" +NETMASK="" +STARTMODE="auto" + +``` + +The following table describes the parameters. + +- | Parameter | Mandatory or Not| Value | Description | + | :-------- | -------- | :------------------------------------------------ | :----------------------------------------------------------- | + | BOOTPROTO | Yes | none / static / dhcp | **none**: No protocol is used for boot, and no IP address is assigned.
**static**: An IP address is statically assigned.
**dhcp**: An IP address is dynamically obtained using the dynamic host configuration protocol (DHCP).| + | DEVICE | Yes | Example: **eth1** | NIC name. | + | IPADDR | Yes | Example: **192.168.11.100** | IP address.
This parameter must be configured only when the value of **BOOTPROTO** is **static**.| + | NETMASK | Yes | - | Subnet mask.
This parameter must be configured only when the value of **BOOTPROTO** is **static**.| + | STARTMODE | Yes | manual / auto / hotplug / ifplugd / nfsroot / off | NIC start mode.
**manual**: A user runs the `ifup` command on a terminal to start an NIC.
**auto**/**hotplug**/**ifplug**/**nfsroot**: An NIC is started when the OS identifies it.
**off**: An NIC cannot be started in any situations.
For details about the parameters, run the `man ifcfg` command on the host that is used to create the ISO image.| + + +#### Configuring Kernel Parameters + +To ensure stable and efficient running of the system, you can modify kernel command line parameters as required. For an OS image created by imageTailor, you can modify the **GRUB_CMDLINE_LINUX** configuration in the **/opt/imageTailor/custom/cfg_openEuler/usr_file/etc/default/grub** file to modify the kernel command line parameters. The default settings of the kernel command line parameters in **GRUB_CMDLINE_LINUX** are as follows: + +```shell +GRUB_CMDLINE_LINUX="net.ifnames=0 biosdevname=0 crashkernel=512M oops=panic softlockup_panic=1 reserve_kbox_mem=16M crash_kexec_post_notifiers panic=3 console=tty0" +``` + +The meanings of the configurations are as follows (for details about other common kernel command line parameters, see related kernel documents): + +- net.ifnames=0 biosdevname=0 + + Name the NIC in traditional mode. + +- crashkernel=512M + + The memory space reserved for kdump is 512 MB. + +- oops=panic panic=3 + + The kernel panics when an oops error occurs, and the system restarts 3 seconds later. + +- softlockup_panic=1 + + The kernel panics when a soft-lockup is detected. + +- reserve_kbox_mem=16M + + The memory space reserved for Kbox is 16 MB. + +- console=tty0 + + Specifies **tty0** as the output device of the first virtual console. + +- crash_kexec_post_notifiers + + After the system crashes, the function registered with the panic notification chain is called first, and then kdump is executed. + +### Creating an Image + +After customizing the operating system, you can use the `mkdliso` script to create the OS image file. The OSimage created using imageTailor is an ISO image file. + +#### Command Description + +##### Syntax + +**mkdliso -p openEuler -c custom/cfg_openEuler [--minios yes|no|force] [--sec] [-h]** + +##### Parameter Description + +| Parameter| Mandatory| Description | Value Range | +| -------- | -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | +| -p | Yes | Specifies the product name. | **openEuler** | +| c | Yes | Specifies the relative path of the configuration file. | **custom/cfg_openEuler** | +| --minios | No | Specifies whether to create the **initrd** file that is used to boot the system during system installation. | The default value is **yes**.
**yes**: The **initrd** file will be created when the command is executed for the first time. When a subsequent `mkdliso` is executed, the system checks whether the **initrd** file exists in the **usr_install/boot** directory using sha256 verification. If the **initrd** file exists, it is not created again. Otherwise, it is created.
**no**: The **initrd** file is not created. The **initrd** file used for system boot and running is the same.
**force**: The **initrd** file will be created forcibly, regardless of whether it exists in the **usr_install/boot** directory or not.| +| --sec | No | Specifies whether to perform security hardening on the generated ISO file.
If this parameter is not specified, the user should undertake the resultant security risks| N/A | +| -h | No | Obtains help information. | N/A | + +#### Image Creation Guide + +To create an ISO image using`mkdliso`, perform the following steps: + +>![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The absolute path to `mkdliso` must not contain spaces. Otherwise, the ISO image creation will fail. +> - In the environment for creating the ISO image, the value of **umask** must be set to **0022**. + +1. Run the `mkdliso` command as the **root** user to generate the ISO image file. The following command is used for reference: + + ```shell + # sudo /opt/imageTailor/mkdliso -p openEuler -c custom/cfg_openEuler --sec + ``` + + After the command is executed, the created files are stored in the **/opt/imageTailor/result/{date}** directory, including **openEuler-aarch64.iso** and **openEuler-aarch64.iso.sha256**. + +2. Verify the integrity of the ISO image file. Assume that the date and time is **2022-03-21-14-48**. + + ```shell + $ cd /opt/imageTailor/result/2022-03-21-14-48/ + $ sha256sum -c openEuler-aarch64.iso.sha256 + ``` + + If the following information is displayed, the ISO image creation is complete. + + ``` + openEuler-aarch64.iso: OK + ``` + + If the following information is displayed, the image is incomplete. The ISO image file is damaged and needs to be created again. + + ```shell + openEuler-aarch64.iso: FAILED + sha256sum: WARNING: 1 computed checksum did NOT match + ``` + +3. View the logs. + + After an image is created, you can view logs as required (for example, when an error occurs during image creation). When an image is created for the first time, the corresponding log file and security hardening log file are compressed into a TAR package (the log file is named in the format of **sys_custom_log_{Date}.tar.gz**) and stored in the **result/log directory**. Only the latest 50 compressed log packages are stored in this directory. If the number of compressed log packages exceeds 50, the earliest files will be overwritten. + + + +### Tailoring Time Zones + +After the customized ISO image is installed, you can tailor the time zones supported by the openEuler system as required. This section describes how to tailor the time zones. + +The information about time zones supported by openEuler is stored in the time zone folder **/usr/shre/zoninfo**. You can run the following command to view the time zone information: + +```shell +$ ls /usr/share/zoneinfo/ +Africa/ America/ Asia/ Atlantic/ Australia/ Etc/ Europe/ +Pacific/ zone.tab +``` + +Each subfolder represents an area. The current areas include continents, oceans, and **Etc**. Each area folder contains the locations that belong to it. Generally, a location is a city or an island. + +All time zones are in the format of *area/location*. For example, if China Standard Time is used in southern China, the time zone is Asia/Shanghai (location may not be the capital). The corresponding time zone file is: + +``` +/usr/share/zoneinfo/Asia/Shanghai +``` + +If you want to tailor some time zones, delete the corresponding time zone files. + +### Customization Example + +This section describes how to use imageTailor to create an ISO image. + +1. Check whether the environment used to create the ISO meets the requirements. + + ``` shell + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. Ensure that the root directory has at least 40 GB free space. + + ```shell + $ df -h + Filesystem Size Used Avail Use% Mounted on + ...... + /dev/vdb 196G 28K 186G 1% / + ``` + +3. Install the imageTailor tailoring tool. For details, see [Installation](#installation). + + ```shell + $ sudo yum install -y imageTailor + $ ll /opt/imageTailor/ + total 88K + drwxr-xr-x. 3 root root 4.0K Mar 3 08:00 custom + drwxr-xr-x. 10 root root 4.0K Mar 3 08:00 kiwi + -r-x------. 1 root root 69K Mar 3 08:00 mkdliso + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 repos + drwxr-xr-x. 2 root root 4.0K Mar 9 14:48 security-tool + ``` + +4. Configure a local repo source. + + ```shell + $ wget https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + $ sudo mkdir -p /opt/openEuler_repo + $ sudo mount openEuler-22.03-LTS-everything-aarch64-dvd.iso /opt/openEuler_repo + mount: /opt/openEuler_repo: WARNING: source write-protected, mounted read-only. + $ sudo rm -rf /opt/imageTailor/repos/euler_base && sudo mkdir -p /opt/imageTailor/repos/euler_base + $ sudo cp -ar /opt/openEuler_repo/Packages/* /opt/imageTailor/repos/euler_base + $ sudo chmod -R 644 /opt/imageTailor/repos/euler_base + $ sudo ls /opt/imageTailor/repos/euler_base|wc -l + 2577 + $ sudo umount /opt/openEuler_repo && sudo rm -rf /opt/openEuler_repo + $ cd /opt/imageTailor + ``` + +5. Change the **root** and GRUB passwords. + + Replace **\${pwd}** with the encrypted password by referring to [Configuring Initial Passwords](#configuring-initial-passwords). + + ```shell + $ cd /opt/imageTailor/ + $ sudo vi custom/cfg_openEuler/usr_file/etc/default/grub + GRUB_PASSWORD="${pwd1}" + $ + $ sudo vi kiwi/minios/cfg_minios/rpm.conf + + + + $ + $ sudo vi custom/cfg_openEuler/rpm.conf + + + + ``` + +6. Run the tailoring command. + + ```shell + $ sudo rm -rf /opt/imageTailor/result + $ sudo ./mkdliso -p openEuler -c custom/cfg_openEuler --minios force + ...... + Complete release iso file at: result/2022-03-09-15-31/openEuler-aarch64.iso + move all mkdliso log file to result/log/sys_custom_log_20220309153231.tar.gz + $ ll result/2022-03-09-15-31/ + total 889M + -rw-r--r--. 1 root root 889M Mar 9 15:32 openEuler-aarch64.iso + -rw-r--r--. 1 root root 87 Mar 9 15:32 openEuler-aarch64.iso.sha256 + ``` diff --git a/docs/en/docs/Virtualization/installation-to-virtualization.md b/docs/en/docs/Virtualization/virtualization-installation.md similarity index 100% rename from docs/en/docs/Virtualization/installation-to-virtualization.md rename to docs/en/docs/Virtualization/virtualization-installation.md diff --git a/docs/en/docs/desktop/kubesphere.md b/docs/en/docs/desktop/kubesphere.md index 32baa2eb1..40a47a96f 100644 --- a/docs/en/docs/desktop/kubesphere.md +++ b/docs/en/docs/desktop/kubesphere.md @@ -1,4 +1,4 @@ -# KubeSphere Installation Guide +# KubeSphere Deployment Guide This document describes how to install and deploy Kubernetes and KubeSphere clusters on openEuler 21.09. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-train.md b/docs/en/docs/thirdparty_migration/OpenStack-train.md new file mode 100644 index 000000000..0816483f0 --- /dev/null +++ b/docs/en/docs/thirdparty_migration/OpenStack-train.md @@ -0,0 +1,2961 @@ +# OpenStack-Wallaby Deployment Guide + + + +- [OpenStack-Wallaby Deployment Guide](#openstack-wallaby-deployment-guide) + - [OpenStack](#openstack) + - [Conventions](#conventions) + - [Preparing the Environment](#preparing-the-environment) + - [Environment Configuration](#environment-configuration) + - [Installing the SQL Database](#installing-the-sql-database) + - [Installing RabbitMQ](#installing-rabbitmq) + - [Installing Memcached](#installing-memcached) + - [OpenStack Installation](#openstack-installation) + - [Installing Keystone](#installing-keystone) + - [Installing Glance](#installing-glance) + - [Installing Placement](#installing-placement) + - [Installing Nova](#installing-nova) + - [Installing Neutron](#installing-neutron) + - [Installing Cinder](#installing-cinder) + - [Installing Horizon](#installing-horizon) + - [Installing Tempest](#installing-tempest) + - [Installing Ironic](#installing-ironic) + - [Installing Kolla](#installing-kolla) + - [Installing Trove](#installing-trove) + - [Installing Swift](#installing-swift) + - [Installing Cyborg](#installing-cyborg) + - [Installing Aodh](#installing-aodh) + - [Installing Gnocchi](#installing-gnocchi) + - [Installing Ceilometer](#installing-ceilometer) + - [Installing Heat](#installing-heat) + - [OpenStack Quick Installation](#openstack-quick-installation) + + +## OpenStack + +OpenStack is an open source cloud computing infrastructure software project developed by the community. It provides an operating platform or tool set for deploying the cloud, offering scalable and flexible cloud computing for organizations. + +As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. + +The official source of openEuler 20.03-LTS-SP3 now supports OpenStack Train. You can configure the Yum source then deploy OpenStack by following the instructions of this document. + +## Conventions + +OpenStack supports multiple deployment modes. This document includes two deployment modes: **All in One** and **Distributed**. The conventions are as follows: + +**All in One** mode: + +```text +Ignores all possible suffixes. +``` + +**Distributed** mode: + +```text +A suffix of (CTL) indicates that the configuration or command applies only to the control node. +A suffix of (CPT) indicates that the configuration or command applies only to the compute node. +A suffix of (STG) indicates that the configuration or command applies only to the storage node. +In other cases, the configuration or command applies to both the control node and compute node. +``` + +***Note*** + +The services involved in the preceding conventions are as follows: + +- Cinder +- Nova +- Neutron + +## Preparing the Environment + +### Environment Configuration + +1. Start the OpenStack Train Yum source. + + ```shell + yum update + yum install openstack-release-train + yum clean all && yum makecache + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + ``` + +2. Change the host name and mapping. + + Set the host name of each node: + + ```shell + hostnamectl set-hostname controller (CTL) + hostnamectl set-hostname compute (CPT) + ``` + + Assuming the IP address of the controller node is **10.0.0.11** and the IP address of the compute node (if any) is **10.0.0.12**, add the following information to the **/etc/hosts** file: + + ```shell + 10.0.0.11 controller + 10.0.0.12 compute + ``` + +### Installing the SQL Database + +1. Run the following command to install the software package: + + ```shell + yum install mariadb mariadb-server python3-PyMySQL + ``` + +2. Run the following command to create and edit the **/etc/my.cnf.d/openstack.cnf** file: + + ```shell + vim /etc/my.cnf.d/openstack.cnf + + [mysqld] + bind-address = 10.0.0.11 + default-storage-engine = innodb + innodb_file_per_table = on + max_connections = 4096 + collation-server = utf8_general_ci + character-set-server = utf8 + ``` + + ***Note*** + + **`bind-address` is set to the management IP address of the controller node.** + +3. Run the following commands to start the database service and configure it to automatically start upon system boot: + + ```shell + systemctl enable mariadb.service + systemctl start mariadb.service + ``` + +4. (Optional) Configure the default database password: + + ```shell + mysql_secure_installation + ``` + + ***Note*** + + **Perform operations as prompted.** + +### Installing RabbitMQ + +1. Run the following command to install the software package: + + ```shell + yum install rabbitmq-server + ``` + +2. Start the RabbitMQ service and configure it to automatically start upon system boot: + + ```shell + systemctl enable rabbitmq-server.service + systemctl start rabbitmq-server.service + ``` + +3. Add the OpenStack user: + + ```shell + rabbitmqctl add_user openstack RABBIT_PASS + ``` + + ***Note*** + + **Replace *RABBIT_PASS* to set the password for the openstack user.** + +4. Run the following command to set the permission of the **openstack** user to allow the user to perform configuration, write, and read operations: + + ```shell + rabbitmqctl set_permissions openstack ".*" ".*" ".*" + ``` + +### Installing Memcached + +1. Run the following command to install the dependency package: + + ```shell + yum install memcached python3-memcached + ``` + +2. Open the **/etc/sysconfig/memcached** file in insert mode. + + ```shell + vim /etc/sysconfig/memcached + + OPTIONS="-l 127.0.0.1,::1,controller" + ``` + +3. Run the following command to start the Memcached service and configure it to automatically start upon system boot: + + ```shell + systemctl enable memcached.service + systemctl start memcached.service + ``` + + ***Note*** + + **After the service is started, you can run `memcached-tool controller stats` to ensure that the service is started properly and available. You can replace `controller` with the management IP address of the controller node.** + +## OpenStack Installation + +### Installing Keystone + +1. Create the **keystone** database and grant permissions: + + ``` sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE keystone; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ + IDENTIFIED BY 'KEYSTONE_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ + IDENTIFIED BY 'KEYSTONE_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *KEYSTONE_DBPASS* to set the password for the keystone database.** + +2. Install the software package: + + ```shell + yum install openstack-keystone httpd mod_wsgi + ``` + +3. Configure Keystone: + + ```shell + vim /etc/keystone/keystone.conf + + [database] + connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone + + [token] + provider = fernet + ``` + + ***Description*** + + In the **[database]** section, configure the database entry . + + In the **[token]** section, configure the token provider . + + ***Note:*** + + **Replace *KEYSTONE_DBPASS* with the password of the keystone database.** + +4. Synchronize the database: + + ```shell + su -s /bin/sh -c "keystone-manage db_sync" keystone + ``` + +5. Initialize the Fernet keystore: + + ```shell + keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone + keystone-manage credential_setup --keystone-user keystone --keystone-group keystone + ``` + +6. Start the service: + + ```shell + keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ + --bootstrap-admin-url http://controller:5000/v3/ \ + --bootstrap-internal-url http://controller:5000/v3/ \ + --bootstrap-public-url http://controller:5000/v3/ \ + --bootstrap-region-id RegionOne + ``` + + ***Note*** + + **Replace *ADMIN_PASS* to set the password for the admin user.** + +7. Configure the Apache HTTP server: + + ```shell + vim /etc/httpd/conf/httpd.conf + + ServerName controller + ``` + + ```shell + ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ + ``` + + ***Description*** + + Configure **ServerName** to use the control node. + + ***Note*** + **If the ServerName item does not exist, create it. + +8. Start the Apache HTTP service: + + ```shell + systemctl enable httpd.service + systemctl start httpd.service + ``` + +9. Create environment variables: + + ```shell + cat << EOF >> ~/.admin-openrc + export OS_PROJECT_DOMAIN_NAME=Default + export OS_USER_DOMAIN_NAME=Default + export OS_PROJECT_NAME=admin + export OS_USERNAME=admin + export OS_PASSWORD=ADMIN_PASS + export OS_AUTH_URL=http://controller:5000/v3 + export OS_IDENTITY_API_VERSION=3 + export OS_IMAGE_API_VERSION=2 + EOF + ``` + + ***Note*** + + **Replace *ADMIN_PASS* with the password of the admin user.** + +10. Create domains, projects, users, and roles in sequence. python3-openstackclient must be installed first: + + ```shell + yum install python3-openstackclient + ``` + + Import the environment variables: + + ```shell + source ~/.admin-openrc + ``` + + Create the project **service**. The domain **default** has been created during keystone-manage bootstrap. + + ```shell + openstack domain create --description "An Example Domain" example + ``` + + ```shell + openstack project create --domain default --description "Service Project" service + ``` + + Create the (non-admin) project **myproject**, user **myuser**, and role **myrole**, and add the role **myrole** to **myproject** and **myuser**. + + ```shell + openstack project create --domain default --description "Demo Project" myproject + openstack user create --domain default --password-prompt myuser + openstack role create myrole + openstack role add --project myproject --user myuser myrole + ``` + +11. Perform the verification. + + Cancel the temporary environment variables **OS_AUTH_URL** and **OS_PASSWORD**. + + ```shell + source ~/.admin-openrc + unset OS_AUTH_URL OS_PASSWORD + ``` + + Request a token for the **admin** user: + + ```shell + openstack --os-auth-url http://controller:5000/v3 \ + --os-project-domain-name Default --os-user-domain-name Default \ + --os-project-name admin --os-username admin token issue + ``` + + Request a token for user **myuser**: + + ```shell + openstack --os-auth-url http://controller:5000/v3 \ + --os-project-domain-name Default --os-user-domain-name Default \ + --os-project-name myproject --os-username myuser token issue + ``` + +### Installing Glance + +1. Create the database, service credentials, and the API endpoints. + + Create the database: + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE glance; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ + IDENTIFIED BY 'GLANCE_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ + IDENTIFIED BY 'GLANCE_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note:*** + + **Replace *GLANCE_DBPASS* to set the password for the glance database.** + + Create the service credential: + + ```shell + source ~/.admin-openrc + + openstack user create --domain default --password-prompt glance + openstack role add --project service --user glance admin + openstack service create --name glance --description "OpenStack Image" image + ``` + + Create the API endpoints for the image service: + + ```shell + openstack endpoint create --region RegionOne image public http://controller:9292 + openstack endpoint create --region RegionOne image internal http://controller:9292 + openstack endpoint create --region RegionOne image admin http://controller:9292 + ``` + +2. Install the software package: + + ```shell + yum install openstack-glance + ``` + +3. Configure Glance: + + ```shell + vim /etc/glance/glance-api.conf + + [database] + connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = glance + password = GLANCE_PASS + + [paste_deploy] + flavor = keystone + + [glance_store] + stores = file,http + default_store = file + filesystem_store_datadir = /var/lib/glance/images/ + ``` + + ***Description:*** + + In the **[database]** section, configure the database entry. + + In the **[keystone_authtoken]** and **[paste_deploy]** sections, configure the identity authentication service entry. + + In the **[glance_store]** section, configure the local file system storage and the location of image files. + + ***Note*** + + **Replace *GLANCE_DBPASS* with the password of the glance database.** + + **Replace *GLANCE_PASS* with the password of user glance.** + +4. Synchronize the database: + + ```shell + su -s /bin/sh -c "glance-manage db_sync" glance + ``` + +5. Start the service: + + ```shell + systemctl enable openstack-glance-api.service + systemctl start openstack-glance-api.service + ``` + +6. Perform the verification. + + Download the image: + + ```shell + source ~/.admin-openrc + + wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img + ``` + + ***Note*** + + **If the Kunpeng architecture is used in your environment, download the image of the AArch64 version. the cirros-0.5.2-aarch64-disk.img image file has been tested.** + + Upload the image to the image service: + + ```shell + openstack image create --disk-format qcow2 --container-format bare \ + --file cirros-0.4.0-x86_64-disk.img --public cirros + ``` + + Confirm the image upload and verify the attributes: + + ```shell + openstack image list + ``` + +### Installing Placement + +1. Create a database, service credentials, and API endpoints. + + Create a database. + + Access the database as the **root** user. Create the **placement** database, and grant permissions. + + ```shell + mysql -u root -p + MariaDB [(none)]> CREATE DATABASE placement; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ + IDENTIFIED BY 'PLACEMENT_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ + IDENTIFIED BY 'PLACEMENT_DBPASS'; + MariaDB [(none)]> exit + ``` + + **Note**: + + **Replace *PLACEMENT_DBPASS* to set the password for the placement database.** + + ```shell + source admin-openrc + ``` + + Run the following commands to create the Placement service credentials, create the **placement** user, and add the **admin** role to the **placement** user: + + Create the Placement API Service. + + ```shell + openstack user create --domain default --password-prompt placement + openstack role add --project service --user placement admin + openstack service create --name placement --description "Placement API" placement + ``` + + Create API endpoints of the **placement** service. + + ```shell + openstack endpoint create --region RegionOne placement public http://controller:8778 + openstack endpoint create --region RegionOne placement internal http://controller:8778 + openstack endpoint create --region RegionOne placement admin http://controller:8778 + ``` + +2. Perform the installation and configuration. + + Install the software package: + + ```shell + yum install openstack-placement-api + ``` + + Configure Placement: + + Edit the **/etc/placement/placement.conf** file: + + In the **[placement_database]** section, configure the database entry. + + In **[api]** and **[keystone_authtoken]** sections, configure the identity authentication service entry. + + ```shell + # vim /etc/placement/placement.conf + [placement_database] + # ... + connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement + [api] + # ... + auth_strategy = keystone + [keystone_authtoken] + # ... + auth_url = http://controller:5000/v3 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = placement + password = PLACEMENT_PASS + ``` + + Replace **PLACEMENT_DBPASS** with the password of the **placement** database, and replace **PLACEMENT_PASS** with the password of the **placement** user. + + Synchronize the database: + + ```shell + su -s /bin/sh -c "placement-manage db sync" placement + ``` + + Start the httpd service. + + ```shell + systemctl restart httpd + ``` + +3. Perform the verification. + + Run the following command to check the status: + + ```shell + . admin-openrc + placement-status upgrade check + ``` + + Run the following command to install osc-placement and list the available resource types and features: + + ```shell + yum install python3-osc-placement + openstack --os-placement-api-version 1.2 resource class list --sort-column name + openstack --os-placement-api-version 1.6 trait list --sort-column name + ``` + +### Installing Nova + +1. Create a database, service credentials, and API endpoints. + + Create a database. + + ```sql + mysql -u root -p (CTL) + + MariaDB [(none)]> CREATE DATABASE nova_api; + MariaDB [(none)]> CREATE DATABASE nova; + MariaDB [(none)]> CREATE DATABASE nova_cell0; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ + IDENTIFIED BY 'NOVA_DBPASS'; + MariaDB [(none)]> exit + ``` + + **Note**: + + **Replace *NOVA_DBPASS* to set the password for the nova database.** + + ```shell + source ~/.admin-openrc (CTL) + ``` + + Run the following command to create the Nova service certificate: + + ```shell + openstack user create --domain default --password-prompt nova (CTL) + openstack role add --project service --user nova admin (CTL) + openstack service create --name nova --description "OpenStack Compute" compute (CTL) + ``` + + Create a Nova API endpoint. + + ```shell + openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 (CTL) + openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 (CTL) + openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 (CTL) + ``` + +2. Install the software packages: + + ```shell + yum install openstack-nova-api openstack-nova-conductor \ (CTL) + openstack-nova-novncproxy openstack-nova-scheduler + + yum install openstack-nova-compute (CPT) + ``` + + **Note**: + + **If the ARM64 architecture is used, you also need to run the following command:** + + ```shell + yum install edk2-aarch64 (CPT) + ``` + +3. Configure Nova: + + ```shell + vim /etc/nova/nova.conf + + [DEFAULT] + enabled_apis = osapi_compute,metadata + transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ + my_ip = 10.0.0.1 + use_neutron = true + firewall_driver = nova.virt.firewall.NoopFirewallDriver + compute_driver=libvirt.LibvirtDriver (CPT) + instances_path = /var/lib/nova/instances/ (CPT) + lock_path = /var/lib/nova/tmp (CPT) + + [api_database] + connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api (CTL) + + [database] + connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova (CTL) + + [api] + auth_strategy = keystone + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000/ + auth_url = http://controller:5000/ + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = nova + password = NOVA_PASS + + [vnc] + enabled = true + server_listen = $my_ip + server_proxyclient_address = $my_ip + novncproxy_base_url = http://controller:6080/vnc_auto.html (CPT) + + [glance] + api_servers = http://controller:9292 + + [oslo_concurrency] + lock_path = /var/lib/nova/tmp (CTL) + + [placement] + region_name = RegionOne + project_domain_name = Default + project_name = service + auth_type = password + user_domain_name = Default + auth_url = http://controller:5000/v3 + username = placement + password = PLACEMENT_PASS + + [neutron] + auth_url = http://controller:5000 + auth_type = password + project_domain_name = default + user_domain_name = default + region_name = RegionOne + project_name = service + username = neutron + password = NEUTRON_PASS + service_metadata_proxy = true (CTL) + metadata_proxy_shared_secret = METADATA_SECRET (CTL) + ``` + + Description + + In the **[default]** section, enable the compute and metadata APIs, configure the RabbitMQ message queue entry, configure **my_ip**, and enable the network service **neutron**. + + In the **[api_database]** and **[database]** sections, configure the database entry. + + In the **[api]** and **[keystone_authtoken]** sections, configure the identity service entry. + + In the **[vnc]** section, enable and configure the entry for the remote console. + + In the **[glance]** section, configure the API address for the image service. + + In the **[oslo_concurrency]** section, configure the lock path. + + In the **[placement]** section, configure the entry of the Placement service. + + **Note**: + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Set *my_ip* to the management IP address of the controller node.** + + **Replace *NOVA_DBPASS* with the password of the nova database.** + + **Replace *NOVA_PASS* with the password of the nova user.** + + **Replace *PLACEMENT_PASS* with the password of the placement user.** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + + Others + + Check whether VM hardware acceleration (x86 architecture) is supported: + + ```shell + egrep -c '(vmx|svm)' /proc/cpuinfo (CPT) + ``` + + If the returned value is **0**, hardware acceleration is not supported. You need to configure libvirt to use QEMU instead of KVM. + + ```shell + vim /etc/nova/nova.conf (CPT) + + [libvirt] + virt_type = qemu + ``` + + If the returned value is **1** or a larger value, hardware acceleration is supported. You can set the value of **virt_type** to **kvm**. + + **Note**: + + **If the ARM64 architecture is used, you also need to run the following command on the compute node:** + + ```shell + + mkdir -p /usr/share/AAVMF + chown nova:nova /usr/share/AAVMF + + ln -s /usr/share/edk2/aarch64/QEMU_EFI-pflash.raw \ + /usr/share/AAVMF/AAVMF_CODE.fd + ln -s /usr/share/edk2/aarch64/vars-template-pflash.raw \ + /usr/share/AAVMF/AAVMF_VARS.fd + + vim /etc/libvirt/qemu.conf + + nvram = ["/usr/share/AAVMF/AAVMF_CODE.fd: \ + /usr/share/AAVMF/AAVMF_VARS.fd", \ + "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw: \ + /usr/share/edk2/aarch64/vars-template-pflash.raw"] + ``` + In addition, when the deployment environment in the ARM architecture is nested virtualization, configure the **[libvirt]** section as follows: + + ```shell + [libvirt] + virt_type = qemu + cpu_mode = custom + cpu_model = cortex-a72 + ``` + +4. Synchronize the database. + + Run the following command to synchronize the **nova-api** database: + + ```shell + su -s /bin/sh -c "nova-manage api_db sync" nova (CTL) + ``` + + Run the following command to register the **cell0** database: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova (CTL) + ``` + + Create the **cell1** cell: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova (CTL) + ``` + + Synchronize the **nova** database: + + ```shell + su -s /bin/sh -c "nova-manage db sync" nova (CTL) + ``` + + Verify whether **cell0** and **cell1** are correctly registered: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova (CTL) + ``` + + Add compute node to the OpenStack cluster: + + ```shell + su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova (CPT) + ``` + +5. Start the services: + + ```shell + systemctl enable \ (CTL) + openstack-nova-api.service \ + openstack-nova-scheduler.service \ + openstack-nova-conductor.service \ + openstack-nova-novncproxy.service + + systemctl start \ (CTL) + openstack-nova-api.service \ + openstack-nova-scheduler.service \ + openstack-nova-conductor.service \ + openstack-nova-novncproxy.service + ``` + + ```shell + systemctl enable libvirtd.service openstack-nova-compute.service (CPT) + systemctl start libvirtd.service openstack-nova-compute.service (CPT) + ``` + +6. Perform the verification. + + ```shell + source ~/.admin-openrc (CTL) + ``` + + List the service components to verify that each process is successfully started and registered: + + ```shell + openstack compute service list (CTL) + ``` + + List the API endpoints in the identity service to verify the connection to the identity service: + + ```shell + openstack catalog list (CTL) + ``` + + List the images in the image service to verify the connections: + + ```shell + openstack image list (CTL) + ``` + + Check whether the cells are running properly and whether other prerequisites are met. + + ```shell + nova-status upgrade check (CTL) + ``` + +### Installing Neutron + +1. Create the database, service credentials, and API endpoints. + + Create the database: + + ```sql + mysql -u root -p (CTL) + + MariaDB [(none)]> CREATE DATABASE neutron; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ + IDENTIFIED BY 'NEUTRON_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ + IDENTIFIED BY 'NEUTRON_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *NEUTRON_DBPASS* to set the password for the neutron database.** + + ```shell + source ~/.admin-openrc (CTL) + ``` + + Create the **neutron** service credential: + + ```shell + openstack user create --domain default --password-prompt neutron (CTL) + openstack role add --project service --user neutron admin (CTL) + openstack service create --name neutron --description "OpenStack Networking" network (CTL) + ``` + + Create the API endpoints of the Neutron service: + + ```shell + openstack endpoint create --region RegionOne network public http://controller:9696 (CTL) + openstack endpoint create --region RegionOne network internal http://controller:9696 (CTL) + openstack endpoint create --region RegionOne network admin http://controller:9696 (CTL) + ``` + +2. Install the software packages: + + ```shell + yum install openstack-neutron openstack-neutron-linuxbridge ebtables ipset \ (CTL) + openstack-neutron-ml2 + ``` + + ```shell + yum install openstack-neutron-linuxbridge ebtables ipset (CPT) + ``` + +3. Configure Neutron. + + Set the main configuration items: + + ```shell + vim /etc/neutron/neutron.conf + + [database] + connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron (CTL) + + [DEFAULT] + core_plugin = ml2 (CTL) + service_plugins = router (CTL) + allow_overlapping_ips = true (CTL) + transport_url = rabbit://openstack:RABBIT_PASS@controller + auth_strategy = keystone + notify_nova_on_port_status_changes = true (CTL) + notify_nova_on_port_data_changes = true (CTL) + api_workers = 3 (CTL) + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = neutron + password = NEUTRON_PASS + + [nova] + auth_url = http://controller:5000 (CTL) + auth_type = password (CTL) + project_domain_name = Default (CTL) + user_domain_name = Default (CTL) + region_name = RegionOne (CTL) + project_name = service (CTL) + username = nova (CTL) + password = NOVA_PASS (CTL) + + [oslo_concurrency] + lock_path = /var/lib/neutron/tmp + ``` + + ***Description*** + + Configure the database entry in the **[database]** section. + + Enable the ML2 and router plugins, allow IP address overlapping, and configure the RabbitMQ message queue entry in the **[default]** section. + + Configure the identity authentication service entry in the **[default]** and **[keystone]** sections. + + Enable the network to notify the change of the compute network topology in the **[default]** and **[nova]** sections. + + Configure the lock path in the **[oslo_concurrency]** section. + + ***Note*** + + **Replace *NEUTRON_DBPASS* with the password of the neutron database.** + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *NOVA_PASS* with the password of the nova user.** + + Configure the ML2 plugin: + + ```shell + vim /etc/neutron/plugins/ml2/ml2_conf.ini + + [ml2] + type_drivers = flat,vlan,vxlan + tenant_network_types = vxlan + mechanism_drivers = linuxbridge,l2population + extension_drivers = port_security + + [ml2_type_flat] + flat_networks = provider + + [ml2_type_vxlan] + vni_ranges = 1:1000 + + [securitygroup] + enable_ipset = true + ``` + + Create the symbolic link for /etc/neutron/plugin.ini. + + ```shell + ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini + ``` + + **Note** + + **Enable flat, vlan, and vxlan networks, enable the linuxbridge and l2population mechanisms, and enable the port security extension driver in the [ml2] section.** + + **Configure the flat network as the provider virtual network in the [ml2_type_flat] section.** + + **Configure the range of the VXLAN network identifier in the [ml2_type_vxlan] section.** + + **Set ipset enabled in the [securitygroup] section.** + + **Remarks** + + **The actual configurations of l2 can be modified based as required. In this example, the provider network + linuxbridge is used.** + + Configure the Linux bridge agent: + + ```shell + vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini + + [linux_bridge] + physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME + + [vxlan] + enable_vxlan = true + local_ip = OVERLAY_INTERFACE_IP_ADDRESS + l2_population = true + + [securitygroup] + enable_security_group = true + firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver + ``` + + ***Description*** + + Map the provider virtual network to the physical network interface in the **[linux_bridge]** section. + + Enable the VXLAN overlay network, configure the IP address of the physical network interface that processes the overlay network, and enable layer-2 population in the **[vxlan]** section. + + Enable the security group and configure the linux bridge iptables firewall driver in the **[securitygroup]** section. + + ***Note*** + + **Replace *PROVIDER_INTERFACE_NAME* with the physical network interface.** + + **Replace *OVERLAY_INTERFACE_IP_ADDRESS* with the management IP address of the controller node.** + + Configure the Layer-3 agent: + + ```shell + vim /etc/neutron/l3_agent.ini (CTL) + + [DEFAULT] + interface_driver = linuxbridge + ``` + + ***Description*** + + Set the interface driver to linuxbridge in the **[default]** section. + + Configure the DHCP agent: + + ```shell + vim /etc/neutron/dhcp_agent.ini (CTL) + + [DEFAULT] + interface_driver = linuxbridge + dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq + enable_isolated_metadata = true + ``` + + ***Description*** + + In the **[default]** section, configure the linuxbridge interface driver and Dnsmasq DHCP driver, and enable the isolated metadata. + + Configure the metadata agent: + + ```shell + vim /etc/neutron/metadata_agent.ini (CTL) + + [DEFAULT] + nova_metadata_host = controller + metadata_proxy_shared_secret = METADATA_SECRET + ``` + + ***Description*** + + In the **[default]**, configure the metadata host and the shared secret. + + ***Note*** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + +4. Configure Nova: + + ```shell + vim /etc/nova/nova.conf + + [neutron] + auth_url = http://controller:5000 + auth_type = password + project_domain_name = Default + user_domain_name = Default + region_name = RegionOne + project_name = service + username = neutron + password = NEUTRON_PASS + service_metadata_proxy = true (CTL) + metadata_proxy_shared_secret = METADATA_SECRET (CTL) + ``` + + ***Description*** + + In the **[neutron]** section, configure the access parameters, enable the metadata agent, and configure the secret. + + ***Note*** + + **Replace *NEUTRON_PASS* with the password of the neutron user.** + + **Replace *METADATA_SECRET* with a proper metadata agent secret.** + +5. Synchronize the database: + + ```shell + su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ + --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron + ``` + +6. Run the following command to restart the compute API service: + + ```shell + systemctl restart openstack-nova-api.service + ``` + +7. Start the network service: + + ```shell + systemctl enable neutron-server.service neutron-linuxbridge-agent.service \ (CTL) + neutron-dhcp-agent.service neutron-metadata-agent.service \ + neutron-l3-agent.service + + systemctl restart neutron-server.service neutron-linuxbridge-agent.service \ (CTL) + neutron-dhcp-agent.service neutron-metadata-agent.service \ + neutron-l3-agent.service + + systemctl enable neutron-linuxbridge-agent.service (CPT) + systemctl restart neutron-linuxbridge-agent.service openstack-nova-compute.service (CPT) + ``` + +8. Perform the verification. + + Run the following command to verify whether the Neutron agent is started successfully: + + ```shell + openstack network agent list + ``` + +### Installing Cinder + +1. Create the database, service credentials, and API endpoints. + + Create the database: + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE cinder; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ + IDENTIFIED BY 'CINDER_DBPASS'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ + IDENTIFIED BY 'CINDER_DBPASS'; + MariaDB [(none)]> exit + ``` + + ***Note*** + + **Replace *CINDER_DBPASS* to set the password for the cinder database.** + + ```shell + source ~/.admin-openrc + ``` + + Create the Cinder service credentials: + + ```shell + openstack user create --domain default --password-prompt cinder + openstack role add --project service --user cinder admin + openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 + openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 + ``` + + Create the API endpoints for the block storage service: + + ```shell + openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%\(project_id\)s + openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%\(project_id\)s + ``` + +2. Install the software packages: + + ```shell + yum install openstack-cinder-api openstack-cinder-scheduler (CTL) + ``` + + ```shell + yum install lvm2 device-mapper-persistent-data scsi-target-utils rpcbind nfs-utils \ (STG) + openstack-cinder-volume openstack-cinder-backup + ``` + +3. Prepare the storage devices. The following is an example: + + ```shell + pvcreate /dev/vdb + vgcreate cinder-volumes /dev/vdb + + vim /etc/lvm/lvm.conf + + + devices { + ... + filter = [ "a/vdb/", "r/.*/"] + ``` + + ***Description*** + + In the **devices** section, add filters to allow the **/dev/vdb** devices and reject other devices. + +4. Prepare the NFS: + + ```shell + mkdir -p /root/cinder/backup + + cat << EOF >> /etc/export + /root/cinder/backup 192.168.1.0/24(rw,sync,no_root_squash,no_all_squash) + EOF + + ``` + +5. Configure Cinder: + + ```shell + vim /etc/cinder/cinder.conf + + [DEFAULT] + transport_url = rabbit://openstack:RABBIT_PASS@controller + auth_strategy = keystone + my_ip = 10.0.0.11 + enabled_backends = lvm (STG) + backup_driver=cinder.backup.drivers.nfs.NFSBackupDriver (STG) + backup_share=HOST:PATH (STG) + + [database] + connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000 + auth_url = http://controller:5000 + memcached_servers = controller:11211 + auth_type = password + project_domain_name = Default + user_domain_name = Default + project_name = service + username = cinder + password = CINDER_PASS + + [oslo_concurrency] + lock_path = /var/lib/cinder/tmp + + [lvm] + volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver (STG) + volume_group = cinder-volumes (STG) + iscsi_protocol = iscsi (STG) + iscsi_helper = tgtadm (STG) + ``` + + ***Description*** + + In the **[database]** section, configure the database entry. + + In the **[DEFAULT]** section, configure the RabbitMQ message queue entry and **my_ip**. + + In the **[DEFAULT]** and **[keystone_authtoken]** sections, configure the identity authentication service entry. + + In the **[oslo_concurrency]** section, configure the lock path. + + ***Note*** + + **Replace *CINDER_DBPASS* with the password of the cinder database.** + + **Replace *RABBIT_PASS* with the password of the openstack user in RabbitMQ.** + + **Set *my_ip* to the management IP address of the controller node.** + + **Replace *CINDER_PASS* with the password of the cinder user.** + + **Replace *HOST:PATH* with the host IP address and the shared path of the NFS.** + +6. Synchronize the database: + + ```shell + su -s /bin/sh -c "cinder-manage db sync" cinder (CTL) + ``` + +7. Configure Nova: + + ```shell + vim /etc/nova/nova.conf (CTL) + + [cinder] + os_region_name = RegionOne + ``` + +8. Restart the compute API service: + + ```shell + systemctl restart openstack-nova-api.service + ``` + +9. Start the Cinder service: + + ```shell + systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) + systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) + ``` + + ```shell + systemctl enable rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) + openstack-cinder-volume.service \ + openstack-cinder-backup.service + systemctl start rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) + openstack-cinder-volume.service \ + openstack-cinder-backup.service + ``` + + ***Note*** + + If the Cinder volumes are mounted using tgtadm, modify the **/etc/tgt/tgtd.conf** file as follows to ensure that tgtd can discover the iscsi target of cinder-volume. + + ```shell + include /var/lib/cinder/volumes/* + ``` + +10. Perform the verification: + + ```shell + source ~/.admin-openrc + openstack volume service list + ``` + +### Installing Horizon + +1. Install the software package: + + ```shell + yum install openstack-dashboard + ``` + +2. Modify the file. + + Modify the variables: + + ```text + vim /etc/openstack-dashboard/local_settings + + OPENSTACK_HOST = "controller" + ALLOWED_HOSTS = ['*', ] + + SESSION_ENGINE = 'django.contrib.sessions.backends.cache' + + CACHES = { + 'default': { + 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', + 'LOCATION': 'controller:11211', + } + } + + OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST + OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True + OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default" + OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user" + + OPENSTACK_API_VERSIONS = { + "identity": 3, + "image": 2, + "volume": 3, + } + ``` + +3. Restart the httpd service: + + ```shell + systemctl restart httpd.service memcached.service + ``` + +4. Perform the verification. + Open the browser, enter in the address bar, and log in to Horizon. + + ***Note*** + + **Replace *HOSTIP* with the management plane IP address of the controller node.** + +### Installing Tempest + +Tempest is the integrated test service of OpenStack. If you need to run a fully automatic test of the functions of the installed OpenStack environment, you are advised to use Tempest. Otherwise, you can choose not to install it. + +1. Install Tempest: + + ```shell + yum install openstack-tempest + ``` + +2. Initialize the directory: + + ```shell + tempest init mytest + ``` + +3. Modify the configuration file: + + ```shell + cd mytest + vi etc/tempest.conf + ``` + + Configure the current OpenStack environment information in **tempest.conf**. For details, see the [official example](https://docs.openstack.org/tempest/latest/sampleconf.html). + +4. Perform the test: + + ```shell + tempest run + ``` + +5. (Optional) Install the tempest extensions. + The OpenStack services have provided some tempest test packages. You can install these packages to enrich the tempest test content. In Train, extension tests for Cinder, Glance, Keystone, Ironic and Trove are provided. You can run the following command to install and use them: + ``` + yum install python3-cinder-tempest-plugin python3-glance-tempest-plugin python3-ironic-tempest-plugin python3-keystone-tempest-plugin python3-trove-tempest-plugin + ``` + +### Installing Ironic + +Ironic is the bare metal service of OpenStack. If you need to deploy bare metal machines, Ironic is recommended. Otherwise, you can choose not to install it. + +1. Set the database. + + The bare metal service stores information in the database. Create a **ironic** database that can be accessed by the **ironic** user and replace **IRONIC_DBPASSWORD** with a proper password. + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ + IDENTIFIED BY 'IRONIC_DBPASSWORD'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ + IDENTIFIED BY 'IRONIC_DBPASSWORD'; + ``` + +2. Install the software packages. + + ```shell + yum install openstack-ironic-api openstack-ironic-conductor python3-ironicclient + ``` + + Start the services. + + ```shell + systemctl enable openstack-ironic-api openstack-ironic-conductor + systemctl start openstack-ironic-api openstack-ironic-conductor + ``` + +3. Create service user authentication. + + 1. Create the bare metal service user: + + ```shell + openstack user create --password IRONIC_PASSWORD \ + --email ironic@example.com ironic + openstack role add --project service --user ironic admin + openstack service create --name ironic \ + --description "Ironic baremetal provisioning service" baremetal + ``` + + 1. Create the bare metal service access entries: + + ```shell + openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 + openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 + openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 + ``` + +4. Configure the ironic-api service. + + Configuration file path: **/etc/ironic/ironic.conf** + + 1. Use **connection** to configure the location of the database as follows. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. + + ```shell + [database] + + # The SQLAlchemy connection string used to connect to the + # database (string value) + + connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic + ``` + + 1. Configure the ironic-api service to use the RabbitMQ message broker. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. + + ```shell + [DEFAULT] + + # A URL representing the messaging driver to use and its full + # configuration. (string value) + + transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ + ``` + + You can also use json-rpc instead of RabbitMQ. + + 1. Configure the ironic-api service to use the credential of the identity authentication service. Replace **PUBLIC_IDENTITY_IP** with the public IP address of the identity authentication server and **PRIVATE_IDENTITY_IP** with the private IP address of the identity authentication server, replace **IRONIC_PASSWORD** with the password of the **ironic** user in the identity authentication service. + + ```shell + [DEFAULT] + + # Authentication strategy used by ironic-api: one of + # "keystone" or "noauth". "noauth" should not be used in a + # production environment because all authentication will be + # disabled. (string value) + + auth_strategy=keystone + + [keystone_authtoken] + # Authentication type to load (string value) + auth_type=password + # Complete public Identity API endpoint (string value) + www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 + # Complete admin Identity API endpoint. (string value) + auth_url=http://PRIVATE_IDENTITY_IP:5000 + # Service username. (string value) + username=ironic + # Service account password. (string value) + password=IRONIC_PASSWORD + # Service tenant name. (string value) + project_name=service + # Domain name containing project (string value) + project_domain_name=Default + # User's domain name (string value) + user_domain_name=Default + + ``` + + 1. Create the bare metal service database table: + + ```shell + ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema + ``` + + 1. Restart the ironic-api service: + + ```shell + sudo systemctl restart openstack-ironic-api + ``` + +5. Configure the ironic-conductor service. + + 1. Replace **HOST_IP** with the IP address of the conductor host. + + ```shell + [DEFAULT] + + # IP address of this host. If unset, will determine the IP + # programmatically. If unable to do so, will use "127.0.0.1". + # (string value) + + my_ip=HOST_IP + ``` + + 1. Specifies the location of the database. ironic-conductor must use the same configuration as ironic-api. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. + + ```shell + [database] + + # The SQLAlchemy connection string to use to connect to the + # database. (string value) + + connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic + ``` + + 1. Configure the ironic-api service to use the RabbitMQ message broker. ironic-conductor must use the same configuration as ironic-api. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. + + ```shell + [DEFAULT] + + # A URL representing the messaging driver to use and its full + # configuration. (string value) + + transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ + ``` + + You can also use json-rpc instead of RabbitMQ. + + 1. Configure the credentials to access other OpenStack services. + + To communicate with other OpenStack services, the bare metal service needs to use the service users to get authenticated by the OpenStack Identity service when requesting other services. The credentials of these users must be configured in each configuration file associated to the corresponding service. + + ```shell + [neutron] - Accessing the OpenStack network services. + [glance] - Accessing the OpenStack image service. + [swift] - Accessing the OpenStack object storage service. + [cinder] - Accessing the OpenStack block storage service. + [inspector] Accessing the OpenStack bare metal introspection service. + [service_catalog] - A special item to store the credential used by the bare metal service. The credential is used to discover the API URL endpoint registered in the OpenStack identity authentication service catalog by the bare metal service. + ``` + + For simplicity, you can use one service user for all services. For backward compatibility, the user name must be the same as that configured in [keystone_authtoken] of the ironic-api service. However, this is not mandatory. You can also create and configure a different service user for each service. + + In the following example, the authentication information for the user to access the OpenStack network service is configured as follows: + + ```shell + The network service is deployed in the identity authentication service domain named RegionOne. Only the public endpoint interface is registered in the service catalog. + + A specific CA SSL certificate is used for HTTPS connection when sending a request. + + The same service user as that configured for ironic-api. + + The dynamic password authentication plugin discovers a proper identity authentication service API version based on other options. + ``` + + ```shell + [neutron] + + # Authentication type to load (string value) + auth_type = password + # Authentication URL (string value) + auth_url=https://IDENTITY_IP:5000/ + # Username (string value) + username=ironic + # User's password (string value) + password=IRONIC_PASSWORD + # Project name to scope to (string value) + project_name=service + # Domain ID containing project (string value) + project_domain_id=default + # User's domain id (string value) + user_domain_id=default + # PEM encoded Certificate Authority to use when verifying + # HTTPs connections. (string value) + cafile=/opt/stack/data/ca-bundle.pem + # The default region_name for endpoint URL discovery. (string + # value) + region_name = RegionOne + # List of interfaces, in order of preference, for endpoint + # URL. (list value) + valid_interfaces=public + ``` + + By default, to communicate with other services, the bare metal service attempts to discover a proper endpoint of the service through the service catalog of the identity authentication service. If you want to use a different endpoint for a specific service, specify the endpoint_override option in the bare metal service configuration file. + + ```shell + [neutron] ... endpoint_override = + ``` + + 1. Configure the allowed drivers and hardware types. + + Set enabled_hardware_types to specify the hardware types that can be used by ironic-conductor: + + ```shell + [DEFAULT] enabled_hardware_types = ipmi + ``` + + Configure hardware interfaces: + + ```shell + enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool + ``` + + Configure the default value of the interface: + + ```shell + [DEFAULT] default_deploy_interface = direct default_network_interface = neutron + ``` + + If any driver that uses Direct Deploy is enabled, you must install and configure the Swift backend of the image service. The Ceph object gateway (RADOS gateway) can also be used as the backend of the image service. + + 1. Restart the ironic-conductor service: + + ```shell + sudo systemctl restart openstack-ironic-conductor + ``` + +6. Configure the httpd service. + + 1. Create the root directory of the httpd used by Ironic, and set the owner and owner group. The directory path must be the same as the path specified by the **http_root** configuration item in the **[deploy]** group in **/etc/ironic/ironic.conf**. + + ``` + mkdir -p /var/lib/ironic/httproot ``chown ironic.ironic /var/lib/ironic/httproot + ``` + + 2. Install and configure the httpd Service. + + 1. Install the httpd service. If the httpd service is already installed, skip this step. + + ``` + yum install httpd -y + ``` + 2. Create the **/etc/httpd/conf.d/openstack-ironic-httpd.conf** file. The file content is as follows: + + ``` + Listen 8080 + + + ServerName ironic.openeuler.com + + ErrorLog "/var/log/httpd/openstack-ironic-httpd-error_log" + CustomLog "/var/log/httpd/openstack-ironic-httpd-access_log" "%h %l %u %t \"%r\" %>s %b" + + DocumentRoot "/var/lib/ironic/httproot" + + Options Indexes FollowSymLinks + Require all granted + + LogLevel warn + AddDefaultCharset UTF-8 + EnableSendfile on + + + ``` + + The listening port must be the same as the port specified by **http_url** in the **[deploy]** section of **/etc/ironic/ironic.conf**. + + 3. Restart the httpd service: + + ``` + systemctl restart httpd + ``` + + + +8. Create the deploy ramdisk image. + + The ramdisk image of Train can be created using the ironic-python-agent service or disk-image-builder tool. You can also use the latest ironic-python-agent-builder provided by the community. You can also use other tools. + To use the Train native tool, you need to install the corresponding software package. + + ```shell + yum install openstack-ironic-python-agent + or + yum install diskimage-builder + ``` + + For details, see the [official document](https://docs.openstack.org/ironic/queens/install/deploy-ramdisk.html). + + The following describes how to use the ironic-python-agent-builder to build the deploy image used by ironic. + + 1. Install ironic-python-agent-builder. + + 1. Install the tool: + + ```shell + pip install ironic-python-agent-builder + ``` + + 2. Modify the python interpreter in the following files: + + ```shell + /usr/bin/yum /usr/libexec/urlgrabber-ext-down + ``` + + 3. Install the other necessary tools: + + ```shell + yum install git + ``` + + **DIB** depends on the `semanage` command. Therefore, check whether the `semanage --help` command is available before creating an image. If the system displays a message indicating that the command is unavailable, install the command: + + ```shell + # Check which package needs to be installed. + [root@localhost ~]# yum provides /usr/sbin/semanage + Loaded plug-in: fastestmirror + Loading mirror speeds from cached hostfile + * base: mirror.vcu.edu + * extras: mirror.vcu.edu + * updates: mirror.math.princeton.edu + policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities + Source: base + Matching source: + File name: /usr/sbin/semanage + # Install. + [root@localhost ~]# yum install policycoreutils-python + ``` + + 2. Create the image. + + For Arm architecture, add the following information: + ```shell + export ARCH=aarch64 + ``` + + Basic usage: + + ```shell + usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] + [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] + distribution + + positional arguments: + distribution Distribution to use + + optional arguments: + -h, --help show this help message and exit + -r RELEASE, --release RELEASE + Distribution release to use + -o OUTPUT, --output OUTPUT + Output base file name + -e ELEMENT, --element ELEMENT + Additional DIB element to use + -b BRANCH, --branch BRANCH + If set, override the branch that is used for ironic- + python-agent and requirements + -v, --verbose Enable verbose logging in diskimage-builder + --extra-args EXTRA_ARGS + Extra arguments to pass to diskimage-builder + ``` + + Example: + + ```shell + ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky + ``` + + 3. Allow SSH login. + + Initialize the environment variables and create the image: + + ```shell + export DIB_DEV_USER_USERNAME=ipa \ + export DIB_DEV_USER_PWDLESS_SUDO=yes \ + export DIB_DEV_USER_PASSWORD='123' + ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser + ``` + + 4. Specify the code repository. + + Initialize the corresponding environment variables and create the image: + + ```shell + # Specify the address and version of the repository. + DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git + DIB_REPOREF_ironic_python_agent=origin/develop + + # Clone code from Gerrit. + DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent + DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 + ``` + + Reference: [source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html). + + The specified repository address and version are verified successfully. + + 5. Note + +The template of the PXE configuration file of the native OpenStack does not support the ARM64 architecture. You need to modify the native OpenStack code. + +In Train, Ironic provided by the community does not support the boot from ARM 64-bit UEFI PXE. As a result, the format of the generated grub.cfg file (generally in /tftpboot/) is incorrect, causing the PXE boot failure. + +You need to modify the code logic for generating the grub.cfg file. + +The following TLS error is reported when Ironic sends a request to IPA to query the command execution status: + +By default, both IPA and Ironic of Train have TLS authentication enabled to send requests to each other. Disable TLS authentication according to the description on the official website. + +1. Add **ipa-insecure=1** to the following configuration in the Ironic configuration file (**/etc/ironic/ironic.conf**): + +``` +[agent] +verify_ca = False + +[pxe] +pxe_append_params = nofb nomodeset vga=normal coreos.autologin ipa-insecure=1 +``` + +2. Add the IPA configuration file **/etc/ironic_python_agent/ironic_python_agent.conf** to the ramdisk image and configure the TLS as follows: + +**/etc/ironic_python_agent/ironic_python_agent.conf** (The **/etc/ironic_python_agent** directory must be created in advance.) + +``` +[DEFAULT] +enable_auto_tls = False +``` + +Set the permission: + +``` +chown -R ipa.ipa /etc/ironic_python_agent/ +``` + +3. Modify the startup file of the IPA service and add the configuration file option. + + vim usr/lib/systemd/system/ironic-python-agent.service + + ``` + [Unit] + Description=Ironic Python Agent + After=network-online.target + + [Service] + ExecStartPre=/sbin/modprobe vfat + ExecStart=/usr/local/bin/ironic-python-agent --config-file /etc/ironic_python_agent/ironic_python_agent.conf + Restart=always + RestartSec=30s + + [Install] + WantedBy=multi-user.target + ``` + + +Other services such as ironic-inspector are also provided for OpenStack Train. Install the services based on site requirements. + +### Installing Kolla + +Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. + +The installation of Kolla is simple. You only need to install the corresponding RPM packages: + +``` +yum install openstack-kolla openstack-kolla-ansible +``` + +After the installation is complete, you can run commands such as `kolla-ansible`, `kolla-build`, `kolla-genpwd`, `kolla-mergepwd` to create an image or deploy a container environment. + +### Installing Trove +Trove is the database service of OpenStack. If you need to use the database service provided by OpenStack, Trove is recommended. Otherwise, you can choose not to install it. + +1. Set the database. + + The database service stores information in the database. Create a **trove** database that can be accessed by the **trove** user and replace **TROVE_DBPASSWORD** with a proper password. + + ```sql + mysql -u root -p + + MariaDB [(none)]> CREATE DATABASE trove CHARACTER SET utf8; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'localhost' \ + IDENTIFIED BY 'TROVE_DBPASSWORD'; + MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'%' \ + IDENTIFIED BY 'TROVE_DBPASSWORD'; + ``` + +2. Create service user authentication. + + 1. Create the **Trove** service user. + + ```shell + openstack user create --domain default --password-prompt trove + openstack role add --project service --user trove admin + openstack service create --name trove --description "Database" database + ``` + **Description:** Replace *TROVE_PASSWORD* with the password of the **trove** user. + + 1. Create the **Database** service access entry + + ```shell + openstack endpoint create --region RegionOne database public http://controller:8779/v1.0/%\(tenant_id\)s + openstack endpoint create --region RegionOne database internal http://controller:8779/v1.0/%\(tenant_id\)s + openstack endpoint create --region RegionOne database admin http://controller:8779/v1.0/%\(tenant_id\)s + ``` + +3. Install and configure the **Trove** components. + + 1. Install the **Trove** package: + ```shell script + yum install openstack-trove python3-troveclient + ``` + + 2. Configure **trove.conf**: + ```shell script + vim /etc/trove/trove.conf + + [DEFAULT] + log_dir = /var/log/trove + trove_auth_url = http://controller:5000/ + nova_compute_url = http://controller:8774/v2 + cinder_url = http://controller:8776/v1 + swift_url = http://controller:8080/v1/AUTH_ + rpc_backend = rabbit + transport_url = rabbit://openstack:RABBIT_PASS@controller:5672 + auth_strategy = keystone + add_addresses = True + api_paste_config = /etc/trove/api-paste.ini + nova_proxy_admin_user = admin + nova_proxy_admin_pass = ADMIN_PASSWORD + nova_proxy_admin_tenant_name = service + taskmanager_manager = trove.taskmanager.manager.Manager + use_nova_server_config_drive = True + # Set these if using Neutron Networking + network_driver = trove.network.neutron.NeutronDriver + network_label_regex = .* + + [database] + connection = mysql+pymysql://trove:TROVE_DBPASSWORD@controller/trove + + [keystone_authtoken] + www_authenticate_uri = http://controller:5000/ + auth_url = http://controller:5000/ + auth_type = password + project_domain_name = default + user_domain_name = default + project_name = service + username = trove + password = TROVE_PASSWORD + ``` + **Description:** + - In the **[Default]** section, **nova_compute_url** and **cinder_url** are endpoints created by Nova and Cinder in Keystone. + - **nova_proxy_XXX** is a user who can access the Nova service. In the preceding example, the **admin** user is used. + - **transport_url** is the **RabbitMQ** connection information, and **RABBIT_PASS** is the RabbitMQ password. + - In the **[database]** section, **connection** is the information of the database created for Trove in MySQL. + - Replace **TROVE_PASSWORD** in the Trove user information with the password of the **trove** user. + + 3. Configure **trove-guestagent.conf**: + ```shell script + vim /etc/trove/trove-guestagent.conf + + rabbit_host = controller + rabbit_password = RABBIT_PASS + trove_auth_url = http://controller:5000/ + ``` + **Description:** **guestagent** is an independent component in Trove and needs to be pre-built into the virtual machine image created by Trove using Nova. + After the database instance is created, the guestagent process is started to report heartbeat messages to the Trove through the message queue (RabbitMQ). + Therefore, you need to configure the user name and password of the RabbitMQ. + **Since Victoria, Trove uses a unified image to run different types of databases. The database service runs in the Docker container of the Guest VM.** + - Replace **RABBIT_PASS** with the RabbitMQ password. + + 4. Generate the **Trove** database table. + ```shell script + su -s /bin/sh -c "trove-manage db_sync" trove + ``` + +4. Complete the installation and configuration. + 1. Configure the **Trove** service to automatically start: + ```shell script + systemctl enable openstack-trove-api.service \ + openstack-trove-taskmanager.service \ + openstack-trove-conductor.service + ``` + 2. Start the services: + ```shell script + systemctl start openstack-trove-api.service \ + openstack-trove-taskmanager.service \ + openstack-trove-conductor.service + ``` +### Installing Swift + +Swift provides a scalable and highly available distributed object storage service, which is suitable for storing unstructured data in large scale. + +1. Create the service credentials and API endpoints. + + Create the service credential: + + ``` shell + # Create the swift user. + openstack user create --domain default --password-prompt swift + # Add the admin role for the swift user. + openstack role add --project service --user swift admin + # Create the swift service entity. + openstack service create --name swift --description "OpenStack Object Storage" object-store + ``` + + Create the Swift API endpoints. + + ```shell + openstack endpoint create --region RegionOne object-store public http://controller:8080/v1/AUTH_%\(project_id\)s + openstack endpoint create --region RegionOne object-store internal http://controller:8080/v1/AUTH_%\(project_id\)s + openstack endpoint create --region RegionOne object-store admin http://controller:8080/v1 + ``` + + +2. Install the software packages: + + ```shell + yum install openstack-swift-proxy python3-swiftclient python3-keystoneclient python3-keystonemiddleware memcached (CTL) + ``` + +3. Configure the proxy-server. + + The Swift RPM package contains a **proxy-server.conf** file which is basically ready to use. You only need to change the values of **ip** and swift **password** in the file. + + ***Note*** + + **Replace password with the password you set for the swift user in the identity service.** + +4. Install and configure the storage node. (STG) + + Install the supported program packages: + ```shell + yum install xfsprogs rsync + ``` + + Format the /dev/vdb and /dev/vdc devices into XFS: + + ```shell + mkfs.xfs /dev/vdb + mkfs.xfs /dev/vdc + ``` + + Create the mount point directory structure: + + ```shell + mkdir -p /srv/node/vdb + mkdir -p /srv/node/vdc + ``` + + Find the UUID of the new partition: + + ```shell + blkid + ``` + + Add the following to the **/etc/fstab** file: + + ```shell + UUID="" /srv/node/vdb xfs noatime 0 2 + UUID="" /srv/node/vdc xfs noatime 0 2 + ``` + + Mount the devices: + + ```shell + mount /srv/node/vdb + mount /srv/node/vdc + ``` + ***Note*** + + **If the disaster recovery function is not required, you only need to create one device and skip the following rsync configuration.** + + (Optional) Create or edit the **/etc/rsyncd.conf** file to include the following content: + + ```shell + [DEFAULT] + uid = swift + gid = swift + log file = /var/log/rsyncd.log + pid file = /var/run/rsyncd.pid + address = MANAGEMENT_INTERFACE_IP_ADDRESS + + [account] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/account.lock + + [container] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/container.lock + + [object] + max connections = 2 + path = /srv/node/ + read only = False + lock file = /var/lock/object.lock + ``` + **Replace *MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node.** + + Start the rsyncd service and configure it to start upon system startup. + + ```shell + systemctl enable rsyncd.service + systemctl start rsyncd.service + ``` + +5. Install and configure the components on storage nodes. (STG) + + Install the software packages: + + ```shell + yum install openstack-swift-account openstack-swift-container openstack-swift-object + ``` + + Edit **account-server.conf**, **container-server.conf**, and **object-server.conf** in the **/etc/swift directory** and replace **bind_ip** with the management network IP address of the storage node. + + Ensure the proper ownership of the mount point directory structure. + + ```shell + chown -R swift:swift /srv/node + ``` + + Create the recon directory and ensure that it has the correct ownership. + + ```shell + mkdir -p /var/cache/swift + chown -R root:swift /var/cache/swift + chmod -R 775 /var/cache/swift + ``` + +6. Create the account ring. (CTL) + + Switch to the **/etc/swift** directory: + + ```shell + cd /etc/swift + ``` + + Create the basic **account.builder** file: + + ```shell + swift-ring-builder account.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder account.builder add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6202 --device DEVICE_NAME --weight DEVICE_WEIGHT + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to each storage device on each storage node.** + + Verify the ring contents: + + ```shell + swift-ring-builder account.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder account.builder rebalance + ``` + +7. Create the container ring. (CTL) + + Switch to the **/etc/swift** directory: + + Create the basic **container.builder** file: + + ```shell + swift-ring-builder container.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder container.builder \ + add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6201 \ + --device DEVICE_NAME --weight 100 + + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to every storage devices on every storage nodes.** + + Verify the ring contents: + + ```shell + swift-ring-builder container.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder container.builder rebalance + ``` + +8. Create the object ring. (CTL) + + Switch to the **/etc/swift** directory: + + Create the basic **object.builder** file: + + ```shell + swift-ring-builder object.builder create 10 1 1 + ``` + + Add each storage node to the ring: + + ```shell + swift-ring-builder object.builder \ + add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6200 \ + --device DEVICE_NAME --weight 100 + ``` + + **Replace *STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS* with the management network IP address of the storage node. Replace *DEVICE_NAME* with the name of the storage device on the same storage node.** + + ***Note*** + **Repeat this command to every storage devices on every storage nodes.** + + Verify the ring contents: + + ```shell + swift-ring-builder object.builder + ``` + + Rebalance the ring: + + ```shell + swift-ring-builder object.builder rebalance + ``` + + Distribute ring configuration files: + + Copy **account.ring.gz**, **container.ring.gz**, and **object.ring.gz** to the **/etc/swift** directory on each storage node and any additional nodes running the proxy service. + + + +9. Complete the installation. + + Edit the **/etc/swift/swift.conf** file: + + ``` shell + [swift-hash] + swift_hash_path_suffix = test-hash + swift_hash_path_prefix = test-hash + + [storage-policy:0] + name = Policy-0 + default = yes + ``` + + **Replace test-hash with a unique value.** + + Copy the **swift.conf** file to the **/etc/swift** directory on each storage node and any additional nodes running the proxy service. + + Ensure correct ownership of the configuration directory on all nodes: + + ```shell + chown -R root:swift /etc/swift + ``` + + On the controller node and any additional nodes running the proxy service, start the object storage proxy service and its dependencies, and configure them to start upon system startup. + + ```shell + systemctl enable openstack-swift-proxy.service memcached.service + systemctl start openstack-swift-proxy.service memcached.service + ``` + + On the storage node, start the object storage services and configure them to start upon system startup. + + ```shell + systemctl enable openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service + + systemctl start openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service + + systemctl enable openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service + + systemctl start openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service + + systemctl enable openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service + + systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service + ``` +### Installing Cyborg + +Cyborg provides acceleration device support for OpenStack, for example, GPUs, FPGAs, ASICs, NPs, SoCs, NVMe/NOF SSDs, ODPs, DPDKs, and SPDKs. + +1. Initialize the databases. + +``` +CREATE DATABASE cyborg; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +$ openstack user create --domain default --password-prompt cyborg +$ openstack role add --project service --user cyborg admin +$ openstack service create --name cyborg --description "Acceleration Service" accelerator + +$ openstack endpoint create --region RegionOne \ + accelerator public http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator internal http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator admin http://:6666/v1 +``` + +3. Install Cyborg + +``` +yum install openstack-cyborg +``` + +4. Configure Cyborg + +Modify **/etc/cyborg/cyborg.conf**. + +``` +[DEFAULT] +transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ +use_syslog = False +state_path = /var/lib/cyborg +debug = True + +[database] +connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg + +[service_catalog] +project_domain_id = default +user_domain_id = default +project_name = service +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[placement] +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = placement +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[keystone_authtoken] +memcached_servers = localhost:11211 +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password +``` + +Set the user names, passwords, and IP addresses as required. + +1. Synchronize the database table. + +``` +cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade +``` + +6. Start the Cyborg services. + +``` +systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +``` + +### Installing Aodh + +1. Create the database. + +``` +CREATE DATABASE aodh; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt aodh + +openstack role add --project service --user aodh admin + +openstack service create --name aodh --description "Telemetry" alarming + +openstack endpoint create --region RegionOne alarming public http://controller:8042 + +openstack endpoint create --region RegionOne alarming internal http://controller:8042 + +openstack endpoint create --region RegionOne alarming admin http://controller:8042 +``` + +3. Install Aodh. + +``` +yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient +``` + +4. Modify the configuration file. + +``` +[database] +connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh + +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +auth_strategy = keystone + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +aodh-dbsync +``` + +6. Start the Aodh services. + +``` +systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service + +systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service +``` + +### Installing Gnocchi + +1. Create the database. + +``` +CREATE DATABASE gnocchi; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt gnocchi + +openstack role add --project service --user gnocchi admin + +openstack service create --name gnocchi --description "Metric Service" metric + +openstack endpoint create --region RegionOne metric public http://controller:8041 + +openstack endpoint create --region RegionOne metric internal http://controller:8041 + +openstack endpoint create --region RegionOne metric admin http://controller:8041 +``` + +3. Install Gnocchi. + +``` +yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient +``` + +1. Modify the **/etc/gnocchi/gnocchi.conf** configuration file. + +``` +[api] +auth_mode = keystone +port = 8041 +uwsgi_mode = http-socket + +[keystone_authtoken] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_name = Default +user_domain_name = Default +project_name = service +username = gnocchi +password = GNOCCHI_PASS +interface = internalURL +region_name = RegionOne + +[indexer] +url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi + +[storage] +# coordination_url is not required but specifying one will improve +# performance with better workload division across workers. +coordination_url = redis://controller:6379 +file_basepath = /var/lib/gnocchi +driver = file +``` + +5. Initialize the database. + +``` +gnocchi-upgrade +``` + +6. Start the Gnocchi services. + +``` +systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service + +systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service +``` + +### Installing Ceilometer + +1. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt ceilometer + +openstack role add --project service --user ceilometer admin + +openstack service create --name ceilometer --description "Telemetry" metering +``` + +2. Install Ceilometer. + +``` +yum install openstack-ceilometer-notification openstack-ceilometer-central +``` + +1. Modify the **/etc/ceilometer/pipeline.yaml** configuration file. + +``` +publishers: + # set address of Gnocchi + # + filter out Gnocchi-related activity meters (Swift driver) + # + set default archive policy + - gnocchi://?filter_project=service&archive_policy=low +``` + +4. Modify the **/etc/ceilometer/ceilometer.conf** configuration file. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = ceilometer +password = CEILOMETER_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +ceilometer-upgrade +``` + +6. Start the Ceilometer services. + +``` +systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service + +systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service +``` + +### Installing Heat + +1. Creat the **heat** database and grant proper privileges to it. Replace **HEAT_DBPASS** with a proper password. + +``` +CREATE DATABASE heat; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; +``` + +2. Create a service credential. Create the **heat** user and add the **admin** role to it. + +``` +openstack user create --domain default --password-prompt heat +openstack role add --project service --user heat admin +``` + +3. Create the **heat** and **heat-cfn** services and their API enpoints. + +``` +openstack service create --name heat --description "Orchestration" orchestration +openstack service create --name heat-cfn --description "Orchestration" cloudformation +openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 +``` + +4. Create additional OpenStack management information, including the **heat** domain and its administrator **heat_domain_admin**, the **heat_stack_owner** role, and the **heat_stack_user** role. + +``` +openstack user create --domain heat --password-prompt heat_domain_admin +openstack role add --domain heat --user-domain heat --user heat_domain_admin admin +openstack role create heat_stack_owner +openstack role create heat_stack_user +``` + +5. Install the software packages. + +``` +yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine +``` + +6. Modify the configuration file **/etc/heat/heat.conf**. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +heat_metadata_server_url = http://controller:8000 +heat_waitcondition_server_url = http://controller:8000/v1/waitcondition +stack_domain_admin = heat_domain_admin +stack_domain_admin_password = HEAT_DOMAIN_PASS +stack_user_domain_name = heat + +[database] +connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_name = default +user_domain_name = default +project_name = service +username = heat +password = HEAT_PASS + +[trustee] +auth_type = password +auth_url = http://controller:5000 +username = heat +password = HEAT_PASS +user_domain_name = default + +[clients_keystone] +auth_uri = http://controller:5000 +``` + +7. Initialize the **heat** database table. + +``` +su -s /bin/sh -c "heat-manage db_sync" heat +``` + +8. Start the services. + +``` +systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +``` + +## OpenStack Quick Installation + +The OpenStack SIG provides the Ansible script for one-click deployment of OpenStack in All in One or Distributed modes. Users can use the script to quickly deploy an OpenStack environment based on openEuler RPM packages. The following uses the All in One mode installation as an example. + +1. Install the OpenStack SIG Tool. + + ```shell + pip install openstack-sig-tool + ``` + +2. Configure the OpenStack Yum source. + + ```shell + yum install openstack-release-train + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + +3. Update the Ansible configurations. + + Open the **/usr/local/etc/inventory/all_in_one.yaml** file and modify the configuration based on the environment and requirements. Modify the file as follows: + + ```shell + all: + hosts: + controller: + ansible_host: + ansible_ssh_private_key_file: + ansible_ssh_user: root + vars: + mysql_root_password: root + mysql_project_password: root + rabbitmq_password: root + project_identity_password: root + enabled_service: + - keystone + - neutron + - cinder + - placement + - nova + - glance + - horizon + - aodh + - ceilometer + - cyborg + - gnocchi + - kolla + - heat + - swift + - trove + - tempest + neutron_provider_interface_name: br-ex + default_ext_subnet_range: 10.100.100.0/24 + default_ext_subnet_gateway: 10.100.100.1 + neutron_dataplane_interface_name: eth1 + cinder_block_device: vdb + swift_storage_devices: + - vdc + swift_hash_path_suffix: ash + swift_hash_path_prefix: has + children: + compute: + hosts: controller + storage: + hosts: controller + network: + hosts: controller + vars: + test-key: test-value + dashboard: + hosts: controller + vars: + allowed_host: '*' + kolla: + hosts: controller + vars: + # We add openEuler OS support for kolla in OpenStack Queens/Rocky release + # Set this var to true if you want to use it in Q/R + openeuler_plugin: false + ``` + + Key Configurations + + | Item | Description| + |---|---| + | ansible_host | IP address of the all-in-one node.| + | ansible_ssh_private_key_file | Key used by the Ansible script for logging in to the all-in-one node.| + | ansible_ssh_user | User used by the Ansible script for logging in to the all-in-one node.| + | enabled_service | List of services to be installed. You can delete services as required.| + | neutron_provider_interface_name | Neutron L3 bridge name. | + | default_ext_subnet_range | Neutron private network IP address range. | + | default_ext_subnet_gateway | Neutron private network gateway. | + | neutron_dataplane_interface_name | NIC used by Neutron. You are advised to use a new NIC to avoid conflicts with existing NICs causing disconnection of the all-in-one node. | + | cinder_block_device | Name of the block device used by Cinder.| + | swift_storage_devices | Name of the block device used by Swift. | + +4. Run the installation command. + + ```shell + oos env setup all_in_one + ``` + + After the command is executed, the OpenStack environment of the All in One mode is successfully deployed. + + The environment variable file **.admin-openrc** is stored in the home directory of the current user. + +5. Initialize the Tempest environment. + + If you want to perform the Tempest test in the environment, run the `oos env init all_in_one` command to create the OpenStack resources required by Tempest. + + After the command is executed successfully, a **mytest** directory is generated in the home directory of the user. You can run the `tempest run` command in the directory. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-victoria.md b/docs/en/docs/thirdparty_migration/OpenStack-victoria.md deleted file mode 100644 index 28e921a4c..000000000 --- a/docs/en/docs/thirdparty_migration/OpenStack-victoria.md +++ /dev/null @@ -1,1832 +0,0 @@ -# OpenStack Victoria Deployment Guide - -## OpenStack - -OpenStack is an open source cloud computing infrastructure software project developed by the community. It provides an operating platform or tool set for deploying the cloud, offering scalable and flexible cloud computing for organizations. - -As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. - -The official Yum source of openEuler 21.09 supports the Openstack Victoria version. You can configure the official Yum source and then deploy OpenStack by following the instructions of this document. - -## Preparing the Environment -### Environment Configuration - -Add controller in the `/etc/hosts` file, for example, for node IP `10.0.0.11`, add the following information: - -```shell -10.0.0.11 controller -``` - -### Installing the SQL Database - -1. Run the following command to install the software package: - - ```plain - # yum install mariadb mariadb-server python-PyMySQL - ``` - -2. Run the following command to create and edit the `/etc/my.cnf.d/openstack.cnf` file: - - ``` - vim /etc/my.cnf.d/openstack.cnf - ``` - - Copy the following content to the file (set **bind-address** to the management IP address of the controller node): - - ``` - [mysqld] - bind-address = 10.0.0.11 - default-storage-engine = innodb - innodb_file_per_table = on - max_connections = 4096 - collation-server = utf8_general_ci - character-set-server = utf8 - ``` - -3. Run the following command to start the database service and enable it to automatically start upon system boot: - - ``` - # systemctl enable mariadb.service - # systemctl start mariadb.service - ``` - -### Installing RabbitMQ - -1. Run the following command to install the software package: - - ``` - #yum install rabbitmq-server - ``` - -2. Start the RabbitMQ service and enable it to automatically start upon system boot. - - ``` - #systemctl enable rabbitmq-server.service - #systemctl start rabbitmq-server.service - ``` - -3. Add an OpenStack user. - - ``` - #rabbitmqctl add_user openstack RABBIT_PASS - ``` - -4. Replace **RABBIT\_PASS** with the password of the OpenStack user. - -5. Run the following command to set the permission of the **openstack** user so that the user can perform configuration, write, and read operations: - - ``` - #rabbitmqctl set_permissions openstack ".*" ".*" ".*" - ``` - -### Installing Memcached - -1. Run the following command to install the target software package: - - ``` - #yum install memcached python3-memcached - ``` - -2. Run the following command to edit the `/etc/sysconfig/memcached` file: - - ``` - #vim /etc/sysconfig/memcached - OPTIONS="-l 127.0.0.1,::1,controller" - ``` - - Change the value of **OPTIONS** to the actual management IP address of the controller node. - -3. Run the following command to start the Memcached service and enable it to automatically start upon system boot: - - ``` - # systemctl enable memcached.service - # systemctl start memcached.service - ``` - -## Installing OpenStack - -### Installing Keystone - -1. Log in to the database as the **root** user. Create the **keystone** database, and grant permissions to the user. - - ``` - # mysql -u root -p - MariaDB [(none)]> CREATE DATABASE keystone; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **KEYSTONE\_DBPASS** with the password of the **keystone** database. - -2. Run the following command to install the software package: - - ``` - #yum install openstack-keystone httpd mod_wsgi - ``` - -3. Edit the `/etc/keystone/keystone.conf` file to configure the **keystone** database. In the **\[database]** section, configure the database entry. In the **\[token]** section, configure the token provider. - - ``` - # vim /etc/keystone/keystone.conf - [database] - connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone - [token] - provider = fernet - ``` - - Replace **KEYSTONE\_DBPASS** with the password of the **keystone** database. - -4. Run the following command to synchronize the database. - - ``` - su -s /bin/sh -c "keystone-manage db_sync" keystone - ``` - -5. Run the following command to initialize the Fernet keystore: - - ``` - # keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone - # keystone-manage credential_setup --keystone-user keystone --keystone-group keystone - ``` - -6. Run the following commands to enable the identity service: - - ``` - # keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ - --bootstrap-admin-url http://controller:5000/v3/ \ - --bootstrap-internal-url http://controller:5000/v3/ \ - --bootstrap-public-url http://controller:5000/v3/ \ - --bootstrap-region-id RegionOne - ``` - - Replace **ADMIN\_PASS** with the password of the **admin** user. - -7. Edit the `/etc/httpd/conf/httpd.conf` file and configure the Apache HTTP server. - - ``` - #vim /etc/httpd/conf/httpd.conf - ``` - - Enable **ServerName** to reference the controller node: - - ``` - ServerName controller - ``` - - If **ServerName** does not exist, create it. - -8. Run the following command to create a link for the `/usr/share/keystone/wsgi-keystone.conf` file: - - ``` - #ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ - - #vim /etc/httpd/conf.d/wsgi-keystone.conf - ``` - -9. After the installation is complete, run the following command to start the Apache HTTP service: - - ``` - # systemctl enable httpd.service - # systemctl start httpd.service - ``` - -10. Run the following command to set environment variables: - - ``` - $ export OS_USERNAME=admin - $ export OS_PASSWORD=ADMIN_PASS - $ export OS_PROJECT_NAME=admin - $ export OS_USER_DOMAIN_NAME=Default - $ export OS_PROJECT_DOMAIN_NAME=Default - $ export OS_AUTH_URL=http://controller:5000/v3 - $ export OS_IDENTITY_API_VERSION=3 - ``` - - Replace **ADMIN\_PASS** with the password set in the **keystone-manage bootstrap** command. - -11. Run the following commands to create the domain, project, user, and role: - - Create a domain named **example**. - - ``` - $ openstack domain create --description "An Example Domain" example - ``` - - Note: The domain **default** has been created in **keystone-manage bootstrap**. - - Create a project named **service**. - - ``` - $ openstack project create --domain default --description "Service Project" service - ``` - - Create a non-admin project named **myproject**, a user named **myuser**, and a role named **myrole**. Add the **myrole** role to **myproject** and **myuser**. - - ``` - $ openstack project create --domain default --description "Demo Project" myproject - $ openstack user create --domain default --password-prompt myuser - $ openstack role create myrole - $ openstack role add --project myproject --user myuser myrole - ``` - -12. Perform the verification. - - Cancel the temporary environment variables **OS\_AUTH\_URL** and **OS\_PASSWORD**. - - ``` - $ unset OS_AUTH_URL OS_PASSWORD - ``` - - Request a token for the **admin** user: - - ``` - $ openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name admin --os-username admin token issue - ``` - - Request a token for the **myuser** user: - - ``` - $ openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name myproject --os-username myuser token issue - ``` - -13. Create the environment script for the OpenStack client. - - Create environment variable scripts for the **admin** and **demo** users. - - ``` - # vim admin-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=admin - export OS_USERNAME=admin - export OS_PASSWORD=ADMIN_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - # - ``` - - ``` - # vim demo-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=myproject - export OS_USERNAME=myuser - export OS_PASSWORD=DEMO_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - ``` - - Replace **ADMIN\_PASS** with the password of the **admin** user. - - Replace **DEMO\_PASS** with the password of the **myuser** user. - - Run the following script to load environment variables: - - ``` - $ source admin-openrc - ``` - -### Installing Glance - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Log in to the database as the **root** user. Create the **glance** database, and grant permissions to the database. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE glance; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **GLANCE\_DBPASS** with the password of the **glance** database. - - ``` - $ source admin-openrc - ``` - - Run the following commands to create the **glance** service credential, create the **glance** user, and add the **admin** role to the **glance** user: - - ``` - $ openstack user create --domain default --password-prompt glance - $ openstack role add --project service --user glance admin - $ openstack service create --name glance --description "OpenStack Image" image - ``` - - Create API endpoints for the image service. - - ``` - $ openstack endpoint create --region RegionOne image public http://controller:9292 - $ openstack endpoint create --region RegionOne image internal http://controller:9292 - $ openstack endpoint create --region RegionOne image admin http://controller:9292 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - #yum install openstack-glance openstack-glance-api - ``` - - Configure Glance: - - Edit the **/etc/glance/glance-api.conf** file: - - In the **\[database]** section, configure the database entry. - - In the **\[keystone\_authtoken]** and **\[paste\_deploy]** sections, configure the identity authentication service entry. - - In the **\[glance\_store]** section, configure the local file system storage and the location where image files are stored. - - ``` - # vim /etc/glance/glance-api.conf - [database] - # ... - connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = glance - password = GLANCE_PASS - [paste_deploy] - # ... - flavor = keystone - [glance_store] - # ... - stores = file,http - default_store = file - filesystem_store_datadir = /var/lib/glance/images/ - ``` - - In the preceding command, replace **GLANCE\_DBPASS** with the password of the **glance** database, and replace **GLANCE\_PASS** with the password of the **glance** user. - - Synchronize the database: - - ``` - su -s /bin/sh -c "glance-manage db_sync" glance - ``` - - Run the following command to start the image service: - - ``` - # systemctl enable openstack-glance-api.service - # systemctl start openstack-glance-api.service - ``` - -3. Perform the verification. - - Download the image. - - ``` - $ source admin-openrc - # Note: If the Kunpeng architecture is used in your environment, download the ARM64 image. - $ wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img - ``` - - Upload the image to the image service. - - ``` - $ glance image-create --name "cirros" --file cirros-0.4.0-x86_64-disk.img --disk-format qcow2 --container-format bare --visibility=public - ``` - - Confirm the image upload and verify the attributes. - - ``` - $ glance image-list - ``` - -### Installing Placement - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **placement** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE placement; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **PLACEMENT\_DBPASS** with the password of the **placement** database. - - ``` - $ source admin-openrc - ``` - - Run the following commands to create the placement service credentials, create the **placement** user, and add the **admin** role to the **placement** user: - - Create the Placement API Service. - - ``` - $ openstack user create --domain default --password-prompt placement - $ openstack role add --project service --user placement admin - $ openstack service create --name placement --description "Placement API" placement - ``` - - Create API endpoints of the Placement service. - - ``` - $ openstack endpoint create --region RegionOne placement public http://controller:8778 - $ openstack endpoint create --region RegionOne placement internal http://controller:8778 - $ openstack endpoint create --region RegionOne placement admin http://controller:8778 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - yum install openstack-placement-api - ``` - - Configure Placement: - - Edit the **/etc/placement/placement.conf** file: - - In the **\[placement\_database]** section, configure the database entry. - - In **\[api]** and **\[keystone\_authtoken]** sections, configure the identity authentication service entry. - - ``` - # vim /etc/placement/placement.conf - [placement_database] - # ... - connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - auth_url = http://controller:5000/v3 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = placement - password = PLACEMENT_PASS - ``` - - Replace **PLACEMENT\_DBPASS** with the password of the **placement** database, and replace **PLACEMENT\_PASS** with the password of the **placement** user. - - Synchronize the database: - - ``` - #su -s /bin/sh -c "placement-manage db sync" placement - ``` - - Start the httpd service. - - ``` - #systemctl restart httpd - ``` - -3. Perform the verification. - - Run the following command to check the status: - - ``` - $ . admin-openrc - $ placement-status upgrade check - ``` - - Run the following command to install **osc-placement** and list the available resource types and features: - - ``` - $ yum install python3-osc-placement - $ openstack --os-placement-api-version 1.2 resource class list --sort-column name - $ openstack --os-placement-api-version 1.6 trait list --sort-column name - ``` - -### Installing Nova - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **nova**, **nova\_api**, and **nova\_cell0** databases and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE nova_api; - MariaDB [(none)]> CREATE DATABASE nova; - MariaDB [(none)]> CREATE DATABASE nova_cell0; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **NOVA\_DBPASS** with the password of the **nova** database. - - Run the following commands to create Nova service credentials, create a **nova** user, and add the **admin** role to the **nova** user: - - ``` - $ . admin-openrc - $ openstack user create --domain default --password-prompt nova - $ openstack role add --project service --user nova admin - $ openstack service create --name nova --description "OpenStack Compute" compute - ``` - - Create API endpoints for the computing service. - - ``` - $ openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 - $ openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 - $ openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 - ``` - -2. Perform the installation and configuration. - - Install the software package: - - ``` - # yum install openstack-nova-api openstack-nova-conductor \ - openstack-nova-novncproxy openstack-nova-scheduler openstack-nova-compute - ``` - - Configure Nova: - - Edit the **/etc/nova/nova.conf** file. - - In the **\[default]** section, enable the computing and metadata APIs, configure the RabbitMQ message queue entry, and set **my\_ip**. - - In the **\[api\_database]** and **\[database]** sections, configure the database entry. - - In the **\[api]** and **\[keystone\_authtoken]** sections, configure the identity service entry. - - In the **\[vnc]** section, enable and configure the entry for the remote console. - - In the **\[glance]** section, configure the API address for the image service. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - In the **\[placement]** section, configure the entry of the Placement service. - - ``` - # vim /etc/nova/nova.conf - [DEFAULT] - # ... - enabled_apis = osapi_compute,metadata - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - my_ip = 10.0.0.11 - [api_database] - # ... - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api - [database] - # ... - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000/ - auth_url = http://controller:5000/ - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = nova - password = NOVA_PASS - [vnc] - enabled = true - # ... - server_listen = $my_ip - server_proxyclient_address = $my_ip - novncproxy_base_url = http://controller:6080/vnc_auto.html - [glance] - # ... - api_servers = http://controller:9292 - [oslo_concurrency] - # ... - lock_path = /var/lib/nova/tmp - [placement] - # ... - region_name = RegionOne - project_domain_name = Default - project_name = service - auth_type = password - user_domain_name = Default - auth_url = http://controller:5000/v3 - username = placement - password = PLACEMENT_PASS - [neutron] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - ``` - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Set **my\_ip** to the management IP address of the controller node. - - Replace **NOVA\_DBPASS** with the password of the **nova** database. - - Replace **NOVA\_PASS** with the password of the **nova** user. - - Replace **PLACEMENT\_PASS** with the password of the **placement** user. - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Run the following command to synchronize the **nova-api** database: - - ``` - su -s /bin/sh -c "nova-manage api_db sync" nova - ``` - - Run the following command to register the **cell0** database: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova - ``` - - Create the **cell1** cell: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova - ``` - - Synchronize the **nova** database: - - ``` - su -s /bin/sh -c "nova-manage db sync" nova - ``` - - Verify whether **cell0** and **cell1** are correctly registered: - - ``` - su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova - ``` - - Check whether VM hardware acceleration (x86 architecture) is supported: - - ``` - $ egrep -c '(vmx|svm)' /proc/cpuinfo - ``` - - If the returned value is **0**, hardware acceleration is not supported. You need to configure libvirt to use QEMU instead of KVM. - - ``` - # vim /etc/nova/nova.conf - [libvirt] - # ... - virt_type = qemu - ``` - - If the returned value is **1** or a larger value, hardware acceleration is supported, and no extra configuration is required. - - Start the computing service and its dependencies, and enable the service to start automatically upon system boot. - - ``` - # systemctl enable \ - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - # systemctl start \ - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - ``` - - ``` - # systemctl enable libvirtd.service openstack-nova-compute.service - # systemctl start libvirtd.service openstack-nova-compute.service - ``` - - Add the compute nodes to the **cell** database: - - Check whether the compute node exists: - - ``` - $ . admin-openrc - $ openstack compute service list --service nova-compute - ``` - - Register a compute node: - - ``` - #su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova - ``` - -3. Perform the verification. - - ``` - $ . admin-openrc - ``` - - List service components to verify that each process is successfully started and registered. - - ``` - $ openstack compute service list - ``` - - List the API endpoints in the identity service and verify the connection to the identity service. - - ``` - $ openstack catalog list - ``` - - List the images in the image service and verify the connections: - - ``` - $ openstack image list - ``` - - Check whether the cells and placement APIs are running properly and whether other prerequisites are met. - - ``` - #nova-status upgrade check - ``` - -### Installing Neutron - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user, create the **neutron** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE neutron; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **NEUTRON\_DBPASS** with the password of the **neutron** database. - - ``` - $ . admin-openrc - ``` - - Run the following commands to create the **neutron** service credential, create the **neutron** user, and add the **admin** role to the **neutron** user: - - Create the **neutron** service credential. - - ``` - $ openstack user create --domain default --password-prompt neutron - $ openstack role add --project service --user neutron admin - $ openstack service create --name neutron --description "OpenStack Networking" network - ``` - - Create API endpoints of the network services. - - ``` - $ openstack endpoint create --region RegionOne network public http://controller:9696 - $ openstack endpoint create --region RegionOne network internal http://controller:9696 - $ openstack endpoint create --region RegionOne network admin http://controller:9696 - ``` - -2. Install and configure the self-service network. - - Install the software package: - - ``` - # yum install openstack-neutron openstack-neutron-ml2 \ - openstack-neutron-linuxbridge ebtables ipset - ``` - - Configure Neutron: - - Edit the **/etc/neutron/neutron.conf** file: - - In the **\[database]** section, configure the database entry. - - In the **\[default]** section, enable the ML2 and router plug-ins. Allow IP address overlapping, and configure the RabbitMQ message queue entry. - - In the **\[default]** and **\[keystone]** sections, configure the identity authentication service entry. - - In the **\[default]** and **\[nova]** sections, enable the network to notify the change of the computing network topology. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - ``` - # vim /etc/neutron/neutron.conf - [database] - # ... - connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron - [DEFAULT] - # ... - core_plugin = ml2 - service_plugins = router - allow_overlapping_ips = true - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - notify_nova_on_port_status_changes = true - notify_nova_on_port_data_changes = true - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = default - user_domain_name = default - project_name = service - username = neutron - password = NEUTRON_PASS - [nova] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = nova - password = NOVA_PASS - [oslo_concurrency] - # ... - lock_path = /var/lib/neutron/tmp - ``` - - Replace **NEUTRON\_DBPASS** with the password of the **neutron** database. - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Replace **NOVA\_PASS** with the password of the **nova** user. - - Configure the ML2 plug-in. - - Edit the **/etc/neutron/plugins/ml2/ml2\_conf.ini** file. - - In the **\[ml2]** section, enable the flat, VLAN, and VXLAN networks, enable the bridge and layer-2 population mechanism, and enable the port security extension driver. - - In the **\[ml2\_type\_flat]** section, configure the flat network as the provider virtual network. - - In the **\[ml2\_type\_vxlan]** section, configure the VXLAN network identifier range. - - In the **\[securitygroup]** section, set **ipset**. - - ``` - # vim /etc/neutron/plugins/ml2/ml2_conf.ini - [ml2] - # ... - type_drivers = flat,vlan,vxlan - tenant_network_types = vxlan - mechanism_drivers = linuxbridge,l2population - extension_drivers = port_security - [ml2_type_flat] - # ... - flat_networks = provider - [ml2_type_vxlan] - # ... - vni_ranges = 1:1000 - [securitygroup] - # ... - enable_ipset = true - ``` - - Configure the Linux bridge agent: - - Edit the **/etc/neutron/plugins/ml2/linuxbridge\_agent.ini** file: - - In the **\[linux\_bridge]** section, map the provider virtual network to the physical network API. - - In the **\[vxlan]** section, enable the VXLAN network. Configure the IP address of the physical network API that processes the coverage network, and enable layer-2 population. - - In the **\[securitygroup]** section, enable the security group and configure the **linux bridge iptables** firewall driver. - - ``` - # vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini - [linux_bridge] - physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME - [vxlan] - enable_vxlan = true - local_ip = OVERLAY_INTERFACE_IP_ADDRESS - l2_population = true - [securitygroup] - # ... - enable_security_group = true - firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver - ``` - - Replace **PROVIDER\_INTERFACE\_NAME** with the physical network API. - - Replace **OVERLAY\_INTERFACE\_IP\_ADDRESS** with the management IP address of the controller node. - - Configure the Layer 3 proxy. - - Edit the **/etc/neutron/l3\_agent.ini** file: - - In the **\[default]** section, set the API driver to **linuxbridge**. - - ``` - # vim /etc/neutron/l3_agent.ini - [DEFAULT] - # ... - interface_driver = linuxbridge - ``` - - Configures the DHCP agent: - - Edit the **/etc/neutron/dhcp\_agent.ini** file. - - In the **\[default]** section, configure the linuxbridge interface driver and Dnsmasq DHCP driver. Enable the isolated metadata. - - ``` - # vim /etc/neutron/dhcp_agent.ini - [DEFAULT] - # ... - interface_driver = linuxbridge - dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq - enable_isolated_metadata = true - ``` - - Configure the metadata proxy. - - Edit the **/etc/neutron/metadata\_agent.ini** file. - - In the **\[default]**, configure the metadata host and shared secret. - - ``` - # vim /etc/neutron/metadata_agent.ini - [DEFAULT] - # ... - nova_metadata_host = controller - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - Replace **METADATA\_SECRET** with a proper metadata agent secret. - -3. Configure the computing service. - - Edit the **/etc/nova/nova.conf** file. - - In the **\[neutron]** section, configure access parameters, enable the metadata proxy, and configure secret. - - ``` - # vim /etc/nova/nova.conf - [neutron] - # ... - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - Replace **NEUTRON\_PASS** with the password of the **neutron** user. - - Replace **METADATA\_SECRET** with a proper metadata agent secret. - -4. Complete the installation. - - Add a link: - - ``` - #ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini - ``` - - Synchronize the database: - - ``` - # su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ - --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron - ``` - - Run the following command to restart the computing API service: - - ``` - #systemctl restart openstack-nova-api.service - ``` - - Start the network service and enable the service to start automatically upon system boot. - - ``` - # systemctl enable neutron-server.service \ - neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ - neutron-metadata-agent.service - # systemctl start neutron-server.service \ - neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ - neutron-metadata-agent.service - # systemctl enable neutron-l3-agent.service - # systemctl start neutron-l3-agent.service - ``` - -5. Perform the verification. - - Run the following command to list the neutron agents: - - ``` - $ openstack network agent list - ``` - -### Installing Cinder - -1. Create a database, service credentials, and API endpoints. - - Create a database. - - Access the database as the **root** user. Create the **cinder** database, and grant permissions. - - ``` - $ mysql -u root -p - MariaDB [(none)]> CREATE DATABASE cinder; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> exit - ``` - - Replace **CINDER\_DBPASS** with the password for the **cinder** database. - - ``` - $ source admin-openrc - ``` - - Create Cinder service credentials: - - Create the **cinder** user. - - Add the **admin** role to the **cinder** user. - - Create the **cinderv2** and **cinderv3** services. - - ``` - $ openstack user create --domain default --password-prompt cinder - $ openstack role add --project service --user cinder admin - $ openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 - $ openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 - ``` - - Create API endpoints for the block storage service. - - ``` - $ openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%s - $ openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%s - $ openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%s - $ openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%s - ``` - -2. Install and configure the controller node. - - Install the software package: - - ``` - #yum install openstack-cinder - ``` - - Configure Cinder: - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[database]** section, configure the database entry. - - In the **\[DEFAULT]** section, configure the RabbitMQ message queue entry and **my\_ip**. - - In the **\[DEFAULT]** and **\[keystone\_authtoken]** sections, configure the identity authentication service entry. - - In the **\[oslo\_concurrency]** section, configure the lock path. - - ``` - # vim /etc/cinder/cinder.conf - [database] - # ... - connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder - [DEFAULT] - # ... - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - my_ip = 10.0.0.11 - [keystone_authtoken] - # ... - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = default - user_domain_name = default - project_name = service - username = cinder - password = CINDER_PASS - [oslo_concurrency] - # ... - lock_path = /var/lib/cinder/tmp - ``` - - Replace **CINDER\_DBPASS** with the password of the **cinder** database. - - Replace **RABBIT\_PASS** with the password of the **openstack** user in RabbitMQ. - - Set **my\_ip** to the management IP address of the controller node. - - Replace **CINDER\_PASS** with the password of the **cinder** user. - - Synchronize the database: - - ``` - su -s /bin/sh -c "cinder-manage db sync" cinder - ``` - - Configure the block storage for the compute nodes. - - Edit the **/etc/nova/nova.conf** file. - - ``` - # vim /etc/nova/nova.conf - [cinder] - os_region_name = RegionOne - ``` - - Complete the installation. - - Restart the computing API service. - - ``` - systemctl restart openstack-nova-api.service - ``` - - Start the block storage service. - - ``` - # systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service - # systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service - ``` - -3. Install and configure the storage node. - - Install the software package: - - ``` - yum install lvm2 device-mapper-persistent-data targetcli python3-keystone - ``` - - Start the service: - - ``` - # systemctl enable lvm2-lvmetad.service - # systemctl start lvm2-lvmetad.service - ``` - - Create the LVM physical volume **/dev/sdb**. - - ``` - pvcreate /dev/sdb - ``` - - Create the LVM volume group **cinder-volumes**. - - ``` - vgcreate cinder-volumes /dev/sdb - ``` - - Edit the **/etc/lvm/lvm.conf** file. - - In the **devices** section, add filtering to allow the **/dev/sdb** device to reject other devices. - - devices { - - ... - - filter = \[ "a/sdb/", "r/.\*/"] - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[lvm]** section, configure the LVM backend using the LVM driver, cinder-volumes volume group, iSCSI protocol, and appropriate iSCSI services. - - In the **\[DEFAULT]** section, enable the LVM backend and configure the location of the API of the image service. - - ``` - [lvm] - volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver - volume_group = cinder-volumes - target_protocol = iscsi - target_helper = lioadm - [DEFAULT] - # ... - enabled_backends = lvm - glance_api_servers = http://controller:9292 - ``` - - Complete the installation. - - ``` - # systemctl enable openstack-cinder-volume.service target.service - # systemctl start openstack-cinder-volume.service target.service - ``` - -4. Install and configure the backup service. - - Edit the **/etc/cinder/cinder.conf** file. - - In the **\[DEFAULT]** section, configure the backup options. - - ``` - [DEFAULT] - # ... - # Note: openEuler 21.09 does not provide the OpenStack Swift software package. You need to install it manually. Alternatively, you can use another backup backend, for example, NFS. The NFS has been tested and verified and can be used properly. - backup_driver = cinder.backup.drivers.swift.SwiftBackupDriver - backup_swift_url = SWIFT_URL - ``` - - Replace **SWIFT\_URL** with the URL of the object storage service. The URL can be found through the object storage API endpoint. - - ``` - $ openstack catalog show object-store - ``` - - Complete the installation. - - ``` - # systemctl enable openstack-cinder-backup.service - # systemctl start openstack-cinder-backup.service - ``` - -5. Perform the verification. - - List service components and verify that each step is successful. - - ``` - $ source admin-openrc - $ openstack volume service list - ``` - - Note: Currently, the Swift component is not supported. If possible, you can configure the interconnection with Ceph. - -### Installing Horizon - -1. Install the software package: - - ```plain - yum install openstack-horizon - ``` - -2. Modify the `/usr/share/openstack-dashboard/openstack_dashboard/local/local_settings.py` file. - - Modify the variables. - - ```plain - ALLOWED_HOSTS = ['*', ] - OPENSTACK_HOST = "controller" - OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST - ``` - - Add variables. - - ```plain - OPENSTACK_API_VERSIONS = { - "identity": 3, - "image": 2, - "volume": 3, - } - WEBROOT = "/dashboard/" - COMPRESS_OFFLINE = True - OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "default" - OPENSTACK_KEYSTONE_DEFAULT_ROLE = "admin" - LOGIN_URL = '/dashboard/auth/login/' - LOGOUT_URL = '/dashboard/auth/logout/' - ``` - -3. Run the following command in the **/usr/share/openstack-dashboard** directory: - - ```plain - ./manage.py compress - ``` - -4. Restart the httpd service. - - ```plain - systemctl restart httpd - ``` - -5. Perform the verification - Open a browser and enter **http://***\* in the address box to log in to Horizon. - -### Installing Tempest - -Tempest is the integrated test service of OpenStack. If you need to run a fully automatic test of the functions of the installed OpenStack environment, you are advised to use Tempest. Otherwise, you can choose not to install it. - -1. Install Tempest: - ``` - yum install openstack-tempest - ``` -2. Initialize the directory: - - ``` - tempest init mytest - ``` -3. Modify the configuration file: - - ``` - cd mytest - vi etc/tempest.conf - ``` - Configure the current OpenStack environment information in **tempest.conf**. For details, see the [official example](https://docs.openstack.org/tempest/latest/sampleconf.html). - -4. Perform the test: - - ``` - tempest run - ``` - -### Installing Ironic - -Ironic is the bare metal service of OpenStack. If you need to deploy bare metal machines, you are advised to use Ironic. Otherwise, you can choose not to install it. - -1. Set the database. - - The bare metal service stores information in the database. Create a **ironic** database that can be accessed by the **ironic** user and replace **IRONIC_DBPASSWORD** with a proper password. - - ``` - # mysql -u root -p MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - ``` - -2. Install and configure the components. - - ##### Creating Service User Authentication - - 1. Create the bare metal service user: - - ``` - $ openstack user create --password IRONIC_PASSWORD \ - --email ironic@example.com ironic - $ openstack role add --project service --user ironic admin - $ openstack service create --name ironic --description \ - "Ironic baremetal provisioning service" baremetal - - $ openstack service create --name ironic-inspector --description "Ironic inspector baremetal provisioning service" baremetal-introspection - $ openstack user create --password IRONIC_INSPECTOR_PASSWORD --email ironic_inspector@example.com ironic_inspector - $ openstack role add --project service --user ironic-inspector admin - ``` - - 2. Create the bare metal service access entries: - - ``` - $ openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 - $ openstack endpoint create --region RegionOne baremetal-introspection internal http://172.20.19.13:5050/v1 - $ openstack endpoint create --region RegionOne baremetal-introspection public http://172.20.19.13:5050/v1 - $ openstack endpoint create --region RegionOne baremetal-introspection admin http://172.20.19.13:5050/v1 - ``` - - ##### Configuring the ironic-api Service - - Configuration file path: **/etc/ironic/ironic.conf**. - - 1. Use **connection** to configure the location of the database as follows. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace **DB_IP** with the IP address of the database server. - - ``` - [database] - - # The SQLAlchemy connection string used to connect to the - # database (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 2. Configure the ironic-api service to use the RabbitMQ message broker. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. - - ``` - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - You can also use json-rpc instead of RabbitMQ. - - 3. Configure the ironic-api service to use the credential of the identity authentication service. Replace **PUBLIC_IDENTITY_IP** with the public IP address of the identity authentication server and **PRIVATE_IDENTITY_IP** with the private IP address of the identity authentication server, replace **IRONIC_PASSWORD** with the password of the **ironic** user in the identity authentication service. - - ``` - [DEFAULT] - - # Authentication strategy used by ironic-api: one of - # "keystone" or "noauth". "noauth" should not be used in a - # production environment because all authentication will be - # disabled. (string value) - - auth_strategy=keystone - - [keystone_authtoken] - # Authentication type to load (string value) - auth_type=password - # Complete public Identity API endpoint (string value) - www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 - # Complete admin Identity API endpoint. (string value) - auth_url=http://PRIVATE_IDENTITY_IP:5000 - # Service username. (string value) - username=ironic - # Service account password. (string value) - password=IRONIC_PASSWORD - # Service tenant name. (string value) - project_name=service - # Domain name containing project (string value) - project_domain_name=Default - # User's domain name (string value) - user_domain_name=Default - ``` - - 4. Create the bare metal service database table: - - ``` - $ ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema - ``` - - 5. Restart the ironic-api service: - - ``` - sudo systemctl restart openstack-ironic-api - ``` - - ##### Configuring the ironic-conductor Service. - - 1. Replace **HOST_IP** with the IP address of the conductor host. - - ``` - [DEFAULT] - - # IP address of this host. If unset, will determine the IP - # programmatically. If unable to do so, will use "127.0.0.1". - # (string value) - - my_ip=HOST_IP - ``` - - 2. Specifies the location of the database. ironic-conductor must use the same configuration as ironic-api. Replace **IRONIC_DBPASSWORD** with the password of user **ironic** and replace DB_IP with the IP address of the database server. - - ``` - [database] - - # The SQLAlchemy connection string to use to connect to the - # database. (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 3. Configure the ironic-api service to use the RabbitMQ message broker. ironic-conductor must use the same configuration as ironic-api. Replace **RPC_\*** with the detailed address and the credential of RabbitMQ. - - ``` - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - You can also use json-rpc instead of RabbitMQ. - - 4. Configure the credentials to access other OpenStack services. - - To communicate with other OpenStack services, the bare metal service needs to use the service users to get authenticated by the OpenStack Identity service when requesting other services. The credentials of these users must be configured in each configuration file associated to the corresponding service. - - ``` - [neutron] - Accessing the OpenStack network services. - [glance] - Accessing the OpenStack image service. - [swift] - Accessing the OpenStack object storage service. - [cinder] - Accessing the OpenStack block storage service. - [inspector] Accessing the OpenStack bare metal introspection service. - [service_catalog] - A special item to store the credential used by the bare metal service. The credential is used to discover the API URL endpoint registered in the OpenStack identity authentication service catalog by the bare metal service. - ``` - - For simplicity, you can use one service user for all services. For backward compatibility, the user name must be the same as that configured in **[keystone_authtoken]** of the ironic-api service. However, this is not mandatory. You can also create and configure a different service user for each service. - - In the following example, the authentication information for the user to access the OpenStack network service is configured as follows: - - ``` - The network service is deployed in the identity authentication service domain named RegionOne. Only the public endpoint interface is registered in the service catalog. - - A specific CA SSL certificate is used for HTTPS connection when sending a request. - - The same service user as that configured for ironic-api. - - The dynamic password authentication plugin discovers a proper identity authentication service API version based on other options. - ``` - - ``` - [neutron] - - # Authentication type to load (string value) - auth_type = password - # Authentication URL (string value) - auth_url=https://IDENTITY_IP:5000/ - # Username (string value) - username=ironic - # User's password (string value) - password=IRONIC_PASSWORD - # Project name to scope to (string value) - project_name=service - # Domain ID containing project (string value) - project_domain_id=default - # User's domain id (string value) - user_domain_id=default - # PEM encoded Certificate Authority to use when verifying - # HTTPs connections. (string value) - cafile=/opt/stack/data/ca-bundle.pem - # The default region_name for endpoint URL discovery. (string - # value) - region_name = RegionOne - # List of interfaces, in order of preference, for endpoint - # URL. (list value) - valid_interfaces=public - ``` - - By default, to communicate with other services, the bare metal service attempts to discover a proper endpoint of the service through the service catalog of the identity authentication service. If you want to use a different endpoint for a specific service, specify the endpoint_override option in the bare metal service configuration file. - - ``` - [neutron] ... endpoint_override = - ``` - - 5. Configure the allowed drivers and hardware types. - - Set enabled_hardware_types to specify the hardware types that can be used by ironic-conductor: - - ``` - [DEFAULT] enabled_hardware_types = ipmi - ``` - - Configure hardware interfaces: - - ``` - enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool - ``` - - Configure the default value of the interface: - - ``` - [DEFAULT] default_deploy_interface = direct default_network_interface = neutron - ``` - - If any driver that uses Direct Deploy is enabled, you must install and configure the Swift backend of the image service. The Ceph object gateway (RADOS gateway) can also be used as the backend of the image service. - - 6. Restart the ironic-conductor service. - - ``` - sudo systemctl restart openstack-ironic-conductor - ``` - - ##### Configuring the ironic-inspector Service - - Configuration file path: **/etc/ironic-inspector/inspector.conf** - - 1. Create the database: - - ``` - # mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE ironic_inspector CHARACTER SET utf8; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'localhost' \ IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'%' \ - IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - ``` - - 2. Use **connection** to configure the location of the database as follows. Replace **IRONIC_INSPECTOR_DBPASSWORD** with the password of user **ironic_inspector** and replace **DB_IP** with the IP address of the database server. - - ``` - [database] - backend = sqlalchemy - connection = mysql+pymysql://ironic_inspector:IRONIC_INSPECTOR_DBPASSWORD@DB_IP/ironic_inspector - ``` - - 3. Configure the communication address of the message queue: - - ``` - [DEFAULT] transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 4. Configure the Keystone authentication: - - ``` - [DEFAULT] - - auth_strategy = keystone - - [ironic] - - api_endpoint = http://IRONIC_API_HOST_ADDRRESS:6385 - auth_type = password - auth_url = http://PUBLIC_IDENTITY_IP:5000 - auth_strategy = keystone - ironic_url = http://IRONIC_API_HOST_ADDRRESS:6385 - os_region = RegionOne - project_name = service - project_domain_name = default - user_domain_name = default - username = IRONIC_SERVICE_USER_NAME - password = IRONIC_SERVICE_USER_PASSWORD - ``` - - 5. Configure the ironic inspector dnsmasq service: - - ``` - # Configuration file path: /etc/ironic-inspector/dnsmasq.conf - port=0 - interface=enp3s0 #Replace with the actual listening network interface. - dhcp-range=172.20.19.100,172.20.19.110 #Replace with the actual DHCP IP address range. - bind-interfaces - enable-tftp - - dhcp-match=set:efi,option:client-arch,7 - dhcp-match=set:efi,option:client-arch,9 - dhcp-match=aarch64, option:client-arch,11 - dhcp-boot=tag:aarch64,grubaa64.efi - dhcp-boot=tag:!aarch64,tag:efi,grubx64.efi - dhcp-boot=tag:!aarch64,tag:!efi,pxelinux.0 - - tftp-root=/tftpboot #Replace with the actual tftpboot directory. - log-facility=/var/log/dnsmasq.log - ``` - - 6. Start the services: - - ``` - $ systemctl enable --now openstack-ironic-inspector.service - $ systemctl enable --now openstack-ironic-inspector-dnsmasq.service - ``` - -3. Creatie the deploy ramdisk Image. - - Currently, you can use the ironic python agent builder to build the ramdisk image. The following describes how to use this tool to build the deploy image used by ironic. - - ##### Installing ironic-python-agent-builder - - 1. Install Python 3 on the local host, switch the local Python to Python 3, and resolve the problems after the switching (for example, the Yum source cannot be used). - - ``` - yum install python36 - ``` - - 2. Install the tool: - - ``` - pip install ironic-python-agent-builder - ``` - - 3. Modify the python interpreter in the following file: - - ``` - /usr/bin/yum /usr/libexec/urlgrabber-ext-down - ``` - - 4. Install the other necessary tools: - - ``` - yum install git - ``` - - `DIB` depends on the `semanage` command. Therefore, check whether the `semanage --help` command is available before creating an image. If the system displays a message indicating that the command is unavailable, install the command: - - ``` - # Check which package needs to be installed. - [root@localhost ~]# yum provides /usr/sbin/semanage - Loaded plug-in: fastestmirror - Loading mirror speeds from cached hostfile - * base: mirror.vcu.edu - * extras: mirror.vcu.edu - * updates: mirror.math.princeton.edu - policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities - Source: base - Matching source: - File name: /usr/sbin/semanage - # Install. - [root@localhost ~]# yum install policycoreutils-python - ``` - - ##### Creating the Image - - According to the test result, only version 8 is supported for CentOS. In addition, centos8-minimal lacks some NIC drivers. As a result, all NICs are in the down state after the Dell physical machine is started. Therefore, CentOS 8 is used in the example. Add the following environment variables: - - ``` - export DIB_PYTHON_VERSION=3 \ - export DIB_RELEASE=8 \ - export DIB_YUM_MINIMAL_CREATE_INTERFACES - ``` - - For `arm` architecture, add the following information in addition: - - ``` - export ARCH=aarch64 - ``` - - ###### Common Image - - Basic usage: - - ``` - usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] - [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] - distribution - - positional arguments: - distribution Distribution to use - - optional arguments: - -h, --help show this help message and exit - -r RELEASE, --release RELEASE - Distribution release to use - -o OUTPUT, --output OUTPUT - Output base file name - -e ELEMENT, --element ELEMENT - Additional DIB element to use - -b BRANCH, --branch BRANCH - If set, override the branch that is used for ironic- - python-agent and requirements - -v, --verbose Enable verbose logging in diskimage-builder - --extra-args EXTRA_ARGS - Extra arguments to pass to diskimage-builder - ``` - - Example: - - ``` - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky - ``` - - ###### Allowing SSH login - - Initialize the environment variables and create the image: - - ``` - export DIB_DEV_USER_USERNAME=ipa \ - export DIB_DEV_USER_PWDLESS_SUDO=yes \ - export DIB_DEV_USER_PASSWORD='123' - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser - ``` - - ###### Specifying the Code Repository - - Initialize the corresponding environment variables and create the image: - - ``` - # Specify the address and version of the repository. - DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git - DIB_REPOREF_ironic_python_agent=origin/develop - - # Clone code from Gerrit. - DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent - DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 - ``` - - Reference: [source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html). - - The specified repository address and version are verified successfully. diff --git a/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md b/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md index ea6141653..486d1856d 100644 --- a/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md +++ b/docs/en/docs/thirdparty_migration/OpenStack-wallaby.md @@ -31,7 +31,7 @@ OpenStack is an open source cloud computing infrastructure software project deve As an open source cloud computing management platform, OpenStack consists of several major components, such as Nova, Cinder, Neutron, Glance, Keystone, and Horizon. OpenStack supports almost all cloud environments. The project aims to provide a cloud computing management platform that is easy-to-use, scalable, unified, and standardized. OpenStack provides an infrastructure as a service (IaaS) solution that combines complementary services, each of which provides an API for integration. -The official source of openEuler 21.09 now supports OpenStack Wallaby. You can configure the Yum source then deploy OpenStack by following the instructions of this document. +The official source of openEuler 22.03 LTS now supports OpenStack Wallaby. You can configure the Yum source then deploy OpenStack by following the instructions of this document. ## Conventions @@ -64,33 +64,26 @@ The services involved in the preceding conventions are as follows: ### Environment Configuration -1. Configure the openEuler 21.09 official Yum source. Enable the EPOL software repository to support OpenStack. +1. Configure the openEuler 22.03 LTS official Yum source. Enable the EPOL software repository to support OpenStack. ```shell - cat << EOF >> /etc/yum.repos.d/21.09-OpenStack_Wallaby.repo - [OS] - name=OS - baseurl=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/RPM-GPG-KEY-openEuler + yum update + yum install openstack-release-wallaby + yum clean all && yum makecache + ``` - [everything] - name=everything - baseurl=http://repo.openeuler.org/openEuler-21.09/everything/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/everything/$basearch/RPM-GPG-KEY-openEuler + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo [EPOL] name=EPOL - baseurl=http://repo.openeuler.org/openEuler-21.09/EPOL/main/$basearch/ + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ enabled=1 gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-21.09/OS/$basearch/RPM-GPG-KEY-openEuler + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler EOF - - yum clean all && yum makecache ``` 2. Change the host name and mapping. @@ -102,7 +95,7 @@ The services involved in the preceding conventions are as follows: hostnamectl set-hostname compute (CPT) ``` - Assuming the IP address of the controller node is `10.0.0.11` and the IP address of the compute node (if any) is `10.0.0.12`, add the following information to the `/etc/hosts` file: + Assuming the IP address of the controller node is **10.0.0.11** and the IP address of the compute node (if any) is **10.0.0.12**, add the following information to the **/etc/hosts** file: ```shell 10.0.0.11 controller @@ -2211,7 +2204,7 @@ chown -R ipa.ipa /etc/ironic_python_agent/ ### Installing Kolla -Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. The Kolla and Kolla-ansible services are introduced in openEuler in version 21.09. +Kolla provides the OpenStack service with the container-based deployment function that is ready for the production environment. The Kolla and Kolla-ansible services are introduced in openEuler in version 22.03 LTS. The installation of Kolla is simple. You only need to install the corresponding RPM packages: @@ -2596,7 +2589,7 @@ Swift provides a scalable and highly available distributed object storage servic Rebalance the ring: ```shell - swift-ring-builder account.builder rebalance + swift-ring-builder container.builder rebalance ``` 8. Create the object ring. (CTL) @@ -2631,7 +2624,7 @@ Swift provides a scalable and highly available distributed object storage servic Rebalance the ring: ```shell - swift-ring-builder account.builder rebalance + swift-ring-builder object.builder rebalance ``` Distribute ring configuration files: @@ -2686,3 +2679,530 @@ Swift provides a scalable and highly available distributed object storage servic systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service ``` + +### Installing Cyborg + +Cyborg provides acceleration device support for OpenStack, for example, GPUs, FPGAs, ASICs, NPs, SoCs, NVMe/NOF SSDs, ODPs, DPDKs, and SPDKs. + +1. Initialize the databases. + +``` +CREATE DATABASE cyborg; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; +GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +$ openstack user create --domain default --password-prompt cyborg +$ openstack role add --project service --user cyborg admin +$ openstack service create --name cyborg --description "Acceleration Service" accelerator + +$ openstack endpoint create --region RegionOne \ + accelerator public http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator internal http://:6666/v1 +$ openstack endpoint create --region RegionOne \ + accelerator admin http://:6666/v1 +``` + +3. Install Cyborg + +``` +yum install openstack-cyborg +``` + +4. Configure Cyborg + +Modify **/etc/cyborg/cyborg.conf**. + +``` +[DEFAULT] +transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ +use_syslog = False +state_path = /var/lib/cyborg +debug = True + +[database] +connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg + +[service_catalog] +project_domain_id = default +user_domain_id = default +project_name = service +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[placement] +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = placement +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password + +[keystone_authtoken] +memcached_servers = localhost:11211 +project_domain_name = Default +project_name = service +user_domain_name = Default +password = PASSWORD +username = cyborg +auth_url = http://%OPENSTACK_HOST_IP%/identity +auth_type = password +``` + +Set the user names, passwords, and IP addresses as required. + +1. Synchronize the database table. + +``` +cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade +``` + +6. Start the Cyborg services. + +``` +systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent +``` + +### Installing Aodh + +1. Create the database. + +``` +CREATE DATABASE aodh; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; + +GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt aodh + +openstack role add --project service --user aodh admin + +openstack service create --name aodh --description "Telemetry" alarming + +openstack endpoint create --region RegionOne alarming public http://controller:8042 + +openstack endpoint create --region RegionOne alarming internal http://controller:8042 + +openstack endpoint create --region RegionOne alarming admin http://controller:8042 +``` + +3. Install Aodh. + +``` +yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient +``` + +4. Modify the configuration file. + +``` +[database] +connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh + +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +auth_strategy = keystone + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = aodh +password = AODH_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +aodh-dbsync +``` + +6. Start the Aodh services. + +``` +systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service + +systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service +``` + +### Installing Gnocchi + +1. Create the database. + +``` +CREATE DATABASE gnocchi; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; + +GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; +``` + +2. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt gnocchi + +openstack role add --project service --user gnocchi admin + +openstack service create --name gnocchi --description "Metric Service" metric + +openstack endpoint create --region RegionOne metric public http://controller:8041 + +openstack endpoint create --region RegionOne metric internal http://controller:8041 + +openstack endpoint create --region RegionOne metric admin http://controller:8041 +``` + +3. Install Gnocchi. + +``` +yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient +``` + +1. Modify the **/etc/gnocchi/gnocchi.conf** configuration file. + +``` +[api] +auth_mode = keystone +port = 8041 +uwsgi_mode = http-socket + +[keystone_authtoken] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_name = Default +user_domain_name = Default +project_name = service +username = gnocchi +password = GNOCCHI_PASS +interface = internalURL +region_name = RegionOne + +[indexer] +url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi + +[storage] +# coordination_url is not required but specifying one will improve +# performance with better workload division across workers. +coordination_url = redis://controller:6379 +file_basepath = /var/lib/gnocchi +driver = file +``` + +5. Initialize the database. + +``` +gnocchi-upgrade +``` + +6. Start the Gnocchi services. + +``` +systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service + +systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service +``` + +### Installing Ceilometer + +1. Create Keystone resource objects. + +``` +openstack user create --domain default --password-prompt ceilometer + +openstack role add --project service --user ceilometer admin + +openstack service create --name ceilometer --description "Telemetry" metering +``` + +2. Install Ceilometer. + +``` +yum install openstack-ceilometer-notification openstack-ceilometer-central +``` + +1. Modify the **/etc/ceilometer/pipeline.yaml** configuration file. + +``` +publishers: + # set address of Gnocchi + # + filter out Gnocchi-related activity meters (Swift driver) + # + set default archive policy + - gnocchi://?filter_project=service&archive_policy=low +``` + +4. Modify the **/etc/ceilometer/ceilometer.conf** configuration file. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller + +[service_credentials] +auth_type = password +auth_url = http://controller:5000/v3 +project_domain_id = default +user_domain_id = default +project_name = service +username = ceilometer +password = CEILOMETER_PASS +interface = internalURL +region_name = RegionOne +``` + +5. Initialize the database. + +``` +ceilometer-upgrade +``` + +6. Start the Ceilometer services. + +``` +systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service + +systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service +``` + +### Installing Heat + +1. Creat the **heat** database and grant proper privileges to it. Replace **HEAT_DBPASS** with a proper password. + +``` +CREATE DATABASE heat; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; +GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; +``` + +2. Create a service credential. Create the **heat** user and add the **admin** role to it. + +``` +openstack user create --domain default --password-prompt heat +openstack role add --project service --user heat admin +``` + +3. Create the **heat** and **heat-cfn** services and their API enpoints. + +``` +openstack service create --name heat --description "Orchestration" orchestration +openstack service create --name heat-cfn --description "Orchestration" cloudformation +openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s +openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 +openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 +``` + +4. Create additional OpenStack management information, including the **heat** domain and its administrator **heat_domain_admin**, the **heat_stack_owner** role, and the **heat_stack_user** role. + +``` +openstack user create --domain heat --password-prompt heat_domain_admin +openstack role add --domain heat --user-domain heat --user heat_domain_admin admin +openstack role create heat_stack_owner +openstack role create heat_stack_user +``` + +5. Install the software packages. + +``` +yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine +``` + +6. Modify the configuration file **/etc/heat/heat.conf**. + +``` +[DEFAULT] +transport_url = rabbit://openstack:RABBIT_PASS@controller +heat_metadata_server_url = http://controller:8000 +heat_waitcondition_server_url = http://controller:8000/v1/waitcondition +stack_domain_admin = heat_domain_admin +stack_domain_admin_password = HEAT_DOMAIN_PASS +stack_user_domain_name = heat + +[database] +connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat + +[keystone_authtoken] +www_authenticate_uri = http://controller:5000 +auth_url = http://controller:5000 +memcached_servers = controller:11211 +auth_type = password +project_domain_name = default +user_domain_name = default +project_name = service +username = heat +password = HEAT_PASS + +[trustee] +auth_type = password +auth_url = http://controller:5000 +username = heat +password = HEAT_PASS +user_domain_name = default + +[clients_keystone] +auth_uri = http://controller:5000 +``` + +7. Initialize the **heat** database table. + +``` +su -s /bin/sh -c "heat-manage db_sync" heat +``` + +8. Start the services. + +``` +systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service +``` + +## OpenStack Quick Installation + +The OpenStack SIG provides the Ansible script for one-click deployment of OpenStack in All in One or Distributed modes. Users can use the script to quickly deploy an OpenStack environment based on openEuler RPM packages. The following uses the All in One mode installation as an example. + +1. Install the OpenStack SIG Tool. + + ```shell + pip install openstack-sig-tool + ``` + +2. Configure the OpenStack Yum source. + + ```shell + yum install openstack-release-wallaby + ``` + + **Note**: Enable the EPOL repository for the Yum source if it is not enabled already. + + ```shell + vi /etc/yum.repos.d/openEuler.repo + + [EPOL] + name=EPOL + baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ + enabled=1 + gpgcheck=1 + gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler + EOF + +3. Update the Ansible configurations. + + Open the **/usr/local/etc/inventory/all_in_one.yaml** file and modify the configuration based on the environment and requirements. Modify the file as follows: + + ```shell + all: + hosts: + controller: + ansible_host: + ansible_ssh_private_key_file: + ansible_ssh_user: root + vars: + mysql_root_password: root + mysql_project_password: root + rabbitmq_password: root + project_identity_password: root + enabled_service: + - keystone + - neutron + - cinder + - placement + - nova + - glance + - horizon + - aodh + - ceilometer + - cyborg + - gnocchi + - kolla + - heat + - swift + - trove + - tempest + neutron_provider_interface_name: br-ex + default_ext_subnet_range: 10.100.100.0/24 + default_ext_subnet_gateway: 10.100.100.1 + neutron_dataplane_interface_name: eth1 + cinder_block_device: vdb + swift_storage_devices: + - vdc + swift_hash_path_suffix: ash + swift_hash_path_prefix: has + children: + compute: + hosts: controller + storage: + hosts: controller + network: + hosts: controller + vars: + test-key: test-value + dashboard: + hosts: controller + vars: + allowed_host: '*' + kolla: + hosts: controller + vars: + # We add openEuler OS support for kolla in OpenStack Queens/Rocky release + # Set this var to true if you want to use it in Q/R + openeuler_plugin: false + ``` + + Key Configurations + + | Item | Description| + |---|---| + | ansible_host | IP address of the all-in-one node.| + | ansible_ssh_private_key_file | Key used by the Ansible script for logging in to the all-in-one node.| + | ansible_ssh_user | User used by the Ansible script for logging in to the all-in-one node.| + | enabled_service | List of services to be installed. You can delete services as required.| + | neutron_provider_interface_name | Neutron L3 bridge name. | + | default_ext_subnet_range | Neutron private network IP address range. | + | default_ext_subnet_gateway | Neutron private network gateway. | + | neutron_dataplane_interface_name | NIC used by Neutron. You are advised to use a new NIC to avoid conflicts with existing NICs causing disconnection of the all-in-one node. | + | cinder_block_device | Name of the block device used by Cinder.| + | swift_storage_devices | Name of the block device used by Swift. | + +4. Run the installation command. + + ```shell + oos env setup all_in_one + ``` + + After the command is executed, the OpenStack environment of the All in One mode is successfully deployed. + + The environment variable file **.admin-openrc** is stored in the home directory of the current user. + +5. Initialize the Tempest environment. + + If you want to perform the Tempest test in the environment, run the `oos env init all_in_one` command to create the OpenStack resources required by Tempest. + + After the command is executed successfully, a **mytest** directory is generated in the home directory of the user. You can run the `tempest run` command in the directory. \ No newline at end of file diff --git a/docs/en/docs/userguide/patch-tracking.md b/docs/en/docs/userguide/patch-tracking.md index 1f427a5d9..67586ab4d 100644 --- a/docs/en/docs/userguide/patch-tracking.md +++ b/docs/en/docs/userguide/patch-tracking.md @@ -335,4 +335,4 @@ During the operation of the patch-tracking, the following error message may occu #### Cause Analysis -The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, HUAWEI CLOUD Hong Kong). \ No newline at end of file +The preceding problem is caused by the unstable network access between the patch-tracking and GitHub API. Ensure that the patch-tracking is operating in a stable network environment (for example, Huawei Cloud Hong Kong). \ No newline at end of file diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 74ce94a24..d3376362e 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -17,7 +17,7 @@ headless: true - [Installation Guide]({{< relref "./docs/Installation/Installation.md" >}}) - [Installation on Servers]({{< relref "./docs/Installation/install-server.md" >}}) - [Installation Preparations]({{< relref "./docs/Installation/installation-preparations.md" >}}) - - [Installation Mode]({{< relref "./docs/Installation/installation-mode.md" >}}) + - [Installation Modes]({{< relref "./docs/Installation/Installation-Modes1.md" >}}) - [Installation Guideline]({{< relref "./docs/Installation/installation-guideline.md" >}}) - [Using Kickstart for Automatic Installation]({{< relref "./docs/Installation/using-kickstart-for-automatic-installation.md" >}}) - [FAQs]({{< relref "./docs/Installation/faqs.md" >}}) @@ -57,7 +57,7 @@ headless: true - [Appendix]({{< relref "./docs/SecHarden/appendix.md" >}}) - [Virtualization User Guide]({{< relref "./docs/Virtualization/virtualization.md" >}}) - [Introduction to Virtualization]({{< relref "./docs/Virtualization/introduction-to-virtualization.md" >}}) - - [Installation to Virtualization]({{< relref "./docs/Virtualization/installation-to-virtualization.md" >}}) + - [Installing Virtualization]({{< relref "./docs/Virtualization/virtualization-installation.md" >}}) - [Environment Preparation]({{< relref "./docs/Virtualization/environment-preparation.md" >}}) - [VM Configuration]({{< relref "./docs/Virtualization/vm-configuration.md" >}}) - [Managing VMs]({{< relref "./docs/Virtualization/managing-vms.md" >}}) @@ -71,12 +71,15 @@ headless: true - [LibcarePlus]({{< relref "./docs/Virtualization/LibcarePlus.md" >}}) - [Appendix]({{< relref "./docs/Virtualization/appendix.md" >}}) - [StratoVirt Virtualization User Guide]({{< relref "./docs/StratoVirt/StratoVrit_guidence.md" >}}) - - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_intoduction.md" >}}) + - [Introduction to StratoVirt]({{< relref "./docs/StratoVirt/StratoVirt_introduction.md" >}}) - [Installing StratoVirt]({{< relref "./docs/StratoVirt/Install_StratoVirt.md" >}}) - [Preparing the Environment]({{< relref "./docs/StratoVirt/Prepare_env.md" >}}) - [Configuring a VM]({{< relref "./docs/StratoVirt/VM_configuration.md" >}}) - [VM Management]({{< relref "./docs/StratoVirt/VM_management.md" >}}) - - [Connecting to the iSula Secure Container]({{< relref "./docs/StratoVirt/connecting-to-the-isula-secure-container.md" >}}) + - [Connecting to the iSula Secure Container]({{< relref "./docs/StratoVirt/interconnect_isula.md" >}}) + - [Interconnecting with libvirt]({{< relref "./docs/StratoVirt/Interconnect_libvirt.md" >}}) + - [StratoVirt VFIO Instructions]({{< relref "./docs/StratoVirt/StratoVirt_VFIO_instructions.md" >}}) +- [Container User Guide]({{< relref "./docs/Container/container.md" >}}) - [iSulad Container Engine]({{< relref "./docs/Container/isulad-container-engine.md" >}}) - [Installation, Upgrade and Uninstallation]({{< relref "./docs/Container/installation-upgrade-Uninstallation.md" >}}) - [Installation and Configuration]({{< relref "./docs/Container/installation-configuration.md" >}}) @@ -85,8 +88,6 @@ headless: true - [Application Scenarios]({{< relref "./docs/Container/application-scenarios.md" >}}) - [Container Management]({{< relref "./docs/Container/container-management.md" >}}) - [Interconnection with the CNI Network]({{< relref "./docs/Container/interconnection-with-the-cni-network.md" >}}) -}) - - [Container Resource Management]({{< relref "./docs/Container/container-resource-management.md" >}}) - [Privileged Container]({{< relref "./docs/Container/privileged-container.md" >}}) - [CRI]({{< relref "./docs/Container/cri.md" >}}) - [Image Management]({{< relref "./docs/Container/image-management.md" >}}) @@ -136,17 +137,24 @@ headless: true - [Application Scenarios]({{< relref "./docs/A-Tune/application-scenarios.md" >}}) - [FAQs]({{< relref "./docs/A-Tune/faqs.md" >}}) - [Appendixes]({{< relref "./docs/A-Tune/appendixes.md" >}}) +- [openEuler Embedded User Guide]({{< relref "./docs/Embedded/embedded.md" >}}) + - [Installation and Running]({{< relref "./docs/Embedded/installation-and-running.md" >}}) + - [Build Guide]({{< relref "./docs/Embedded/building-guide.md" >}}) + - [Quick Build Guide]({{< relref "./docs/Embedded/quick-build-guide.md" >}}) + - [Container Build Guide]({{< relref "./docs/Embedded/container-build-guide.md" >}}) + - [Installation and Running]({{< relref "./docs/Embedded/installation-and-running.md" >}}) + - [Application Development Using openEuler Embedded SDK]({{< relref "./docs/Embedded/application-development-using-sdk.md" >}}) +- [Kernel Live Upgrade Guide]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) + - [Installation and Deployment]({{< relref "./docs/KernelLiveUpgrade/installation-and-deployment.md" >}}) + - [How to Run]({{< relref "./docs/KernelLiveUpgrade/how-to-run.md" >}}) + - [Common Problems and Solutions]({{< relref "./docs/KernelLiveUpgrade/common-problems-and-solutions.md" >}}) - [Application Development Guide]({{< relref "./docs/ApplicationDev/application-development.md" >}}) - - [Preparation]({{< relref "./docs/ApplicationDev/preparation.md" >}}) + - [Preparation]({{< relref "./docs/ApplicationDev/preparations-for-development-environment.md" >}}) - [Using GCC for Compilation]({{< relref "./docs/ApplicationDev/using-gcc-for-compilation.md" >}}) - [Using Make for Compilation]({{< relref "./docs/ApplicationDev/using-make-for-compilation.md" >}}) - [Using JDK for Compilation]({{< relref "./docs/ApplicationDev/using-jdk-for-compilation.md" >}}) - [Building an RPM Package]({{< relref "./docs/ApplicationDev/building-an-rpm-package.md" >}}) - [FAQ]({{< relref "./docs/ApplicationDev/FAQ.md" >}}) -- [Kernel Hot Upgrade Guide]({{< relref "./docs/KernelLiveUpgrade/KernelLiveUpgrade.md" >}}) - - [Installation and Deployment]({{< relref "./docs/KernelLiveUpgrade/installation-and-deployment.md" >}}) - - [How to Run]({{< relref "./docs/KernelLiveUpgrade/how-to-run.md" >}}) - - [Common Problems and Solutions]({{< relref "./docs/KernelLiveUpgrade/common-problems-and-solutions.md" >}}) - [secGear Development Guide]({{< relref "./docs/secGear/secGear.md" >}}) - [Introduction to secGear]({{< relref "./docs/secGear/introduction-to-secGear.md" >}}) - [Installing secGear]({{< relref "./docs/secGear/installing-secGear.md" >}}) @@ -166,10 +174,15 @@ headless: true - [Deploying a Cluster]({{< relref "./docs/Kubernetes/eggo-deploying-a-cluster.md" >}}) - [Dismantling a Cluster]({{< relref "./docs/Kubernetes/eggo-dismantling-a-cluster.md" >}}) - [Running the Test Pod]({{< relref "./docs/Kubernetes/running-the-test-pod.md" >}}) +- [KubeEdge User Guide]({{< relref "./docs/KubeEdge/overview.md" >}}) + - [KubeEdge Usage Guide]({{< relref "./docs/KubeEdge/kubeedge-usage-guide.md" >}}) + - [KubeEdge Deployment Guide]({{< relref "./docs/KubeEdge/kubeedge-deployment-guide.md" >}}) - [Third-Party Software Deployment Guide]({{< relref "./docs/thirdparty_migration/thidrparty.md" >}}) - - [OpenStack Victoria Deployment Guide]({{< relref "./docs/thirdparty_migration/OpenStack-victoria.md" >}}) - - [Installing and Deploying an HA Cluster]({{< relref "./docs/thirdparty_migration/installha.md" >}}) - - [KubeSphere Installation Guide]({{< relref "./docs/thirdparty_migration/kubesphere.md" >}}) + - [OpenStack-Wallaby Deployment Guide]({{< relref "./docs/thirdparty_migration/OpenStack-wallaby.md" >}}) + - [HA User Guide]({{< relref "./docs/desktop/ha.md" >}}) + - [Deploying an HA Cluster]({{< relref "./docs/thirdparty_migration/installha.md" >}}) + - [HA Usage Example]({{< relref "./docs/desktop/HA_usage_example.md" >}}) + - [KubeSphere Deployment Guide]({{< relref "./docs/desktop/kubesphere.md" >}}) - [Desktop Environment User Guide]({{< relref "./docs/desktop/desktop.md" >}}) - [UKUI]({{< relref "./docs/desktop/ukui.md" >}}) - [UKUI Installation]({{< relref "./docs/desktop/installing-UKUI.md" >}}) @@ -199,4 +212,10 @@ headless: true - [Installation and Deployment]({{< relref "./docs/KubeOS/installation-and-deployment.md" >}}) - [Usage Instructions]({{< relref "./docs/KubeOS/usage-instructions.md" >}}) - [Image Tailoring and Customization Tool]({{< relref "./docs/TailorCustom/overview.md" >}}) - - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) \ No newline at end of file + - [isocut Usage Guide]({{< relref "./docs/TailorCustom/isocut-usage-guide.md" >}}) + - [ImageTailor User Guide]({{< relref "./docs/TailorCustom/imageTailor-user-guide.md" >}}) +- [Gazelle User Guide]({{< relref "./docs/Gazelle/Gazelle.md" >}}) +- [NestOS User Guide]({{< relref "./docs/NestOS/overview.md" >}}) + - [Installation and Deployment]({{< relref "./docs/NestOS/installation-and-deployment.md" >}}) + - [Setting Up Kubernetes and iSulad]({{< relref "./docs/NestOS/usage.md" >}}) + - [Feature Description]({{< relref "./docs/NestOS/feature-description.md" >}}) \ No newline at end of file -- Gitee From 49cbc90dd67eaaee9665645b2fccfc67741cccc1 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Wed, 27 Apr 2022 18:17:13 +0800 Subject: [PATCH 030/130] =?UTF-8?q?=E6=9C=89=E5=A5=96=E6=8D=89=E8=99=ABmas?= =?UTF-8?q?ter=E5=90=8C=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...05\344\270\216\351\203\250\347\275\262.md" | 38 ++++++++--------- ...72\347\241\200\351\205\215\347\275\256.md" | 40 +++++++++--------- ...\273\272\346\214\207\345\257\274.markdown" | 17 ++++---- ...50\346\210\267\351\241\273\347\237\245.md" | 2 +- ...73\347\273\237\345\256\211\350\243\205.md" | 2 +- docs/zh/docs/rubik/figures/icon-note.gif | Bin 0 -> 394 bytes ...05\344\270\216\351\203\250\347\275\262.md" | 2 +- ...24\347\246\273\347\244\272\344\276\213.md" | 2 +- 8 files changed, 52 insertions(+), 51 deletions(-) create mode 100644 docs/zh/docs/rubik/figures/icon-note.gif diff --git "a/docs/zh/docs/A-Tune/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/A-Tune/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" index 730c75141..2f6e33d14 100644 --- "a/docs/zh/docs/A-Tune/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" +++ "b/docs/zh/docs/A-Tune/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -4,15 +4,15 @@ - [安装与部署](#安装与部署) - - [软硬件要求](#软硬件要求) - - [环境准备](#环境准备) - - [安装A-Tune](#安装a-tune) - - [安装模式介绍](#安装模式介绍) - - [安装操作](#安装操作) - - [部署A-Tune](#部署a-tune) - - [配置介绍](#配置介绍) - - [启动A-Tune](#启动a-tune) - - [启动A-Tune engine](#启动a-tune-engine) + - [软硬件要求](#软硬件要求) + - [环境准备](#环境准备) + - [安装A-Tune](#安装a-tune) + - [安装模式介绍](#安装模式介绍) + - [安装操作](#安装操作) + - [部署A-Tune](#部署a-tune) + - [配置介绍](#配置介绍) + - [启动A-Tune](#启动a-tune) + - [启动A-Tune engine](#启动a-tune-engine) ## 软硬件要求 @@ -33,7 +33,7 @@ ## 安装A-Tune -本章介绍A-Tune的安装模式和安装方法。 +本节介绍A-Tune的安装模式和安装方法。 ### 安装模式介绍 A-Tune支持单机模式和分布式模式安装: @@ -113,7 +113,7 @@ A-Tune支持单机模式和分布式模式安装: ## 部署A-Tune -本章介绍A-Tune的配置部署。 +本节介绍A-Tune的配置部署。 ### 配置介绍 A-Tune配置文件/etc/atuned/atuned.cnf的配置项说明如下: @@ -122,25 +122,25 @@ A-Tune配置文件/etc/atuned/atuned.cnf的配置项说明如下: 可根据需要进行修改。 - - protocol:系统grpc服务使用的协议,unix或tcp,unix为本地socket通信方式,tcp为socket监听端口方式。默认为unix。 - - address:系统grpc服务的侦听地址,默认为unix socket,若为分布式部署,需修改为侦听的ip地址。 - - port:系统grpc服务的侦听端口,范围为0\~65535未使用的端口。如果protocol配置是unix,则不需要配置。 - - connect:若为集群部署时,atune所在节点的ip列表,ip地址以逗号分隔。 + - protocol:系统gRPC服务使用的协议,unix或tcp,unix为本地socket通信方式,tcp为socket监听端口方式。默认为unix。 + - address:系统gRPC服务的侦听地址,默认为unix socket,若为分布式部署,需修改为侦听的ip地址。 + - port:系统gRPC服务的侦听端口,范围为0\~65535未使用的端口。如果protocol配置是unix,则不需要配置。 + - connect:若为集群部署时,A-Tune所在节点的ip列表,ip地址以逗号分隔。 - rest_host:系统rest service的侦听地址,默认为localhost。 - rest_port:系统rest service的侦听端口,范围为0~65535未使用的端口,默认为8383。 - engine_host:与系统atune engine service链接的地址。 - engine_port:与系统atune engine service链接的端口。 - sample_num:系统执行analysis流程时采集样本的数量,默认为20。 - interval:系统执行analysis流程时采集样本的间隔时间,默认为5s。 - - grpc_tls:系统grpc的SSL/TLS证书校验开关,默认不开启。开启grpc_tls后,atune-adm命令在使用前需要设置以下环境变量方可与服务端进行通讯: + - grpc_tls:系统gRPC的SSL/TLS证书校验开关,默认不开启。开启grpc_tls后,atune-adm命令在使用前需要设置以下环境变量方可与服务端进行通讯: - export ATUNE_TLS=yes - export ATUNED_CACERT=<客户端CA证书路径> - export ATUNED_CLIENTCERT=<客户端证书路径> - export ATUNED_CLIENTKEY=<客户端秘钥路径> - export ATUNED_SERVERCN=server - - tlsservercafile:gPRC服务端CA证书路径。 - - tlsservercertfile:gPRC服务端证书路径。 - - tlsserverkeyfile:gPRC服务端秘钥路径。 + - tlsservercafile:gRPC服务端CA证书路径。 + - tlsservercertfile:gRPC服务端证书路径。 + - tlsserverkeyfile:gRPC服务端秘钥路径。 - rest_tls:系统rest service的SSL/TLS证书校验开关,默认开启。 - tlsrestcacertfile:系统rest service的服务端CA证书路径。 - tlsrestservercertfile:系统rest service的服务端证书路径 diff --git "a/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" "b/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" index fbb068949..ff5e779e2 100644 --- "a/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" @@ -2,25 +2,25 @@ - [基础配置](#基础配置) - - [设置语言环境](#设置语言环境) - - [显示当前语言环境状态](#显示当前语言环境状态) - - [列出可用的语言环境](#列出可用的语言环境) - - [设置语言环境](#设置语言环境-1) - - [设置键盘](#设置键盘) - - [显示当前设置](#显示当前设置) - - [列出可用的键盘布局](#列出可用的键盘布局) - - [设置键盘布局](#设置键盘布局) - - [设置日期和时间](#设置日期和时间) - - [使用timedatectl命令设置](#使用timedatectl命令设置) - - [使用date命令设置](#使用date命令设置) - - [使用hwclock命令设置](#使用hwclock命令设置) - - [设置kdump](#设置kdump) - - [设置kdump预留内存](#设置kdump预留内存) - - [预留内存推荐值](#预留内存推荐值) - - [禁用网络相关驱动](#禁用网络相关驱动) - - [设置磁盘调度算法](#设置磁盘调度算法) - - [临时修改调度策略](#临时修改调度策略) - - [永久设置调度策略](#永久设置调度策略) + - [设置语言环境](#设置语言环境) + - [显示当前语言环境状态](#显示当前语言环境状态) + - [列出可用的语言环境](#列出可用的语言环境) + - [设置语言环境](#设置语言环境-1) + - [设置键盘](#设置键盘) + - [显示当前设置](#显示当前设置) + - [列出可用的键盘布局](#列出可用的键盘布局) + - [设置键盘布局](#设置键盘布局) + - [设置日期和时间](#设置日期和时间) + - [使用timedatectl命令设置](#使用timedatectl命令设置) + - [使用date命令设置](#使用date命令设置) + - [使用hwclock命令设置](#使用hwclock命令设置) + - [设置kdump](#设置kdump) + - [设置kdump预留内存](#设置kdump预留内存) + - [预留内存推荐值](#预留内存推荐值) + - [禁用网络相关驱动](#禁用网络相关驱动) + - [设置磁盘调度算法](#设置磁盘调度算法) + - [临时修改调度策略](#临时修改调度策略) + - [永久设置调度策略](#永久设置调度策略) @@ -441,7 +441,7 @@ Linux 将时钟分为: ``` ## 设置kdump -本节介绍如何设置kdump预留内存及kdump配置文件参数修改。 +本节介绍如何设置kdump预留内存及修改kdump配置文件参数。 diff --git "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" index d5d41a8bc..1b2fbe654 100644 --- "a/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" +++ "b/docs/zh/docs/Embedded/\345\277\253\351\200\237\346\236\204\345\273\272\346\214\207\345\257\274.markdown" @@ -5,14 +5,15 @@ -- [环境准备](#环境准备) - - [Yocto中主机端命令使用](#Yocto中主机端命令使用) - - [openEuler Embedded所需构建工具](#openEuler Embedded所需构建工具) - - [已安装好工具的构建容器](#已安装好工具的构建容器) -- [版本构建](#版本构建) - - [构建代码下载](#构建代码下载) - - [编译构建](#编译构建) - - [构建结果说明](#构建结果说明) +- [快速构建指导](#快速构建指导) + - [环境准备](#环境准备) + - [Yocto中主机端命令使用](#yocto中主机端命令使用) + - [openEuler Embedded所需构建工具](#openeuler-embedded所需构建工具) + - [已安装好工具的构建容器](#已安装好工具的构建容器) + - [版本构建](#版本构建) + - [构建代码下载](#构建代码下载) + - [编译构建](#编译构建) + - [构建结果说明](#构建结果说明) 环境准备 diff --git "a/docs/zh/docs/Releasenotes/\347\224\250\346\210\267\351\241\273\347\237\245.md" "b/docs/zh/docs/Releasenotes/\347\224\250\346\210\267\351\241\273\347\237\245.md" index 3a48661b2..9fd87a0e9 100644 --- "a/docs/zh/docs/Releasenotes/\347\224\250\346\210\267\351\241\273\347\237\245.md" +++ "b/docs/zh/docs/Releasenotes/\347\224\250\346\210\267\351\241\273\347\237\245.md" @@ -1,5 +1,5 @@ # 用户须知 - openEuler版本号计数规则由openEuler x.x变更为以年月为版本号,以便用户了解版本发布时间,例如openEuler 21.03表示发布时间为2021年3月。 -- [Python核心团队](https://www.python.org/dev/peps/pep-0373/#update)已经于2020年1月停止对Python 2的维护。2021年,openEuler 21.03 仅修复Python 2的致命CVE,已于2020年12月31日全面停止维护。请您尽快切换到Python 3。 +- [Python核心团队](https://www.python.org/dev/peps/pep-0373/#update)已经于2020年1月停止对Python 2的维护。2021年,openEuler 21.03 仅修复Python 2的致命CVE。Python 2已于2020年12月31日全面停止维护。请您尽快切换到Python 3。 - openEuler 22.03-LTS版本开始,停止支持和维护Python 2,仅支持Python 3,请您切换和使用Python 3。 \ No newline at end of file diff --git "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" index 8436fea53..fb6ff44ab 100644 --- "a/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" +++ "b/docs/zh/docs/Releasenotes/\347\263\273\347\273\237\345\256\211\350\243\205.md" @@ -2,7 +2,7 @@ ## 发布件 -openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)、[嵌入式镜像](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表5](#table953512211576)。 +openEuler发布件包括[ISO发布包](http://repo.openeuler.org/openEuler-22.03-LTS/ISO/)、[虚拟机镜像](http://repo.openeuler.org/openEuler-22.03-LTS/virtual_machine_img/)、[容器镜像](http://repo.openeuler.org/openEuler-22.03-LTS/docker_img/)、[嵌入式镜像](http://repo.openeuler.org/openEuler-22.03-LTS/embedded_img/)和[repo源](http://repo.openeuler.org/openEuler-22.03-LTS/)。ISO发布包请参见[表1](#table8396719144315)。容器镜像清单参见[表3](#table1276911538154)。repo源方便在线使用,repo源目录请参见[表5](#table953512211576)。 **表 1** 发布ISO列表 diff --git a/docs/zh/docs/rubik/figures/icon-note.gif b/docs/zh/docs/rubik/figures/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 diff --git "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" index a18043eef..3669c4294 100644 --- "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" +++ "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -53,7 +53,7 @@ rubik以k8s daemonSet形式部署在k8s的每一个节点上,故需要在每 ``` -> ![](D:\Typora图片\icon-note.gif)**说明**: +> ![](.\figures/icon-note.gif)**说明**: > > rubik工具相关文件会安装在/var/lib/rubik目录下 diff --git "a/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" index 48895ccce..109179e5a 100644 --- "a/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" +++ "b/docs/zh/docs/rubik/\346\267\267\351\203\250\351\232\224\347\246\273\347\244\272\344\276\213.md" @@ -43,7 +43,7 @@ Server: **在线业务(clickhouse)** -使用clickhouse-benmark测试工具进行性能测试,统计出QPS/P50/P90/P99等相关性能指标,用法参考:https://clickhouse.com/docs/zh/operations/utilities/clickhouse-benchmark/ +使用clickhouse-benchmark测试工具进行性能测试,统计出QPS/P50/P90/P99等相关性能指标,用法参考:https://clickhouse.com/docs/zh/operations/utilities/clickhouse-benchmark/ **离线业务(stress)** -- Gitee From 455800b6feec520f887d90db6a0901878bb0ed45 Mon Sep 17 00:00:00 2001 From: Judith Date: Thu, 12 May 2022 10:36:07 +0000 Subject: [PATCH 031/130] =?UTF-8?q?update=20docs/zh/docs/ApplicationDev/?= =?UTF-8?q?=E4=BD=BF=E7=94=A8GCC=E7=BC=96=E8=AF=91.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...344\275\277\347\224\250GCC\347\274\226\350\257\221.md" | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git "a/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" "b/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" index 57c425e98..8d4e70ee9 100644 --- "a/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" +++ "b/docs/zh/docs/ApplicationDev/\344\275\277\347\224\250GCC\347\274\226\350\257\221.md" @@ -126,7 +126,7 @@ _options_ :编译选项。 _filenames_ :文件名称。 -GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有些大部分并不常用,常用的 _options_ 取值如[表2](#table1342946175212)所示。 +GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但大部分并不常用,常用的 _options_ 取值如[表2](#table1342946175212)所示。 **表 2** GCC常用的编译选项 @@ -214,7 +214,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有
@@ -243,7 +243,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有 - 分别编译各个源文件,之后对编译后输出的目标文件链接。编译时只重新编译修改的文件,未修改的文件不用重新编译。 - 示例:分别编译test1.c,test2.c,在将二者的目标文件test1.o,test2.o链接成test可执行文件。 + 示例:分别编译test1.c,test2.c,再将二者的目标文件test1.o,test2.o链接成test可执行文件。 ``` $ gcc -c test1.c @@ -262,7 +262,7 @@ GCC是一个功能强大的编译器,其 _options_ 参数取值很多,但有 - 资源利用不一样。 - 静态库为生成的可执行文件的一部分,而动态库为单独的文件。所以使用静态库和和动态库的可执行文件大小和占用的磁盘空间大小不一样,导致资源利用不一样。 + 静态库为生成的可执行文件的一部分,而动态库为单独的文件。所以使用静态库和动态库的可执行文件大小和占用的磁盘空间大小不一样,导致资源利用不一样。 - 扩展性与兼容性不一样 -- Gitee From 69cba63a9533905040b733c29fe7c03dc7e83283 Mon Sep 17 00:00:00 2001 From: Judith Date: Thu, 12 May 2022 10:37:20 +0000 Subject: [PATCH 032/130] =?UTF-8?q?update=20docs/zh/docs/ApplicationDev/?= =?UTF-8?q?=E5=BC=80=E5=8F=91=E7=8E=AF=E5=A2=83=E5=87=86=E5=A4=87.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...17\221\347\216\257\345\242\203\345\207\206\345\244\207.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" index 52cc0e383..5e5266e4c 100644 --- "a/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ "b/docs/zh/docs/ApplicationDev/\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" @@ -426,7 +426,7 @@ $ export PATH=$JAVA_HOME/bin:$PATH $ dnf list installed | grep gtk ``` -如果显示gtk2或者gtk3,则表示您已安装该库,可以直接跳过进入下一步,否则在root权限西下运行如下命令自动下载安装gtk库。 +如果显示gtk2或者gtk3,则表示您已安装该库,可以直接跳过进入下一步,否则在root权限下运行如下命令自动下载安装gtk库。 ``` # dnf -y install gtk2 libXtst libXrender xauth @@ -448,7 +448,7 @@ $ mkdir ~/.ssh 然后在.ssh目录下编辑config文件并保存: -1. 使用vim打卡config文件 +1. 使用vim打开config文件 ``` $ vim config -- Gitee From 9d5f232a3a1cd14d97743f6cb8457656c67c5ddb Mon Sep 17 00:00:00 2001 From: Dream03 Date: Mon, 16 May 2022 07:37:49 +0000 Subject: [PATCH 033/130] =?UTF-8?q?update=20score=5Fadmins.yaml.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=94=A8=E6=88=B7=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- score_admins.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/score_admins.yaml b/score_admins.yaml index fd5ef5469..b1a8b426a 100644 --- a/score_admins.yaml +++ b/score_admins.yaml @@ -2,4 +2,5 @@ score_admins: amy_mayun zhangcuihong lanlanbenming - rachel_123456 \ No newline at end of file + rachel_123456 + hebin03 \ No newline at end of file -- Gitee From 3e4ca3d2d71042486338c0aaa1257df316f63e77 Mon Sep 17 00:00:00 2001 From: Fisher Date: Wed, 18 May 2022 07:24:31 +0000 Subject: [PATCH 034/130] =?UTF-8?q?=E3=80=90=E6=9C=89=E5=A5=96=E6=8D=89?= =?UTF-8?q?=E8=99=AB=E3=80=91=E8=99=9A=E6=8B=9F=E5=8C=96=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=8C=87=E5=8D=97=E9=83=A8=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...\277\201\347\247\273\350\231\232\346\213\237\346\234\272.md" | 2 +- ...\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" | 2 +- ...\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git "a/docs/zh/docs/Virtualization/\347\203\255\350\277\201\347\247\273\350\231\232\346\213\237\346\234\272.md" "b/docs/zh/docs/Virtualization/\347\203\255\350\277\201\347\247\273\350\231\232\346\213\237\346\234\272.md" index e0ae48c4e..efc870807 100644 --- "a/docs/zh/docs/Virtualization/\347\203\255\350\277\201\347\247\273\350\231\232\346\213\237\346\234\272.md" +++ "b/docs/zh/docs/Virtualization/\347\203\255\350\277\201\347\247\273\350\231\232\346\213\237\346\234\272.md" @@ -63,7 +63,7 @@ 例如,指定名为openEulerVM的虚拟机,计算时间为1s: ``` -virsh qemu-monitor-command openEulerVM '{"execute":"calc-dirty-rate", "arguments": {"calc-time": 1}} +virsh qemu-monitor-command openEulerVM '{"execute":"calc-dirty-rate", "arguments": {"calc-time": 1}}' ``` 间隔1s后,查询脏页变化速率: diff --git "a/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" "b/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" index af14e6720..7f47246ec 100644 --- "a/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" +++ "b/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" @@ -385,7 +385,7 @@ Libvirt组件提供了一组查询虚拟机状态信息的命令,包括虚拟 - diff --git "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index 43af4bcd2..9c858c51b 100644 --- "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -663,7 +663,7 @@ XML中还有一部分体系架构相关的配置,这部分配置包括主板 - os:定义虚拟机启动参数。 - 子元素type:指定虚拟机类型,属性arch表示架构类型,如aarch64,属性machine表示虚拟机的芯片组类型,虚拟机支持的芯片组可以通过 **qemu-kvm -machine ?**命令查询,如AArch64结构使用“virt”类型。 + 子元素type:指定虚拟机类型,属性arch表示架构类型,如aarch64,属性machine表示虚拟机的芯片组类型,虚拟机支持的芯片组可以通过 **qemu-kvm -machine ?** 命令查询,如AArch64结构使用“virt”类型。 子元素loader:指定加载固件 ,如配置EDK提供的UEFI文件,属性readonly表示是否是只读文件,值为“yes”或“no”,属性type表示loader的类型,常用的值有“rom”、“pflash”。 -- Gitee From 0d030f27b26df95f3cd8bfa3933d502975f2c43c Mon Sep 17 00:00:00 2001 From: x30004928 Date: Sat, 14 May 2022 15:23:19 +0800 Subject: [PATCH 035/130] =?UTF-8?q?isocut=20=E5=B7=A5=E5=85=B7=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=20kickstart=20=E5=8A=9F=E8=83=BD=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\346\214\207\345\215\227.md" | 158 ++++++++++++++++-- 1 file changed, 145 insertions(+), 13 deletions(-) diff --git "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" index 27ad1109d..dd3eb734a 100644 --- "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -80,9 +80,9 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 ```shell $ sudo isocut -h Checking input ... - usage: isocut [-h] [-t temporary_path] [-r rpm_path] source_iso dest_iso + usage: isocut [-h] [-t temporary_path] [-r rpm_path] [-k file_path] source_iso dest_iso - Cut EulerOS iso to small one + Cut openEuler iso to small one positional arguments: source_iso source iso image @@ -92,6 +92,7 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 -h, --help show this help message and exit -t temporary_path temporary path -r rpm_path extern rpm packages path + -k file_path kickstart file ``` @@ -106,17 +107,18 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 镜像裁剪定制工具通过 isocut 命令执行功能。命令的使用格式为: -**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] < *source_iso* > < *dest_iso* > +**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] [ -k <*file_path*> ] < *source_iso* > < *dest_iso* > #### 参数说明 -| 参数 | 是否必选 | 参数含义 | -| ------------ | -------- | -------------------------------------------------------- | -| --help \| -h | 否 | 查询命令的帮助信息。 | -| -t <*temp_path*> | 否 | 指定工具运行的临时目录 *temp_path*,其中 *temp_path* 为绝对路径。默认为 /tmp 。 | -| -r <*rpm_path*> | 否 | 用户需要额外添加到 ISO 镜像中的 RPM 包路径。 | -| *source_iso* | 是 | 用于裁剪的 ISO 源镜像所在路径和名称。不指定路径时,默认当前路径。 | -| *dest_iso* | 是 | 裁剪定制生成的 ISO 新镜像存放路径和名称。不指定路径时,默认当前路径。 | +| 参数 | 是否必选 | 参数含义 | +| ---------------- | -------- | ------------------------------------------------------------ | +| --help \| -h | 否 | 查询命令的帮助信息。 | +| -t <*temp_path*> | 否 | 指定工具运行的临时目录 *temp_path*,其中 *temp_path* 为绝对路径。默认为 /tmp 。 | +| -r <*rpm_path*> | 否 | 用户需要额外添加到 ISO 镜像中的 RPM 包路径。 | +| -k <*file_path*> | 否 | 用户需要使用 kickstart 自动安装,指定 kickstart 模板路径。 | +| *source_iso* | 是 | 用于裁剪的 ISO 源镜像所在路径和名称。不指定路径时,默认当前路径。 | +| *dest_iso* | 是 | 裁剪定制生成的 ISO 新镜像存放路径和名称。不指定路径时,默认当前路径。 | @@ -126,7 +128,7 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 - 原有 ISO 镜像。该情况通过配置文件 /etc/isocut/rpmlist 指定需要安装的 RPM 软件包,配置格式为 "软件包名.对应架构",例如:kernel.aarch64 。 -- 额外指定。执行 **isocut** 时使用 -r 参数指定软件包所在路径。 +- 额外指定。执行 **isocut** 时使用 -r 参数指定软件包所在路径,并将添加的 RPM 包按上述格式添加到配置文件 /etc/isocut/rpmlist 中。 @@ -135,11 +137,136 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 >- 裁剪定制镜像时,若无法找到配置文件中指定的 RPM 包,则镜像中不会添加该 RPM 包。 >- 若 RPM 包的依赖有问题,则裁剪定制镜像时可能会报错。 - -### 操作指导 +### kickstart 功能介绍 + +用户需要实现镜像自动化安装,可以通过 kickstart 的方式。在执行 **isocut** 时使用 -k 参数指定 kickstart 文件。 + +isocut 为用户提供了 kickstart 模板,路径是 /etc/isocut/anaconda-ks.cfg,用户可以基于该模板修改。 + +#### 修改 kickstart 模板 + +若用户需要使用 isocut 工具提供的 kickstart 模板,需要修改以下内容: + +- 必须在文件 /etc/isocut/anaconda-ks.cfg 中配置 root 和 grub2 的密码。否则镜像自动化安装会卡在设置密码的环节,等待用户手动输入密码。 +- 如果要添加额外 RPM 包,并使用 kickstart 自动安装,则在 /etc/isocut/rpmlist 和 kickstart 文件的 %packages 字段都要指定该 RPM 包。 + +接下来介绍 kickstart 文件详细修改方法。 + +##### 配置初始密码 + +###### 配置 root 初始密码 + +/etc/isocut/anaconda-ks.cfg 中 root 初始密码的默认配置如下,其中 ${pwd} 需要替换成用户实际的加密密文: + +```shell +rootpw --iscrypted ${pwd} +``` + +这里给出设置 root 初始密码的方法(需使用 root 权限): + +1. 添加用于生成密码的用户,此处假设 testUser。 + + ``` shell script + $ sudo useradd testUser + ``` + +2. 设置 testUser 用户的密码。参考命令如下,根据提示设置密码: + + ``` shell script + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. 查看 /etc/shadow 文件,获取加密密码(用户 testUser 后,两个 : 间的字符串,此处使用 *** 代替)。 + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:***:19052:0:90:7:35:: + ``` + +4. 拷贝上述加密密码替换 /etc/isocut/anaconda-ks.cfg 中的 pwd 字段,如下所示(请用实际内容替换 *** ): + ``` shell script + rootpw --iscrypted *** + ``` + +###### 配置 grub2 初始密码 +/etc/isocut/anaconda-ks.cfg 文件中添加以下配置,配置 grub2 初始密码。其中 ${pwd} 需要替换成用户实际的加密密文: +```shell +%addon com_huawei_grub_safe --iscrypted --password='${pwd}' +%end +``` + +> ![](./public_sys-resources/icon-note.gif)说明: +> +> - 配置 grub 初始密码需要使用 root 权限。 +> - grub 密码对应的默认用户为 root 。 +> +> - 系统中需有 grub2-set-password 命令,若不存在,请提前安装该命令。 + +1. 执行如下命令,根据提示设置 grub2 密码: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. 命令执行完成后,会在当前目录生成 user.cfg 文件,grub.pbkdf2.sha512 开头的内容即 grub2 加密密码。 + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.*** + ``` + +3. 复制上述密文,并在 /etc/isocut/anaconda-ks.cfg 文件中增加如下配置: + + ```shell + %addon com_huawei_grub_safe --iscrypted --password='grub.pbkdf2.sha512.***' + %end + ``` + +##### 配置 %packages 字段 + +如果需要添加额外 RPM 包,并使用 kickstart 自动安装,需要在 /etc/isocut/rpmlist 和 kickstart 文件的 %packages 字段都指定该 RPM 包。 + +此处介绍在 /etc/isocut/anaconda-ks.cfg 文件中添加 RPM 包。 + +/etc/isocut/anaconda-ks.cfg 文件的 %packages 默认配置如下: + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +%end +``` + +将额外指定的 RPM 软件包添加到 %packages 配置中,需要遵循如下配置格式: + +"软件包名.对应架构",例如:kernel.aarch64 + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +kernel.aarch64 +%end +``` + + +### 操作指导 >![](./public_sys-resources/icon-note.gif) **说明:** > @@ -200,3 +327,8 @@ openEuler 光盘镜像较大,下载、传输镜像很耗时。另外,使用 ```shell sudo isocut -t /home/temp -r /home/rpms /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso ``` + + **场景三**:使用 kickstart 文件实现自动化安装,需要修改 /etc/isocut/anaconda-ks.cfg 文件 + ```shell + sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso + ``` -- Gitee From 4d732671f83c15da7d945c33cfbf5b8f82cc97d5 Mon Sep 17 00:00:00 2001 From: x30004928 Date: Mon, 23 May 2022 21:29:55 +0800 Subject: [PATCH 036/130] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=BB=98=E8=AE=A4rpm?= =?UTF-8?q?=E5=8C=85=E5=88=97=E8=A1=A8=E5=AE=89=E8=A3=85=E5=A4=B1=E8=B4=A5?= =?UTF-8?q?=E8=A7=A3=E5=86=B3=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\346\214\207\345\215\227.md" | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" index dd3eb734a..14204524b 100644 --- "a/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" +++ "b/docs/zh/docs/TailorCustom/isocut\344\275\277\347\224\250\346\214\207\345\215\227.md" @@ -7,6 +7,8 @@ - [命令介绍](#命令介绍) - [软件包来源](#软件包来源) - [操作指导](#操作指导) +- [FAQ](#FAQ) + - [默认 rpm 包列表安装系统失败](#默认-rpm-包列表安装系统失败) ## 简介 @@ -332,3 +334,51 @@ kernel.aarch64 ```shell sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso ``` + + +## FAQ + +### 默认 rpm 包列表安装系统失败 + +#### 背景描述 + +用户使用 isocut 裁剪镜像时通过配置文件 /etc/isocut/rpmlist 指定需要安装的软件包。 + +由于不同版本会有软件包减少,可能导致裁剪镜像时出现缺包等问题。 +因此 /etc/isocut/rpmlist 中默认只包含 kernel 软件包。 +保证默认配置裁剪镜像必定成功。 + +#### 问题描述 + +使用默认配置裁剪出来的 iso 镜像,能够裁剪成功,但是安装可能失败。 + +安装报错缺包,报错截图如下: + +![](./figures/lack_pack.png) + +#### 原因分析 + +使用默认配置的 RPM 软件包列表,裁剪的 iso 镜像在安装时缺少必要的 RPM 包。 +缺少的包如报错的图示,并且在不同版本中,缺少的 RPM 包也可能是不同的,以安装时实际报错为准。 + +# 解决方案 + +1. 增加缺少的包 + + 1. 根据报错的提示整理缺少的 RPM 包列表 + 2. 将上述 RPM 包列表添加到配置文件 /etc/isocut/rpmlist 中。 + 3. 再次裁剪安装 iso 镜像 + + 以问题描述中的缺包情况为例,修改 rpmlist 配置文件如下: + ```shell + $ cat /etc/isocut/rpmlist + kernel.aarch64 + lvm2.aarch64 + chrony.aarch64 + authselect.aarch64 + shim.aarch64 + efibootmgr.aarch64 + grub2-efi-aa64.aarch64 + dosfstools.aarch64 + ``` + -- Gitee From f7b731c7cf0f2a8dd72da59c2eb07239468e34eb Mon Sep 17 00:00:00 2001 From: gomico Date: Wed, 25 May 2022 18:20:08 +0800 Subject: [PATCH 037/130] revise some KubeOS docs --- docs/en/docs/KubeOS/about-kubeos.md | 12 +++--- .../file-system-layout-of-a-container-os.png | Bin 42326 -> 28281 bytes .../KubeOS/figures/kubeos-architecture.png | Bin 190442 -> 90848 bytes .../KubeOS/installation-and-deployment.md | 39 +++++++++--------- docs/en/docs/KubeOS/usage-instructions.md | 18 ++++---- 5 files changed, 35 insertions(+), 34 deletions(-) diff --git a/docs/en/docs/KubeOS/about-kubeos.md b/docs/en/docs/KubeOS/about-kubeos.md index 0793503e8..54feebcea 100644 --- a/docs/en/docs/KubeOS/about-kubeos.md +++ b/docs/en/docs/KubeOS/about-kubeos.md @@ -4,9 +4,9 @@ Containers and Kubernetes are widely used in cloud scenarios. However, a current manner of managing the containers and the OSs separately usually faces problems of function redundancy and difficult collaboration between scheduling systems. In addition, it is difficult to manage OS versions. Software packages are installed, updated, and deleted separately in OSs of the same version. After a period of time, the OS versions become inconsistent, causing version fragmentation. Besides, the OSs may be tightly coupled with services, making it difficult to upgrade major versions. To solve the preceding problems, openEuler provides KubeOS, a container OS upgrade tool based on openEuler. -Container OSs are lightweight OSs designed for scenarios where services run in containers. KubeOS connects container OSs as components to Kubernetes, so that the container OSs are in the same position as services. The Kubernetes cluster manages containers and container OSs in a unified system. +Container OSs are lightweight OSs designed for scenarios where services run in containers. KubeOS connects container OSs as components to Kubernetes, so that the container OSs are in the same position as services. With KubeOS, a Kubernetes cluster manages containers and container OSs in a unified system. -KubeOS is a Kubernetes operator for controlling the container OS upgrade process and upgrading the container OSs as a whole to implement collaboration between the OS manager and services. Before the container OSs are upgraded, services are migrated to other nodes to reduce the impact on services during OS upgrade and configuration. In this upgrade pattern, the container OSs are upgraded atomically so that the OSs remain synchronized with the expected status. This ensures that the OS versions in the cluster are consistent, preventing version fragmentation. +KubeOS is a Kubernetes operator for controlling the container OS upgrade process and upgrading the container OSs as a whole to implement collaboration between the OS managers and services. Before the container OSs are upgraded, services are migrated to other nodes to reduce the impact on services during OS upgrade and configuration. In this upgrade pattern, the container OSs are upgraded atomically so that the OSs remain synchronized with the expected status. This ensures that the OS versions in the cluster are consistent, preventing version fragmentation. ## Architecture @@ -16,13 +16,13 @@ KubeOS is a Kubernetes operator for controlling the container OS upgrade process ![](./figures/kubeos-architecture.png) -As shown in the preceding figure, KubeOS consists of three components: os-operator, os-proxy, and os-agent. The os-operator and os-proxy components run in containers and are deployed in the Kubernetes cluster. The os-agent component does not belong to the cluster and runs on worker nodes as processes. +As shown in the preceding figure, KubeOS consists of three components: os-operator, os-proxy, and os-agent. The os-operator and os-proxy components run in containers and are deployed in the Kubernetes cluster. os-agent is not considered a cluster component. Its instances run on worker nodes as processes. - os-operator: global container OS manager, which continuously checks the container OS versions of all nodes, controls the number of nodes to be upgraded concurrently based on the configured information, and marks the nodes to be upgraded. - os-proxy: OS manager of a single node, which continuously checks the container OS version of the node. If a node is marked as the node to be upgraded by os-operator, the node is locked, the pod is evicted, and the upgrade information is forwarded to os-agent. -- os-agent: receives information from the proxy, downloads the container OS image used for upgrade from the OS image server, upgrades the container OS, and restarts the node. +- os-agent: receives information from os-proxy, downloads the container OS image used for upgrade from the OS image server, upgrades the container OS, and restarts the node. ### File System of a Container OS @@ -37,6 +37,6 @@ As shown in the figure, a container OS comprises four partitions: - boot partition: GRUB2 file partition. - Persist partition: stores persistent user data. When the container OS is upgraded, the data in this partition is retained. -- Two root partitions: A container OS uses the dual-partition mode with two root partitions, rootA and rootB. Assume that the system runs on the rootA partition after initialization. When the system is upgraded, the new system is downloaded to the rootB partition. GRUB has two boot options: A and B. The default boot option of GRUB is set to B and the node is restarted. After the node is started, the container OS runs on the updated rootB partition. +- Two root partitions: Container OSs use the dual-partition mode with two root partitions, rootA and rootB. Assume that the container runs the OS stored in the rootA partition after initialization. When the system is upgraded, the new system is downloaded to the rootB partition. GRUB has two boot options: A and B. The default boot option of GRUB is set to B and the node is restarted. After the node is started, the container runs the upgraded OS in the rootB partition. -The root file system of the container OS is read-only. Users' persistent data is stored in the Persist partition. +The root file system of a container OS is read-only. Users' persistent data is stored in the Persist partition. diff --git a/docs/en/docs/KubeOS/figures/file-system-layout-of-a-container-os.png b/docs/en/docs/KubeOS/figures/file-system-layout-of-a-container-os.png index b4a3af27b6dd7f23dc6f45ec4601bfceabbf5e9a..add62e72f85b103b7dd5780d2e360049f5f712df 100644 GIT binary patch literal 28281 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 literal 42326 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 VkBC(9HtN9N>43Wf>APbW{tps!E2;nh diff --git a/docs/en/docs/KubeOS/figures/kubeos-architecture.png b/docs/en/docs/KubeOS/figures/kubeos-architecture.png index 7d32855d3167706975c2323109005af3ffb1b4f5..7834a3793b73c49ddd046502c65335a08f576c30 100644 GIT binary patch literal 90848 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

DQ+9|mxdL?!c(ddGMkt$C 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%0A=%#;K2@`kTsf}57)owUC+k- zp18K!@GYPeb@;}F?3>ts@Z`h}reb;I3h+cEzzU&n9e{_YVmqub0lskRY&CA^SM5G< zZ+Vxlgg#+_>^Q4mjUDhQG@do*#hX{M^d8)$!1$(12EzS5laU83i6jgx^<01q6to5U zi|Be24bD}LA!rAsL#uAGGDl-?FXyf{g&u_t9;c7!+puLu&UI-SjQW;|pqkJqqf+>~{sOxz+3BXdmGWFWPI7N?~wANlImbg%nIH2>=? zkLY2$ov?G|hO81$1HZeG%g-JTmoM>84CAM>qyYhtFv}VPx?xg*Et@ce5=Bd0_w|H* zoqy-ZPnU7%M3OhfVD#vRBA1A~eDfd{JJ+s}sRMEavh8y<1+IQJ1=dGwEXmf%8_C1E zY|y-SV{>nk%N=E+((+DHlJ8Muirb+T6k79wmWengm>al-)VZWj>>+re3(d;f(2E+G ziIXfAyYuYi)8xivE*-Xma|-{=742s_9amr-8^i?9q%mR>EBW`toth#Ti`^G^`+3^( z-Q@X7KSbpS$y^z$0moNQjbny3taPYFurx42U?zyZ*B}bT2S$Ee0~o53_Ai0| z3O6X>F6>C2J12rftFU#%)`}RPR^(+buTt2<7A;vPODcG)F4ASfBrmhZH~XrR)!Cp~ z6$91P6>#G`e+>?e3e{cfc_Pkh)7Qt;{R9eLf#ovifx{!CP*X!M<>7A^t;_KoK^C?< z)mG^t6y%mQZMAC1nl7h$kU>*)>IC$87{XESo_2L?@`T2F{wZ<2W9_4>00pA{SqgG` zjZn>nmt^N4ZPoRxOe6``*NNYPMnq&>9IXYFyGkCVWz4kZ&qNO~o+OX~GcfvgqGi--%|2-bBodG=w>fhnnwf z3nZU#q&D`I7}U;^Z;Nl^tANjK_clXbFgBIgq8nJM#v7>3=G`4zS|nP}E^#EzDs7x!b_( ztK0|~m)${X{w{ORN1bjcjIBEA)--MDJ`+~59-0!2qZe5^AMsYh^P4a9SevB9^EmT| zmDZem(?RddpjzpLh9g$RoX?B14Ns0~0%JZc&AIE1Z=o(*=jYE>(G%Ns0e&BMjXF_7 zS>-dF*==99{jcG(ALIMt%KY)Pw)V139=Ckh-O&2(j$&9_6ym4bdK{~7T*if3MNB-Z z37p_tcOCKdcys0xVVh<@e^)4F=RE8Mqs&~2>A4;3xZo0rhi+0>4czgVw7fH`O#dod z@@U?fePBcPDIl34|4L>yJt~b`wh1hStZ>uhS}-s39wSFVz;NXcsJ;4Ib)G|AxDyp# zV8Qk%fdn~9{iHaTQgv;HE!f&fv{P+(fZ%HU;JwUl!M9`KWLEKtjB+bs^5xR7=mbW+ zYR3v0G^=!#p0eIi*7SZei#upV9FRiHoaE#d8qy->2oJW$ciFHV>ef)vcvZtXyuzAT z`hx>+-19oDSkGFwuZvs^%dHqW^N>nh>JJ*Y3wOUZagc*0QFkD<8v6q7;k(-u2TidCR;n0Mm$`<Fdo07&Mt+P>?{$+!5N}{*nQyLz_7(5Qxmt}&GKzdLERFD;-_du#syyN=?GZ-Qk>s~ z`wy$HFA53JZy>)cn`Zkqd+G$HnE7v<1!tPCA{ehTL|lg6&^5H9TfBz}JLch03Q zJ^OVpXWO4GU7!jt8;5#`+z$gEC7z*1cQ-U3wI{YC4WlWw{uVjc%{d;tRUV<|yq`Cv zf!?^^D~Ab%#ur4pOARiAu3mioHG|u#958)laA}(E!*zNYj>=dJ*hg?}U*MCXe@;)9 z`v^>+PKkH&GAaU&E&Hdr&V~saDYv&SXtlNv?A4rI$4{1bWNek^Yt1gM*y3snXXjB> zmq&sU=WWx0K05DJyN7}=V#iA*ONT@~h)M_>1*S{e{4b~Vd^;@@^W%@*K5iX;dwtGv ze<${;K&nd2Y~5DmrDOBvq*b|NU8`ZqX7gH^<4k$O)uCd2igRRXEMPsfsGq~Q(}Dq8 ze5SmQ0))Egk3dOb4muF@XBK+tf)Ovso@fvhSswKI60@k-<<<9Idw;7rfg4bQ}Sm&q} zF9(d($xaT^XeM}JljNT4LqX2Q&cv8tGAv*Mkm- zcIcdM-maTCGs{+4N9Iu8rz|$S{MrQ@+%PcVBAd-pL7+j$qcdev<0)Ak~?O!9V zba45@-F9Utr<7DaK4lZX-()-r`=f@o{e_cfpfWF2(YB|f*p^E=;i3I#&iYP?Y+qcF z4m9NO@rmRjh{)rxd-g}^{n@r-LhRF^`HaV0=TlECAuvk@bG;)zz+R}y3=eN^l3j&@t%&UkOPDQbSHqgyi_bs-YkbchUZEYSp*FO%{14>s6wr^DS z*(Iv+c*5E387g98I=;~Vt|tTfG6Bz(t-jRHvMNxt#z?plowzx-NIvfU)=)|Yc7 z0*K5j*~=_E58WV1tl1BXUCwTbs5-W^@uHC_NAya6)#WN?&2lj6y&8ziEw<1T71sKi zdG-9zrtQbQdBb!45vYZc)_E4)MA4X4Q=4r6P8c3+<1Xn7LE)yj*zgnbM?!DUAc-JF5G!&8HjA33(Ty+3Lj#Q}Ty zI850e*o1fA`{8h4;F0}xV|HxO zq4o8i=>592=^NkTKN_qwkGs%Z3pNweVa2SFN?iCbJ=)fllTDM&XJt81?g{%b6nwmSz0fNOQ|5Pk*gOnHXhmry zLmIJm?L3CX5xqpy%lx!EcLgth<(R9aI0x*h-0@B0EX>=fCMY>(ud~a+){f6QywjyS zr=-xsB3o8~Q*_IiUYHEzu0&{TBPf(9&|n{p{RE%F?jU5Ok%4e0{Oh;M4l8$Z(BaHy zEs7IK#Hd+@;Bk;1zhemF%(!B#0QTTPNb41iT3yWqZ)C9!7Y(a}#<@(LH;O^rs|fAB zgJSn+Tv0yWM{8C|=!(tG$05HDKLF>xJgv91KQ~Cf*L05%``p%E&oM{1x~bldmT!P0?(PIN8Oj-lP4+sOBUtp@Pe4po zKeB^n52K1m)!pL9?vYcckF6~uzffnizOp_Ef*e) z7@+KSLWPJ9E6#ov$ebFOJvys`+JYsY0@SO0boLyQoU7ri+$}e#JIW!stp`r;Am}vG z3s7S$Ez_h*a@0Ax(6on97XbE;Req`AgrY1tSy@u6Lt~pw=LDzj#)%|kC*ES^>f49L zExW=#GLYK3V5yHq(Xm>t@F`syPtk;^%?lSo3{#T_ROJclX^U2$0=y z2|?(Dy11}(|4$naxm2F_Y1~c|$DdL%EYxgHr+?e?{VI}F8tgh!_&uAlWHUR9AUd+9 z))g(=)ZdQ?z)%bMpewXn!C38~eD&F&LFBk|ywpGB>y`F2e+_rxDpZCX#Aj8!CamWcKm{!V0&2{lD@y9dQDK%U&|hg?Q>qsxU`!cokgo@ z^R!j@u9f?6@-T7@AC`s%UGlJcSzm0N;m09!r<4Z6;Y^MwP?0drHXJfk<#sG2u3d62 zc)Tp=K~!r0v|BO0bsPvboJ9GW94$^MU)Ti>3XL9AoGqnAiple4;8g~A*%ZRO_})V(t$tx;3U&tpB-s* zSvmdXAuJAd^=i1ac#WaRNd0=WGk z=`Nc9%D`XvC@-G1bSYWkQQ$43$18j|ao(deDBs~Lkd8SvjAn1i+u8K_7XpezlFL6OlIF`53>LMNXYC^~7h!^$6Gad$%ymgZfs zY8Srt392imIg!8JYWF&yI$XC@t9Q($)={@QHfxD`Iwx?#BklXtDAZEJ5CRaJdsbtz zQ|v2_?5fBe4RHl4STeb01y@b%^bRdW&3;v~#4ziaqWX53$D?^hQD3)k^R&DonJO*! zW_5CM5K1%`x|B&V3;V$^=ysXKBGQJUS2(Bw*R(_<&e8^J;oH;7y>f;DXdgTnbkU2o zFMPEst7gXj);n4$fOPfw&D{Frjih6yHSfgtuau&PnSMSnE#rq>Dn^WM^WsooAM!d0 z`wu)6$AEWOC@tlh_y1VWW;?O&kvY}>KiWI9pr*1kj-$5Hf{3kz%|Ym?W@#W|%c6iW zwk<(LRs%vX2*Y9s1Y}hS1eb!A0Ma6xYyl#K1VUJhERjS&Kx7F40!qM$vW7(@2}>Y2 z7wPKinyPu3=eZB};numQ&OLSN`~KhWe@`9#QJs(%fE43qSQ!sVmi@JAg4c)M;0fvA zBtfptl#(RO|9~^wyWg{NIH!TS%x6$vvz547*Li^CoKR{BiBK$gI4JC1ie`wrDyxh4 zY0iw9HP-4btvlSW_(Y9qh%ZSAU#Yo8Px2(S8R;%~^%vq6Perf-0dTC9|M8kC7-_M5 zw+C0hTz}am%^+XfI_{0BP3@X*xO3p)VeeD}e3qB0-WE~!>H<5T(gTL50ELaKfl_#S6 z5eyjU44sP4LMXe^whG?BHk60(2PXd^8e9JsH?}!VNdGxW5=MPLKRje_7+n5wE`yHk zbU}YlfQV#aZ0`9}HX9PZB#+QIgUC7;dtJ6FbrtJsg@GJ$9-^7exRn)tumRSaPSG*- zyWdpqI=B!;D)OW}0#fq3Bz;eqqZhoh5^V_*!AI~##qRXvRK$nAg8qXxu1;p>;?97O z;TOvMCKO3#=18h%m&JjgrrBjNL+)1CP{iJ*-WoJ3QyaVG9o`MG> z-Yg^JiHJ5AOn(UcWW@vg%NX!jE*p`Wn5N%FsVkqj+cMWTUYZ;gT&xXfr+@k1wc<@n z;3pMUNDr;px(e-FGkrg^%Ae$0J2W!JKUU{kQ<_Wh<%JqQT0DFnJA82B$3$jubEBh3 z9OS!qp}JI$w&L*|E@}i7Q?0CS&6oLRg&6`YR4>Wnh(fvGop<(p>0OKNu3k^l9s^TX zQd8@qy+Sx;m9*nrH?wysMt!kQrfiRVZ3S-%zf9N+FX&(96p-<>Y;&h|4>0*eL15+c z>b-HCV=Yg8skntv^EliE4~65uH+3uQW?XHD=^vR~^_8P1VN`R=1HIsU73-C}P~eE@ z1=#}A&akD@XsFiJNa%*SQ9UvzrS1s$ni$i!rp&%Ndl4@-tW?}6KLGg*-!-9+KbnV} z{v5X_Yn=`RTQ4cP9tT4Y$k2O8W++Pt)RrB|y+htpb~DKQ>R3U582~^J*oPP;QKoA{ zxIwel*Di^OrcrL1^!F;gsp|@2^Vtl{O=h8w(28zhcyrtKU}FIv|2Bk%tbgU|QMgF4s14jCVb*q>*^`i=fw zg^>j!mKuqkai>F;)QBmf8^*eZ!niYhBY_3=E5BBnB~B)8G@?9XD*Q_0cM>EYzqCxQ z?W9VE9Hso{v)~ZT+_jUOhkdJTt;ntxtX)G<3@L_1k%}7~pEQ>)bC18ujwpkU3pgL0 zzm{`)?ZoX3Y@seKJXuq)z*BcqrHA>Gk<`>jb)VZeOs7wJm5?M@=@01(PfnBeEm$;Z zR7K88Z$K;v85fVd55V(bQ~g4iX`)$fVzb_zOXs!$_ve$|w#HIh=r^$i+Kz zpxkyvWi&s?C@GvLuUL2N(6j0b`M(U$RpoC!x!#QyJ@<|jVFo;D8Cl#rRrn{3?yO0I zBc-YC#y$lf%1bplB4XhL+7B7s?uJK{mN zWvgJ^Y6yJ06_+7eQN-K$wC%v?q3S#^*}|}IxUw!V??pzl3h(7^s-8E{e)etKVWJV#(kL$}L*TdF+=)(R7BA(|;0KpDjF=iBRQgekb-9X0wjcuheKB!q89i zB{mwmq?yjmdLEfjJ7ACYM~X)gLDvY1@bY=rsKzMdO6ed{V}!^Lo&gBN+`29DK8uaT zBN>uiQt7}&Irkx$QE{2?qL4%d3L~jk#_(vx`!js#>{`C5^mt>V)SSx_xOT)jT3NBx zyfY;Cikt|@#U360(NT90Gh#o86#+?}pCx09CK61`!aK3pPHJ@F ztdo~XE~$3Z9pat=thzelcJTFqfPZH2i#}%h9TupiA|hR^oVw!&mYxv}tqq4^oYbnJ zj=hTUDeoMSfK%Km77#_)jB^6AvsyO2->y zSDiBZkX4>UO^1O%xo)Msn1Lj9&@E!mW7SKL86I%V(PuL6DQq2e2Y$bUG55A(<+uAJ z3l=jal}&1LN7DQh{TZKR*=d%35B6M^{&Gck;ZbZ`Zl2NY!yuGOx9hCzPynCTkvwNS zs(7>{$oe2>2uME%pidlB6&$~o{&Tb`PuEGpiD7C&0$H=%Yl0Q5fEi`Wmb&n(sg==C z%ESPdWd)Lp?G3YGd^Iju}||KYf}*=BL?Cc0hDg|xx)5$>C!Whv?-mL84k{#Q5!C$ zbu5czrBgEWUyUOof<_g)^=%;;J+w%QZNq7R;79s9J$kh4kCAAr+$F!kztajC_ z!-t&WvO{=`Zd7fsJI7fzyT%-l(6`<^ZAO*oP>vxu#<0B?_5%`z@u#qqk$Fi4f?Ynx zbMAr1Wn{7?uP$CO5}fmkIvrDT&KQ-=ou0|x2(e`C;}6oYwA(YU0>5E@y`+*@H~^{I z$V8O}UEIJRB#4vbC`TMe17OAH#CFvL__B5B!1zuePA_gL_?okqGgmubO{+&xRoJ+> zOvpaAo;K)Pa#DhQIt1QThP%N2+!fEv8oBj1s}krYsCXPm>w4BcvP+x!L0N2U_kF@OkubUoSFuIX6ShhE){EL8Smq_ZU`dyHQ`k-u-Zud@+9gOY z8D+Un$1;JoUw)7yGJ}_)Y!MsqeGdZe>>9vfeSn`8w(7obUodH}7me-^QNc^Ppo3?R zpOlziGxP3Lv56J!cv`jlu{?_rI@t4?;CuG`b+P^V(uZYJgQ9m6yK)s6RZs40})40}_PBKn&Fziq|8I#sx7?PYQyPd1b_{Pbc9jZ5xJ z_{*gK)2>hb@r&t8paBA*{N45t|9{_}fuIat&^lCnPd_JF+3DuivkO*s=PJ&6-upM% CKD-YA diff --git a/docs/en/docs/KubeOS/installation-and-deployment.md b/docs/en/docs/KubeOS/installation-and-deployment.md index 1ce8f8070..0c0d8cf5c 100644 --- a/docs/en/docs/KubeOS/installation-and-deployment.md +++ b/docs/en/docs/KubeOS/installation-and-deployment.md @@ -45,7 +45,7 @@ This chapter describes how to install and deploy the KubeOS tool. To install KubeOS, perform the following steps: -1. Configure the Yum sources: openEuler 21.09 and openEuler 21.09:EPOL: +1. Configure the Yum sources openEuler 21.09 and openEuler 21.09:EPOL: ``` [openEuler21.09] # openEuler 21.09 official source @@ -108,9 +108,9 @@ Before using Docker to create a container image, ensure that Docker has been ins 4. Compile a Dockerfile to build an image. Pay attention to the following points when compiling a Dockerfile: - * The os-operator and os-proxy images must be built based on the base image. Ensure the security of the base image. + * The os-operator and os-proxy images must be built based on the base image. Ensure that the base image is safe. * Copy the os-operator and os-proxy binary files to the corresponding images. - * Ensure that the **root** owner and owner group are assigned for the os-proxy binary file in the os-proxy image, and the file permission is **500**. + * Ensure that the owner and owner group of the os-proxy binary file in the os-proxy image are the **root** user, and the file permission is **500**. * Ensure that the owner and owner group of the os-operator binary file in the os-operator image are the user who runs the os-operator process in the container, and the file permission is **500**. * The locations of the os-operator and os-proxy binary files in the image and the commands run during container startup must correspond to the parameters specified in the YAML file used for deployment. @@ -128,9 +128,9 @@ Before using Docker to create a container image, ensure that Docker has been ins ENTRYPOINT ["/operator"] ``` - You can build the Dockerfile in multiple phases. + Alternatively, you can use multi-stage builds in the Dockerfile. -5. Build the images to be deployed in containers (os-operator and os-proxy images). +5. Build the images (the os-operator and os-proxy images) to be included in the containers OS image. ```shell # Specify the Dockerfile path of os-proxy. @@ -142,7 +142,7 @@ Before using Docker to create a container image, ensure that Docker has been ins docker build -t ${IMG_PROXY} -f ${DOCKERFILE_PROXY} . ``` -6. Push the container images to the image repository. +6. Push the images to the image repository. ```shell docker push ${IMG_OPERATOR} @@ -155,29 +155,29 @@ Before using Docker to create a container image, ensure that Docker has been ins #### Precautions * The **root** permissions are required for creating a container OS image. -* The RPM package source of the container OS image build tool is the full ISO file of openEuler, for example, **openEuler-21.09-everything-x86_64-dvd.iso**. -* By default, the container OS image built using the default RPM list is stored in the same path as the build tool. This partition must have at least 25 GiB free disk space. +* The RPM package source of the container OS image is the Everything and EPOL repositories of a specific version of openEuler. You are advised to configure both the Everything and EPOL repositories as Yum sources in the repo file provided for creating the image. +* By default, the container OS image built using the default RPM list is stored in the same path as the build tool. This partition must have at least 25 GiB free space. * When creating a container OS image, you cannot customize the file system to be mounted. #### Procedure The command for creating a container OS is as follows: -`generate.sh` *ISO_PATH VERSION AGENT_PATH ENCRYPTED_PASSWD* +`generate.sh` *REPO_PATH VERSION AGENT_PATH ENCRYPTED_PASSWD* The parameters are described as follows: -- `ISO_PATH`: full ISO file path +- `REPO_PATH`: repo file path - `AGENT_PATH`: os-agent binary file path * `VERSION`: version of the created container OS image -* `ENCRYPTED_PASSWD`: password of the **root** user of the container OS image. The password is encrypted with a salt value and can be generated using OpenSSL or KIWI commands. +* `ENCRYPTED_PASSWD`: password of the **root** user of the container OS image. The password must be encrypted and salted. You can generate a password using OpenSSL or KIWI commands. To create a container OS, perform the following steps: -1. Go to the execution directory. +1. Go to the working directory. ```shell cd /opt/kubeOS/scripts @@ -186,31 +186,32 @@ To create a container OS, perform the following steps: 2. Run `generate.sh` to create the container OS. The following is a command example: ```shell - bash generate.sh openEuler-21.09-everything-x86_64-dvd.iso v1 ../bin/os-agent '''$1$xyz$RdLyKTL32WEvK3lg8CXID0''' + bash generate.sh xx.repo v1 ../bin/os-agent '''$1$xyz$RdLyKTL32WEvK3lg8CXID0''' ``` + In the command, **xx.repo** indicates the actual Yum source file used for creating the image. You are advised to configure both the Everything and EPOL repositories as Yum sources. After the container OS image is created, the following files are generated in the **/opt/kubeOS/scripts** directory: - **system.qcow2**: system image. The default size of **system.qcow2** is 20 GiB. The size of the root file system partition is less than 2020 MiB, and the size of the Persist partition is less than 16 GiB. - **update.img**: partition image of the root file system that is used for upgrade. - The created container OS image can be used only in the VM of the x86 or AArch64 architecture. + The created container OS image can be used only in a VM of the x86 or AArch64 architecture. ### Deploying CRD, os-operator, and os-proxy #### Precautions -* Deploy the Kubernetes cluster first. For details, see the _openEuler 21.09 Kubernetes Cluster Deployment Guide_. +* The Kubernetes cluster must be deployed first. For details, see the _openEuler 21.09 Kubernetes Cluster Deployment Guide_. -- The OS of the worker nodes to be upgraded in the cluster must be the container OS built using the method described in the previous section. If it is not, use **system.qcow2** to deploy the VM again. For details about how to deploy a VM, see the _openEuler 21.09 Virtualization User Guide_. Currently, the master nodes do not support container OS upgrade. Use openEuler 21.09 to deploy the upgrade on the master nodes. -- Compile the YAML files for deploying CustomResourceDefinition (CRD), os-operator, os-proxy, and role-based access control (RBAC) of the OS. +- The OS of the worker nodes to be upgraded in the cluster must be the container OS built using the method described in the previous section. If it is not, use **system.qcow2** to deploy the VM again. For details about how to deploy a VM, see the _openEuler 21.09 Virtualization User Guide_. Currently, KubeOS does not support the master nodes. Use openEuler 21.09 to deploy the upgrade on the master nodes. +- The YAML files for deploying CustomResourceDefinition (CRD), os-operator, os-proxy, and role-based access control (RBAC) of the OS need to be compiled. - The os-operator and os-proxy components are deployed in the Kubernetes cluster. os-operator must be deployed as a Deployment, and os-proxy as a DaemonSet. -- Deploy Kubernetes security mechanisms, such as the RBAC, pod service account, and security policy. +- Kubernetes security mechanisms, such as the RBAC, pod service account, and security policies, must be deployed. #### Procedure -1. Prepare YAML files, including those used for deploying CRD, RBAC, os-operator, and os-proxy of the OS. For details, see [YAML examples](https://gitee.com/openeuler/KubeOS/tree/master/docs/example/config). The following uses **crd.yaml**, **rbac.yaml**, and **manager.yaml** as examples. +1. Prepare YAML files used for deploying CRD, RBAC, os-operator, and os-proxy of the OS. For details, see [YAML examples](https://gitee.com/openeuler/KubeOS/tree/master/docs/example/config). The following uses **crd.yaml**, **rbac.yaml**, and **manager.yaml** as examples. 2. Deploy CRD, RBAC, os-operator, and os-proxy. Assume that the **crd.yaml**, **rbac.yaml**, and **manager.yaml** files are stored in the **config/crd**, **config/rbac**, and **config/manager** directories, respectively. Run the following commands: diff --git a/docs/en/docs/KubeOS/usage-instructions.md b/docs/en/docs/KubeOS/usage-instructions.md index 9e54dda2e..1c9c6738f 100644 --- a/docs/en/docs/KubeOS/usage-instructions.md +++ b/docs/en/docs/KubeOS/usage-instructions.md @@ -24,14 +24,14 @@ ## Precautions -1. KubeOS provides atomic upgrade for all software packages. By default, single-package upgrade is not supported. +1. KubeOS upgrades the container OS in an atomic manner, where all software packages are upgraded at the same time. By default, single-package upgrade is not supported. 2. KubeOS supports container OSs with two partitions. Partitions more than two are not supported. 3. You can view the upgrade logs of a single node in the **/var/log/messages** file on the node. -4. Strictly follow the upgrade and rollback processes described in this document. If the processes are invoked in an abnormal sequence, the system may fail to be upgraded or rolled back. +4. Strictly follow the upgrade and rollback procedures described in this document. If the steps are performed in a wrong sequence, the system may fail to be upgraded or rolled back. ## Upgrade -Compile the YAML file to deploy the instance of the OS custom resource (CR) in the cluster. The following is an example YAML file for deploying the CR instance: +Compile the YAML file for deploying the OS as a custom resource (CR) instance in the cluster. The following is an example YAML file for deploying the CR instance: ``` apiVersion: upgrade.openeuler.org/v1alpha1 @@ -50,15 +50,15 @@ Parameter description: | Parameter | Description | Mandatory (Yes/No)| | -------------- | ----------------------------------- | -------- | -| osversion | Address of the image used for the upgrade | Yes | -| imageurl | Version of the OS image used for the upgrade | Yes | +| osversion | Version of the OS image used for the upgrade | Yes | +| imageurl | Address of the OS image used for the upgrade | Yes | | maxunavailable | Number of nodes that are upgraded concurrently | Yes | | checksum | Checksum (SHA-256) value of the image used for the upgrade| Yes | | flagsafe | Whether `imageurl` specifies a secure address| Yes | -The address specified by `imageurl` contains the protocol. Only the HTTP or HTTPS protocol is supported. If `imageurl` is set to an HTTPS address, secure transmission is used. If `imageurl` is set to an HTTP address, set `flagsafe` to `true`, because the image can be downloaded only when the address is secure. If `imageurl` is set to an HTTP address but `flagsafe` is not set to `true`, the address is insecure by default. The image will not be downloaded, and a message is written to the log of the node to be upgraded indicating that the address is insecure. +The address specified by `imageurl` contains the protocol. Only the HTTP or HTTPS protocol is supported. If `imageurl` is set to an HTTPS address, secure transmission is used. If `imageurl` is set to an HTTP address, set `flagsafe` to `true`, because the image can be downloaded only when the address is secure. If `imageurl` is set to an HTTP address but `flagsafe` is not set to `true`, the address is considered insecure by default. The image will not be downloaded, and a message is written to the log of the node to be upgraded indicating that the address is insecure. -You are advised to set `imageurl` to an HTTPS address. In this case, ensure that the required certificate has been installed on the node to be upgraded. If the image server is maintained by yourself, you need to sign the certificate and ensure that the certificate has been installed on the node to be upgraded. Place the certificate in the **/etc/pki/ca-trust/source/anchors** directory of the container OS and run the `update-ca-trust extract` command to install the certificate. The administrator specifies the address and must ensure the security of the address. The intranet address is recommended. +You are advised to set `imageurl` to an HTTPS address. In this case, ensure that the required certificate has been installed on the node to be upgraded. If the image server is maintained by yourself, you need to sign the certificate and ensure that the certificate has been installed on the node to be upgraded. Place the certificate in the **/etc/pki/ca-trust/source/anchors** directory of the container OS and run the `update-ca-trust extract` command to install the certificate. The administrator specifies the address and must ensure the security of the address. An intranet address is recommended. Assume that the YAML file is **upgrade_v1alpha1_os.yaml**. @@ -82,7 +82,7 @@ kubectl get nodes -o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.osI > ![](./public_sys-resources/icon-note.gif)**NOTE**: > -> If the upgrade needs to be performed again, modify the `imageurl`, `osversion`, `checksum`, `maxunavailable`, or `flagsafe` parameter in the **upgrade_v1alpha1_os.yaml** file. +> If the upgrade needs to be performed again, modify the `imageurl`, `osversion`, `checksum`, `maxunavailable`, and `flagsafe` parameters in the **upgrade_v1alpha1_os.yaml** file. ## Rollback @@ -107,7 +107,7 @@ Manually restart the node and select the second boot option to roll back the con After the update is complete, the node rolls back the container OS based on the configuration information. -3. Check the OS version of the container on the node to determine whether the rollback is successful. +3. Check the container OS version on the node to determine whether the rollback is successful. ``` kubectl get nodes -o custom-columns='NAME:.metadata.name,OS:.status.nodeInfo.osImage' -- Gitee From 64ca75a6354070ea75862ce7b23722c793ca9f7c Mon Sep 17 00:00:00 2001 From: x30004928 Date: Sat, 28 May 2022 16:26:34 +0800 Subject: [PATCH 038/130] =?UTF-8?q?isocut=E4=BD=BF=E7=94=A8=E6=8C=87?= =?UTF-8?q?=E5=8D=97=E6=B7=BB=E5=8A=A0lack=5Fpack.png=E5=9B=BE=E7=89=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/TailorCustom/figures/lack_pack.png | Bin 0 -> 33182 bytes ...\277\347\224\250\346\214\207\345\215\227.md" | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/zh/docs/TailorCustom/figures/lack_pack.png diff --git a/docs/zh/docs/TailorCustom/figures/lack_pack.png b/docs/zh/docs/TailorCustom/figures/lack_pack.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b7f1da15da70f63a86aae360e89017c2b98f2d GIT binary patch literal 33182 zcmd42cQ~8>A3kc-s$H$vv!ZH*QhU^^<^Ns%W_$<> zyS-8w-d?#8N15Y(MTs;)R0DhW_9`-45oLJ$F{KrXd+`5mz-99p^WeWLsgVC) z-b(p<)B>k6aYPFL|Ne7Q^jqyrF_Aas26s|`Fq?sNwrlig{C^fGwb09WIp~e0JqZ3k zruY>7e`;Nz7K;o_z+tNHX~{x^h{I$JpTm3=&yIo%he?~sJvIecvfrQWL(Fhjh5ba? zi0%ac4Jg_z<>mFLFU2+8fr=@@*+MDg&jJ*16%jtWkt;{-?swFy(ytF|Ae@OP!~fB$LupBa9)X3)Twf!Y-3=jTqV zSJ!>ZFHB5WroH#>5mPZT37Ir}_Pf0qExf>Ve2~2>quNHP-mJBA$MvrovEe9bJG%bTgeru=KWdf)8Q@>%bVaU%e8DN z%asigwuw~7nOSFv9smO5M7YeWbC%hIEp zzG&Crvk4jJAyimuJX(twv!4hTS?-OXO^xH}PYoj^p$fgaJd5BPEsU__Ru8iiwGLN~ zp!UyPmeb3Ten2m1gc{$+9b8i_bH8;a!hiMG8#7`Ic3uRimqTw*Zp6F>GFh33V^!cR zF|8MxZ954FhI=ox3H$HORyg0Z3HKpCTqZcvvto=uZ>z*&vm}R&py!&={Snk`q1@_m zp&8Zdp-bP?BG7caQ>}o|6K3&H>}bZtH|@ed=}YH8-8lVl{*r;yohiC9)8;MsPr9uG zUn{?B?0Loe6Q-cM?X5t)Ec!S$Ii|r}Ip(#&Ja+k;rsqEvezBcG~u6Nq7+>9&_cH+4)RTLlf zJHc`zl6H?y8#CAJ9YF@Py`*NkPfWpf&+lY+-PLKniD$OSw`-pk;k-}^l=D9J#BW5=|V$KkdyXv>LGqp7Hw$`-3UGJJrE)yV>abQy8 z5e1?Nr(oYhyTY!&hFvFeoXff#d;u{*{79Hqq876198NKP6B19~he^4wTM@}lc<+tR zsk$mEDt^_Dc$+~rl)8CrRNZpz8f2;XjMX(;nAGCX^WxYJuwN4)P092&YhxRvIp5?d zdjG+LunV2cP@)+6FceBlZ`JrVErZlhXM({mR9!5s-bsYW`JaYw;+)M%&cE?H9lzy$ z_^ym66|;o1n@G%oiiv0SHf=ZfwN$uOg>SLA(Cf;VZt;&`v@gJKX$>O;19HMYbsi*q z+nLm)HZ;S!?GutvhrT`8j`-f67GZB#-n8mAh&|7L|0#0`h2R2sfwQxwXesM<7!S z7inbx*NVdVujlEIkC(oCT#*Zp7Yw{RbklM9uX$1BnfUv0S*TQ91I+{-P=|^#OZ@DR zmm-ELR4Db$h~M{`e|O%S>rE6#FO1sgHb)|gnDMoJUzRlp2fV6IjXCJ-bT=#S?srC_ z)QobDf>0Z?t59(HrJ z4=2AlEm8=hmOmG(+5IcBGub#g$4W|v*#Gs^zRKw?>EmwWR<%!E-o=JC2(FJQE^~gT z;;ywL@v7*o<8vM-SpDYT4pshMWQ_S8{`h4D>`Jvu;3GLsuHF4z`Sst~gu0 z;&e}egW{=T5UM-Mri`T9dE1NCr z%>laqGbT`r1LnKa>N>jSvS$)}*=#1nM|QS9*B@OihK}Lr{1_=Y(;&s&^1+@4Y^p8$ z$GDy~417Pn~Nf;I* zI-#72L6}+$G@zHfgRZq~r|JU5^G>qFC{9>ahGvdWsOR?eb>i$%{c2P^p6k@@ zNI~cO6H|N40WmkknhCYC;K~A%{5eX?IMm?~fPu)Pk9f>VDtFq0%iUk5<7$(@Z&K5M zOsUlS@D>+|pry`(UTXQ{w8ca#WFxo`JZB_uu#{xvz83D4BYmlKhuq^nT=c)zFY>N3 zE_I zS>nyR5TYTiC&6?&&E0GJ@pjDH&4PqXpw1+IMkRpa28fb)3q$Lu{#MTY{!KSTO~|Fv zt!JAng$K5u_1C=3P4$O z9|eGq_(u>iuE`3Uop4Nya~ryb4m8pIgoo-{@7&#a>%KQt!1qgPwjC!Lo1t8E+FjbY ze>MZmn;lAln<&J=U!*7-09Ty4`x9_p-0~Acq(Y}uZ?i9Nc`=aT)Hhe*3bkEmtd1I5 z70M)yXuqg>U;Fo`R(*v}Ut)#(gwTR@v0eXo+ZzTn9aVh{u}&tjKrE?5Hy~B5IIf>KCwGk;^)W4|>ISW_{^?&!dLrwA z`CP=ezo8GZNtg4^{hpsTHgRX6F4nD^D<($sK3o_%GWpZEUf2%#nmXhuqkg-T4#5ZZLqd-f3oQ2C+L|J#%)VD*FnQCS-aj_~(GKh|LHy+v?tnTyeuCx(Ikp zZ%l}Y-2Yvc$ri*NdbESi`FCY4Tub$f%qA=Bpr`tNcb1UM*PhJcck^K9o|3ZNbadG`O%$1@y##}2^i2Q` z#q0`$*paa{?DS%n zIyA4GLM#F3B8t}Mq0O}i}e zdbr#A+#R#d1)=T4wg%mp8B`#I9a0c&a4Zi?P!ebi;o?xF$|C!bS0~aK1p!&aK}}U3 zR`(OGH^fzB>&+*rAF$}j!+7Q6@Fxzluynk3D3BAgT_=FFzqWvml$}U&U8;xNCsgra zDxB>R^In2B|GQD>`lIc1JyeV(m=Lx?2-3qi{n}`Tyoc^vpAq zVWi;)L8K4u!A2$Y=lbpJh=%>Y9Ub?DcaD&`_1oj+XYs&_BB!?vhQY1&@vI7K<^U*Y zsz!L9TRoobWQgY|YOUr7{s41t7FUr@q?Xev{Lh?jY{@T`igLiadiu||q36f%Wh$d)a`RwH+r+;7x+u;idmzHisKzH?&iSA-S6;YDaN z{hFuZ;=xm8dE1XP&&iLP4y+Igumk-iog0#%n}6`ci3|9=P%Inu_-t%mHzq}QlvJkdbIt|Wyzcu53ICU*(T;H^z+x)+y zj)?NQ?o<^|cz}i2k6#m#IH=ZFcLI03@uL=I2{|R)2GWJSudyztI~hfTt>w6g3jf5y zxF!f*43rZb*gkxW0#xj9FwB$mgT@gpE!@|>`}*U=K1^*2x5;SKuX z2vzK3tGAOH*PB@3cioW{4v6UIyLoU`v@saWkUHbj1v>&b=6Cy4`u$-7bm|z_l?fNi z#FXM2l#f~u99+DUoosYZ8>+n0u`Mz^YU4s*#)VjghhIMq>F;lcblyFzKh`wC*||Kp zJCncv0pIel#%}4~&sTam{^kgfL3M86WjNocP3UM5|61QbakRM!*Kazd{I6_z2K1yS zdx00BQAtIibiBF^ig;+%Y1da8%ro=?Z&}o0nONUuzVN{f(spXc9Dc6$(QxnmDZ1-} z3F@x8-I)cA?l*-PR#8|>Z$H!(27lfx1w;94Sb9o$UlZIU`@c<(UaWrvb1nZ$Iif~W zpb#)LTK>{pIPh@QP=0=xdZa9nm1Z*1d{!7%weXKWGuR*Jef#{kotn|O#ySYhur`>r zA1?%cT8`OkcG>vLdA1L6*|XktxCQ^lkSQGWM| zmrNhd-}oG`Xjw34|K+rJoX?xq2;pyTh4KP&0zY|{wsGVuj=3Z z>DC$cGfs=k0@Vu|xTB2M-K0Y86Q9dt_7~PXvS+VNbt(^y8{el)h{gxo4Cb=#8A);8qhgi6 zU#Oe6=czaYuC@MDB$yG$Xh2M^BS0f@wp2O&l}Bs#@$bNcAQf$g$p*gJmW0YG*M%4W z$Tu_HW#kU23rmpfRz!opabP@?sJO#)3t~G_cs9f>0=(DGErBG?lNh-=sUPdAuYDhJ znj`J+_rs=473;M*-!=35OTMzsLuv|g0O-`C*NtnQaP_h;yKy{K^eVKfQz7@zhU?3f z(^Gu6-M2mKf;!lj#F3QP6}4AE^y?n>yf);6)-zA8J;09i0w(vvC(k*%)P1H#dKk#t zeq8AMFe}#G_}dtBrhM4#3Hlgy)cmHnwe>Hx+FRdy>=21)^JzZE=oW}+AvO_$*_o<_ zvAXJu8|w&+Qu|^xnJ#Aa{E*7rRTrnyty$~o@cI? zEr9&VjI`^oE49QHXr`tGQw46eoal_GGLGKJV^*r4g zsQQY7?6C=ma}4GcUAWi-Fze`omY^)Oe_+bJ#f*fSd2Rg3HQf2;y25i?++$4Mi}Y}4lO&&@d;S<-EIfi~f|kY|!TU?ZZ%tna z$$0G!oGN}Xb)Ko4n;}|8R3v;W`BZiY3x(U^b_BDm)Dy9;bik&4zAIt{i$krOHR);A zeJhLnA|1|uE}I+k#q|?UcZCc4E(a%FZDgQgj6CLxdva&W_f7`@apFN4$rcKuDdaN8UMYrGU^I!^F!&T4!X{#$2iBS{&Ey`;^COAhP*#tn_~!71LB{eU z+~e7|Lhh5TnIUGuPyVrpzGc2{#*lUw=5|STcIR=&NlB0GDSqvAv8gb}v-wtKs1`4! zobHxK1unM36vaP_e)&|RtAoYW*2;ibG8?3vSDbd96#u`ng?17VVs$oe&)wnCJ3A_Q z4rE>LdO6x#Gak_>V-7?ry4B$nvfC04$BM4$s~K?8(Nb|?Zt<^}?}UK+_c71(=Fj$K z*3sq?9ZEjL&cts*^+~oDnH?4t@!Y9LLWKA2tdto=Txh8(`=EuAc-)bN#*)a7ZtG?g z?b>k^*hp?zQm*!SyafK!(b6|(`wM5m;Zf8}2n*%x1Y-&3X}rdsed?8@;J}GJxm@aL z-EY=^Oe0;X(0^Mzvv9N2NXa9pOR;^@Jy^)UKR+s=T`ghc0T9I+?JBotG;VPoUX>RX z-`No|AvRrwf2vUlUeVvf>zbXeh}kWS9=hD<&Ncb_y0em(JI;8g`xLKrUi;EL?X7$d z5&3$>ML|?Co{VWJ{6Va`JLy6bB~zFgeO#E4LwP|8uFLD= zMGJpEiu^3Er0__*Lr?DEB^e5!02w@j+$UGwk}w*YO*_K*BxfC}IR&P-r_(~X!!&*O zM6ZoTPe34jmQ-DeYXEJo8vDA`jQd};{M5`eXMB>mwPS%9ygH03Fuf|@r1!14^5?|d zN3iCTtyRb1Cq+(--e3>)N@dItyle{+`@|*~G1=bmY~i~cZbdY_9Y(bKkPbgtlbKF_ z<>U=p|0^eqKq6I73oL}#FT2Kbad1n&H)cR@*juc!gPo>0IJj}8!|s}hp) z+>tq9o?%0yvxr0;BevIO8ZNZDL8zP>&#m!4TQ!qivvn7}5W_$8f~w-y-t|x34>y&j zu@Zz61@_nNwon+QC$iDMt{EOsQkX-=+d>?=ck^2sv_b;73pLo6P1g2bG`EE>$V8j> zXirmc#hkV`{BBVWlK0v8l4m0TrCs=`B~fnEgTKa0KQ_P`fXb=-;dK>0e`=jES>(VF zfl&yI!x-HeVLN{e{F)x7(D^IjlSt$X=b~|9K4ledN6D^7<{I9j!2=M9x>s9-maLT2 z%B8F)RWNO1OMInEP7_~r|4HP~;Z-|GP^uRcxMJabSV)SEFE)|Bkz56;Tf}>x&UvE`lmS_j{c;*w(0w~ zu#!Wfx~^YR(eyLh)+Y~jw9I@D1^wfKEJWAD!gvK@-ogA1jULW-8A1>)N2#Ur3eQWZ zQPv;x1R?2_;a=^d0@Dxml#oTGvIP-{OOa+0NW?`^JZFzlc8_pmhmw}WGQOQ!y8bEY z1JI~W@}|0zsg+xyImg3{5=PNS>Zn6ko+D&>|mI0y|{0`5l^b|$A`693vf z%1Q{GdImBX5Gx`$;GSgIG#&Q z?I5OD5?Mi&cdv?$NmSnD!GME0+GzkdX7Nd0g$%(m^|}8W+)?+k#CJqhMpQE7>oCVm zsQxBA>v=l>IksvZ6c#^NiEqpfBlc~ugbsBgv^ovP+D?4aCBYg`u8+i|%=$-PM=eY! zqa^Ti5(ZgiHoiqr&mF4rT6`X4@wcG#)3W&Z?mM!wsJr~>i#ukX%#Xw!1{^*qkrZ+t z{La?AN&>ZcY(I`4U?`!Ht_;C#V@n>pc3OO3miMbMw)WBPeHifrdoVf_0EtC&X!vK@ zLQb$;=$XMo*J0ug_WrW|dd0XmKsqyu^^aXh0{zY}^<%h@2D7aTgE^ArvB&QF4R(YN zP-*x!1v`l#qMvq=8jbtYs)gQTu+qK!elhYvA+=+p5G$qK^phG6l0+=vLF?P3WYUcX$1j0lOHkR7P zXyAOf`T_cgkjCYb<2qIuze}y2PYs)+L0|Odv1=@ZLcVbmqd?!zXIT~pycE0ZqvgdI zj-W0eN6CBbJKA7Sb%BeVy# zW6BxbUfvGxG2fw*g5n26R2~+}BV`wpe27XrYIcBJUzy7vsQ+u@sD)}ffSU};%vQ@} z!LN;L?QdSo#Jrd<=ZDeS9B&fWNlv{yeHZ!UJFAO)^g_W9$a(WjL>~d+(EVkHN+ZJX z@W)J=RWxvZ@Ga^HkRIF7-*0e6NQy3Z5Gv@g zI?dJ$UwF%$DHg<5yuI$z-zP6mSX+vEg1Tbe)R5*UmVZ6_r*cSlbkd))vNBzhIa_i6C1dYF%?B5m4I0DAFa(yX3~m zih%To$rC@Z0RVBZ6*NcxS~Jfa`QgdsL6TmpV~~jq-1*tO`5P=S5XNYj8dN_r4P#zt6EOqi>x>S9k41`H*+XS=qn}pTiLoHgXvuzQVs!0 z9C#sSArK06eAcVfzZiKiZBNKF@q__nRwu@hTRi?_b$mcI2H@XS(9x!iy%*P;8LIsE zvjJ9s@pa`LI^y})*e4mnlcE_27w`)j^PFZ+cXI00P+=?8=-(#Jom2}|P;rfJ`$P_y zLUj~#|J_dN{Is1=3gVVhmE!4IA0g#I3_ey^7DiOah7e-qVL0#$;LfK;)QwQDJHd2K}S&`u#s+{;4CeTNitcy z5G`q+Um-O`T^KQ{s0HJxZ%x;KbJfKzXkuC~=B{(qqtmKuXnej?Eg$Dk6pu*S{6y2c z9c_Nt16`s8s%-S<8J_oS6P*!k$?0Gr2&)mqJ$m*=cr?aJmdPQIR4cGWL667<+U}g} z_f4R}0F_AK$t32%Z*k1OKHqOx;t|8^8INdE%kh&BM@XWn5pogeFCk-kg#5}|wz!>~ z(0tu=0aoGWWT8`@IS&=8#mpnfKE;)znbp+GHTlCx6rd98`G6C)EJCjy3ze-@`YbXi za+;WmLl#q*XpszT@vBBgNzMV8%OV`51vw(w?xcxelA(~M)lHpcdcj#FYdo$N^r2-N z=XfSW=Z7QCwd8&7_9Y2TKe;}MwF8fT!^1rZFaS-9P|x;TCF^2nmKfKbeviWqG0$c? zTdQ^R#>zY=6(&_2iD#zM4AULNXl4V6L8rn(nNshrolKv5iXhBxhT%2%Z{^?UiDCNmZCB$jrRe*7Yr*!uv|^`lXZtbNG~SD+ zyQ!`RK{qq|v*ua61hM*_Ow%oP?(0( ze!j3YW?|)uv1Js9-whfUlMZ}J*Qfm)ye}EC-R{cl!bd3mbdRaTV`^U#hs<%ITpn0_ zjzy;e-~oTX*yPEJTZnmAwnO>Y$OyPTHgN`GS}k=}5+v*()Y`=B8);d@j*wOF;s88t zT|7-3Vw(89e-_ySyE;OEdMg^Zg&46AQ#=DUViAGgSm4zvZs17_ofcXDC1-%L}ZRZ!$5f-=VobhEJD8LODQ-Km^FuV#yj`F`KlFVL#?e z0PUkO9T&HFu+8nMrWVNsU1G`0ix}dT1uX2cNOj`$3lZZ63`vINM%#hOe$!4@x$-!Q zoSYCp?=+F|`zQ4l4i?(hC4q0T)<_aUl6^Yt>at#L71qzcQtESMP94gLpB&)J#;6XF zT;nqH@vOXL=?C>f6!LX?V4aX;1pWHxmmSSl5rd|I@>=7F?MU-!4n4{~d)ezJXf2uL zFy)?n$-P7y`i%zW1lWbzVHe#>iYxF`;n^|tDX&gL40aC`gf2q%iA2{0pX6(h+(-PjVY5xa`451I|GV4s~al;!k&fn&gHt@e*>eCduJdeioT*DZ}u5 z0(bf-r=@`8Kbk~X{W97X&pid;C<+YcUtV#f(@4t#RYPgRXWTM78l7mU`jSAV8~w77K;SB>OuQ_y6I$9{xzHQDL`7ezK3Gw!fQt!Nt5t!|nPd zDnx>YBsB{ja9n9j^HVvLV>9yWg$@EVfnx5p==;+1MRmGQLP(4hiIGgLDCdIp@!J&y zFk~|_1lng;$#T9YGro>_2EJx!z*Wgjx`cXAu{ki|5iE+3KhU1vMupK%bq6xMLg|GI z3jjvs31@E`oo@z)XLt3I?Bj=`hXNmMhmtkb>DmRTNcA#(w3!4Yv=7GKj~#|Fq5nFg zhp{cs$AqD$4)x-0tY?MshiRvOv^-j}JC|XHao=NWRBra#2uT{KVaH2xf8#3;?in6R zZWcLwMdbMPBo6fl)ST7x!Imr6U6-)F#1fGY7PT5* z==F)wfjpy&)pw{1k`NTT56Fe}kY8tLaY#Rp*&R9gY+2d@0mvjN7a8ZE`Lv1bVC`|~ zG$qry&^?THbs+0z5u2-^WXm8SyIf5zqKR>3M79h7R>Bne6 zJBk!OpQf`q2TD3x@N%|zni01B8*T|ltLs~=txM+6=IF0nV>my)Xc;Dips&5D7V^SN)FVR8TPWd4Rq&R>ZMB z^l4FP9nmR|>FJ1{110a^5z?Zf@WT}I6zR!};1=Vp&E$^_f^a>yRQLx=HwYewJj$9V zj-TM`swxWLeFsPyD#evd7NZz4J9mqBk!V@l=z+UoQ*2((GH)S)?%HGhr6t z0Q3_M{`V8UznMGA=RDFdQ`G)^IWTB*%S^Yl1FXf3SY`Fh~3TPD^_`Qc6Y2*-{i=??7A5|O}WuEn&-*1Hfj;Md;hFE?jk#p;!tMZpgQLiI-L&XL5&<`X$*&fX z9AY%c6`nW}(#It$$MN2pSgt{rJVk6d#_4;?rFc1@BAG+;v=Yx`b^UIF3*Cq;jXZf))16SL*gU1eU?6Pd*JN>BgCr)%V#fN$u4IuQ3GVpso z!@7Ehnab+@)Gk@NuEHquF9D2040CJ)`(m@E;AIE{pnoi|Lta!n2Z~3ETVx0 zTD(;L*R9SjCSIaKK|#@ip44Z)U+IE25bfPyh$Lcql(cd;E8rjnN<9k6q$)nMzpC^(adx(6^K zEzb1Z4g-1xc>%vDb8wIuvUP(9pBvJNlUfC|GlW+D?IBAM6Ind4-6?kd)fhx)j4wiZ z@Z*zkK@t((IC-7KQ;|4fQ&#@;x@@2TultIjI!^?OZS(47}B$3cYXY*VG|>P%)?rY zwY?|Y3gkB~;oaf-uqw$1!zU+A!lx$&zB%ms<|AMh>5Qa`dE;iG%JE`wrrySjm{a$T z7{T|J6dL_{2ZS5@i{b#|E)}O`VVmogoo`BC%pS3K`?av?$N#ogLev7oiB2z9RHc#9 zY}`~T@Ade(kqV5t?lulDt<;ms;pgMt6q``4kD9@Kk5b7lzrWo3C$UF_c|8K8xeEsW zw4tZdX2Ve!4xh-p|C)}W9lxKb%)OLqag;Bco&vgIzvtaqA(osc4( z#BSB*QsgpN*BwH4v>z6v)Nsz$O?~KJ*}rxh zFPDlB%kW4|PM+NFm>;UZs}d!cNYK3_;wWpBtG%UNqLW$wJC3C0YB$wuZp}D%R=_sd>*(K_p5< zh8?uTQ{fX^WOK~iV?0enE|eQtVZ*QYOaAg=TLAN?N|9)yOQg*#3t;#bQxTu9_0MMCo?VYZz@^_Imn-fU{^B2 z@K9;!w6>_Rw6rQCOpgoc{HC};g)Joa3tTk!Z*J99w~CYy3#ppf!<#dOD+I#NEtqcU zyIH^(TA~c%&g4#_M&R|qLWHI(h25WPg|drwKXY+rfZ>l%&nsd2FaJn9JJO>*Shp4I zHSp5gqZaM%EiahgTx()5F`%xZDDjuybXn_H;J<6BY!@1sUY;crwZUg2&OZ}TJ4WuF z_$a1}aGOOiv(LnjOeCRO_iuL{3>q1q6A5`ziKW>?d}VuX7#}jwVE%-D_#PGBe?$9Q z`yC4*ibnwLCI}DYC6G~Ux!!CyQEy`iNLrFrNTm{ZCDNM9E5p`>xzfS2-qUNy8`Z(QV}mlf z#BM{V=q3Ptx4}KTRBXq7)BLMXPBz{pGiOJSJ*@a zoXh$K8i7@YaU27|PkP2)m=||fRW2X_1$=cRsAUFtlJ7DTDteRas=LE{nsYsAlNhy_ z`Hs;=o^GQ0BwMX;7CL8hNZPmkvpGFayA_T z(?SE5_zRG~{ZJQHgkav^ zcb&O{GN4v(*qn`W5aK-xdF$zUGp+LFV5?hHY;jq0jo$k&Fxp4k7L+r zyl=J_U;ru>N!z8oIC5P5d)Gg9U1b4P41FUOuEp&C;n?No-8^K5Qz3hu<^1_L>shQT zLiT$tb*KMaa6?_xz(inX0kV;vLs_#OA#t`^SgqCIKqKh?2HXG$t=6hzRKljt@0 z{6ahanbvD{NxM@S1s9a>8laZ_gxDHlF`P#zwkT*|qXC`IV)A(6mC!uz5HZe-Z9ZtC znwsr-UUZDP=*L_@?g6w*hu~oNWXv1+w2{I9-$dUhpf5D`0e3Dmp?l`Eyc!y;5#eSX zWQV=~&Ajf1B#pdm;(Azd&C&inS-CDjqB9A>$NW_E>9JO_OUko_VN0_6A2EX}%e)Qy zpt46hYKb+UqtD2r%+X3du_2#3>S=D&%-p*8*l)@Jo&nttCl*U?%8W}6##X*dV8;%) zS6%5rz?OlC$ABYIgFEzO(Eg`IswiY z)Qj_jovQXYB8R1u`XL2stu&B7a3D)*HefF$hZeI)WbT&r)W&JD+1VUi7Z4T{p5YR3 znyM#p$Qg>M&8){a-&&dva8$qib}J_2!m-fUI(Vthe>}TV)9LgoZeX5pZU{>m54-J@$!M4$(y1k42Ki>YVgK zW-Px9${E|P>(p%Ln?5xwRG`nU2`_hN6I}{+mPz!niRJhq5ut3Ymzao$<3{tCueu(Z zi`5C;&9;4s!Y;pQ;JjZ0CvxY6_MlCVif?6k15(w>3;2X`v&nX&o%vl6Rjx~J!#3?7 z4*Jr}!`_~3MU)w=kx;W9f)db;U?dvHc zF&qnyC{8c-9+l!yky`{#&y~lZW^pRf@kc3G?{kmd20cA}_>}wFq#Vg*nitL7Z2b14 zt^slwQSR9-34k{hC(GP&;`~PlB7qszW}0uGGl`D(H+eQwS)x|>EDNIyRwO5;+_n?hANlL4k%*ppJpLgOxAQn-G zuYdo*aHEir0J!FN>9-v1np(Ss4kA&=)A{%c(#C{uy`du`BQDDqC%AY52igo|u731f zxV{o9oazV`JKLLB=stb`*oidTQ-(EAoe`)wXJS;vP+74&4``=;_{Io(bdv@JQ`_(1 z{Auoav(M&BbDG8e*cXl?E#HH@7|@XwIDN%8_)5LkT$4*b61ReR8fjP3flf+dmT){) z?ZI(#?a&(MPvdTdo?6HRaj<8@MpajIrKz3eSbx*QUSft zyud#aPO}w6e^e9<%&_8Bs`xR?DD{R{;pmpzOa_y?-3O9Z-0H^~T3xOKz;zJc9}5jX z_v6}qyN5$a&P*})hyes1=EDBfB9*T&3LXzfDo4YJ*a_xdN-d6_z-vs^Zjf zhj;NrgN&9hI>w$zhzp&5Yy3Rrt?`$qyVSR`A}z<5amQI)Te6ee>VG9mKxh9>ovtdh z!wuuOE1h3^#h&kbf_y;NI5*e(^a4rHN#RYP!ZhA@1T2y9+Pt@xsj>3C8mDOi|7`Zy zr@h8>sORH|J^5ZC6bt`KSTE8m(E{zz zdOQ)K{}sV`&_ftMBimS>g84>UF<8)5Z*jHwoE*?tF{9UQx3*TPw<<0F!l? zs}rPP6?szgK8+SmY8>#vHS7@|-(XMB(VEU#FJh~&-xY%&WL&JPCOK0ZX%mWuU!jMt zKQisz+m^5n-8_2K1b)X=A7ne*5@!6xw=X8%2v5FV|23T<&f7WQ8rZ}^$C*0+>53-E zFd_|e^!SaOv;HKGo$i@uJraZyYSJ~Pb=|6+hZyQZ7^w7R{r60~$$XKA_N%qn2i^NP zUU}ySPUXCN@B;sNB^+}{6qN=Tr?~{fk_>DDvPZi?sXqUS?oo5fsQSc?1^1ilE2m9_ zwC_YHyTL3G*{##rk7rNiKR?-O+a{E+$J|gcOFhP+-+u1vAQy#yxO4H7CEcF$k`ubC ztnGk?(3=}U(@4Bn@H%y~L`Lsy*jz&ZGX<3~galM+WT8F*n*tx>x4ZdXnP@xBw9PHA zUgN}k?xaUJAI7-wa8LxHS$lXh(pG3rWxV&?(9Hpe=RxP6avo5zNpFBK=uW0_OJw2^ zj>6;;BeHjoW%*{-eLP#rC~rYW|})H4-h=Ue?v1L#08lmV4I zx01rhGs38a=fsxYTmSg#2Ov@=Z4gy(rJEIlWoJ1KM%+7X=M9z`g!-Gcq3j*q*Z)Z5 z&&X__J~P=l6!zT`1GIxx&OhHVSQv)(Hfsn5IWJC&)sxgwLt~y`BWV5l?D1j*W=bpH z0P;X;7FDba26mwbIEiQ?3Uz>9HxC~)ZH_Pk-ZzBRKOU&_hosEcIU1jmJAj=@(j)iB zipq_DPg%zb4$#1HQhUz?ElGN!D-z1Pa=VzX2rZKh?&nF(axUgxkqmN9E&Hbxet$Aw zym&#gXUu}zH8x84lO##(4UKyyYk6y_8#j}r+LsajpGS*Rb_jk*@tnsJ;ZzP@`MM$D zZ7~E~_3meEQ#gf}4H$rvs3tID~=Q~SndJSUPq`wyj~RIJh~2CHg+-lo5BV)o1Yq5SV2Z^Z+q z@ttZSn=7W!b(}^q(AnbJE%qwBlH-hBax(0ZT~B#Npcicl8dktQK~QI)>>}X93HoB(DHT4`Q@1OFCF;sF&;zeB8^7f{+u6V-N}XZCX{GU8iSNo#H_;0z^=-XzJNn4lo{ODmPf zi5D`ro~>p7OaVRkUZGj-z0Fh?wPi&Q`VSP6fq1aH zHQZI>y)NxP)Z6>(;06IlOZbW@yojAHoX$j8s z#|uwwS3a(iF@u2OXY%~R7=bUiJyEi;|KZn~2XxHl<|9ES z&e5Fbw!C#^&-zb&+{CB;&uorfc|;#VF0~Km8Oc_VN)~T<>_V2N-f`lP)z>eo(n(Sc z+Af&1y{3m*M(Z{f3-MxKk`E|@V6|vG_(5y>d-(83mPSNZrIuB$Y9o`B9iQAYZbi?f zB%iA!YU;DU5`J7`E0N2825uaIKJlOW_nT@pED2JWSCX9OQ3#LQd1iR!=K8bjXl9Vn8ZOuaVS5{kUYL=c*WtWL5c5gsd8 z*R`qEBJ_N>>-x;w)kgNQ+>lp+fq_L%yIb$Pu63?3=&mlQJ-Mh*pw1A=CtnZ>tqUO8 zEBS1Eo}DM|8M%N;|mPXF4jMm1TZz*Ki#O&>CN;@_Ga@`pC<4P6KvC>fW&5*OY zU5PHfjPRykzRtRd4Nye>GA@!n$f6LK4e9G6g$-%L6^*dP3g4|2mi|IhZMJoXTia>k z2wt1cG`^D^XM!}@q1hq6yh6*N(flkRTW80Vpns-JuBN5BI)1D`%{7-i>F21f?4^ABf;YOQJ@7H&20J_himA4>v9-D+_`_ z@krRunkPV={;?6Z@6NIYJm(_JSosEYuRod^)qT#E_{zyB%7Y;Py@l<5zUO+O9=${z<6kh=Tp zuQ>|eY;EU1Euu>q*9rGJ^$wgsN}T4`y!h+AY)i1+G80>4l91j$fw_Z0ux86!nF(Ed3;-*;ZdW%@e`-fAJ+j|5Agz!#AYi?9fHu< z7+U^QL8K3NN175Zpm)7xUvlg6wR`QBTQG_T#3r@f4pYA~X*E$TO{TtEtUv&w_2kUI z97HiFtiw<*K?uWHcc2DTO*)m`Gi13Qrya|v_gLJJiPXPPn+fT}5OCylhL9FyG4^=BMQ33Ag z(OvCEJ3chUyiwq#RrYSmXhef6I8IkweCf2Soto-t6VUYCRyK1~irt=n7!2 z4*DgAu1%)zE-R`FEx&FVycH77Ecv)%bB(O@w(f5Kbh1G6j-F z`>&Y*rFa;f78|vOnRlfV+;E*hLCcu7^zDjDOkuGi{(KN^Z(S2=yvuhUNFdGI&kvM+ z>v!p{JsbgZ7B3BG+XyOa(z^dCgs0CY#V{H08GF_Zi76VUP8Emq7~>6@;Z3H6ZdL&j z)x+I-g3P!4@82#}KK7tp&IxeR@)4LFO9}QN_zEAb!*i+oFBDtxY*?lD>sWo$z&Zgw z-xQ7M9Vj+4aLR+Cig#MDvRl(P)@On{Mt|&X6BAVg8(TIGC$57k$1bVTHUnd(C*k)f zkKQqPfi*gEYsA-aOxXEm*NrKpcUXn=Jb|qf}b0rv0D`nDnxE?RLZSxm6)PSH((K zwO(n3s|qsjq?3h-uz?_fLUZTWQ0D5cWdeI(QkB z0lSLqdx~5+)wcinN>lcmDheNTQ+X$(I1A|LTs(0$DYRPWxRdbM%C54F=SwSTN*2`g zT9s81o2}(B-e%qRbNE--KS^Q9cDJL>Ey6K?P$V8F7btZSar2I=K%5VP2OyWVB`_=P z>ROLK(yU_}bPqQ)S>bzf*Z0!p3(TqRQz|;#VW;-T24Nwfpj;AoG>jY>-mG9Gvkjo~ zt)fb>^)w}~kmAV}-)#!%r119$-IItP8aD~(*l{?mKN?9vqhFoKy!LFVQo5c;EM9p& zQwLLitLR)ARDVNV%*#}Nysr78B-=lvb4^H}p;HCIY(j+7kd zj~d9!am&LYO`QFof3Wd+8()O#FO}Te20}Ehzj%a$H0JspdI^i8i=At?Og6p@!0aa@ zp^bUUqPv15o(N&5SZtA93z8bALDW<7Tue0m+_K2A{@rn+>u+~6bzO` zqdaFVvJn?{lTUtgtJCtR{_TKfaz$vcEvJ^E9d9pWkCoD{79^9UtCK7@dYsS0d*9DO zPC)DO_X990+|0f|Qo#J-ZeL-J`90B6$j;)I`=Yf@J%#fD$>oSKvPNxpB4<+Ay&%!7 z^TpA)>jvnZIeb%upO98fb6b8 zP?5c?x%AcY7MUj3dXLB(zwC!ATsqUaNd9V|)>8a*&^?1z{KBNH;hkzmg-tT^>K}Y; z+r@BcGbiC=s(5pzYX)Qiohj*65rUwy-&`DuO7!)e$ z@?*gOW~&i&p=)tKJ@NucK8sT|{CaqJoYsdp-B@OemDl6%Z}>(TLy{`PLu(!;(tsA5 z)_F^=!#p~9`q`7=X)X9&?}V>X7X}|5bvWrF!&v?fH;KQL?;g_%JHjDV?ZsHyx~Z^G z4ef`e4r*85-39H2yL60)69(k;j z9Q9r9Rnc?~65oa4*q=(S7!ivGN^L`Ud&jxI6&XNbMv((&=%;l;__fc}zF{j+`b$zI z9Ty)uvZ>}XxycE0P}fTtZZt>k`zBSmzCva`32Z(RCjC)TT9xa7$jDwAUZCtlgDA&~ z1qS_)a+#Qvce{WI;}gGxKYEpG_$;ZyW^_mDG+K;3LYDf0zm?rPJJRso!+fLmp)uPOa3-?0=u~3%oIJ*UADRdn(5zqO4l3sk zzN{4Y>VyidjpBJI57BY<#n7iK;4#zt+=Vbh+>ABjmNxy4K2@ zN|`1+?)nEjzg6& zzX~lJ={=zVkONSl!`T3IXcmyrs(X1w3t^fad3K$1O4~`V`eC13Fna7joK3oG;~M4F z@nhlwfydpNpSBRfHX~IzC@=py#j<|NgXBz-rTRF0SeJ4#-1?-cm&)>aWz9cQ6dxtY%InGh03x zbqpB?i9;h2F9IzlKSP7m3j4`v&PM6h^||jgv?kK)c8wZnw3T=E+olAourTLZpKY~^ z$*{aNon}J}=_+_T%0o{O%@@P9kH<;I30ohH7mJWJ5w#rn89{LI&M-fAB%*!-W|Gye z^ABA(34Nr&(q;N9xrR+zNaS(cb~wUswZ7>HT=@t}f6jPAwnGy@&!aZ)daoTjBCZns zo0CrK!O)wq#95NR+01&x>g|^nIZ_$rmAXSGGW-_yl+#7?4f{cTYBItsO6Xbf9bp}g zLjI41MMXJmO~+dRrv2EBBbP%|i@NkG<#FaP4Ci`STfp8PbZ=+?RkUF6#jKH6zg2+y zCzLY2)evQ~Sv^9mC284r9Y;qX&Pa zm~WX2JlPA>xR|y1Rgzm&H{CKKw6EOGXeQ!ucQZa1p@O2jNBKTE_Cdg10Cn-1;jk5_ zdeS3K9KV%*Q{eUTc@H^M7sIfguv@D`mr=1yu%R@mT`EToDNf&pMn^F1Y-i}wS4us( zhtEJ{cf^*JwvR0W{U8H5r&_&EBNdXH5K;c1tE5Auy^;AK{ltIY<004SbL~f7t3(&< z?+@~-=vz{(ntmU9bIHClUAgYD=DTKEQcco@>Ww+hnO_;?*T$gb`xVen!p^~zVA*Ho zYjo)D0fN7;9{N6J_5NitKL_3r8k+i2*R1g=?{SmJk0k_huK7c^Kd;HA8v!B`YJn|D zjCFH{q@Rt)y|UZ+5;_lbR{nG+Ueu+>s!03_>wjvfe#E=pMcx|`3)JuO-yYI%gf-TD zrR6MfG9k3a&r&QVnuL=hqkV4I2un;B16om2bW4_DV662~ojNV*o1ftQ!Jdz>aG3r% zE+U5c((}=}j#SA{-!FvvV4{qSTI2+TaH6Pm_llz?Vky^LIG^=>;r$9wiv-34_Ba@3 z{=WV@i}0p5Kh-{mlzq#t3;+s+GKvEP;lN`04T+bP{C>vOdInQRk3=X=eqq6PYIFG2PS(v{Ewe$ty+_U@P8C0bGT!zl_ZQ#%O+btLIJAVndxik04RQ z%ELkf1JfauuA@&Tn)Zz7eh&Qrp$M6TbK*+*qTpA)uVH5&63Cp!FIOJ~y|8qfJ&QW* zy1o7N@#ZR7E}azp7Aobm?oGm$SApsRZ$@bo)7#V_kWq!g0g$peJTiFmp(HMzQ|Sgl z&a{2V1;`Tl)5EF0$u#AJ4DzJ5vi6C65(N>VQP7ZcauRYNe5k?q(GsaU6L;g7eB#_| z{%8oLP6$-HvfT@6(cidZ4f^_uNZUBa= zl)+zg&9dQmTVMk+dFIY-dX#4-XEdc!pr0$~@mdNH=d~5>MN0s6Qkg#!ylv{5{PE%z z2c$xMi*5BoP31>G^<(vgC1(_vID9$FsU^w)<8Si0x#aMOM3&thAkxq`oBfv#SR0A( zyf-zgl^(;MDA9gGODX39H;#57>7<~Mv|5>%D^w_gF?uSKY?X8Acd;YbE<#aw@@*udtxo{DQ5+2$YTgJf%_8;KHJBF@tiDSQw zD}n;H_sF%F^c7LwjA0aW`(E+SQ+z7j<|^3|pV=ky3}cLvEU#Z=nTXJ<1mLPai!hW?vtSM>1PbE*wMaAIBkJ4naKqLOcV%=-wn=jsezE#E|-D zr-9NxqUHsfpNpR#79R4~a#~BqxvI{|yMAD+bJ+7ac3A0n=}K3F=wsN$wfcHwm%0Wh z(iFM9#?=!h=Pz@E7s?}PcICZNfZ1mtyRf@KNlIBa{B*#Z;1w~H5wqes(yx<*aJf0F z>)e)#&CYsfk#+N?$K1$Yb3YO1g*V4pw}&jfuRz%^Ho+l0Jg1iE#Xg(oc~ADTL~xt^ z<0C+6cUcH3vBKMQi|FbsgsBhlSBnr{WQUtCL@E1vYrSiF$UQ~iJnrai7qFxwS4 zcZQdre|W0fnrSNCM~P}tl<(HhRRyQBTGK0*L-K5F*8~J zO2V#vc)R)_d_Q)iSR;(e2K2z0EngmfuNwO*RZAh=szj4@Z#ZM0)OV3!k7yZhHlEr$ zVQDR}V%#n5EyL+dEE&w_4ze02>AKVqnScGeoSUslkdZ5k?RM))oDGwQcjqWS+jj_ zX;p5_76HEkdTViVI4$|*cWCdbkm!?71hk2~ZnDH6o&rhQ&q?{{pSFKC6-iht1Rm-l z9KEkKY#G>+mZkrl2c*DZhb4Z;a~X4V6g!~xxsi@M596=z?;?W7j~fih!}Cw`$VUw@ z0GC|Yq)4HJ??~O&#@KL$b8QUmco45z6vB3gs1~pjG^{$Ze3&ZkM=i#*U;;ZY2f~}< zj=jVCEwB>F=p!Pxr>jXygYuP&qI9ztUR#cUW?M`{SqCK zC~9JPN8b7-a!QNCKiJc+yDeh>?r2Am%*VZ0^Jd~@j8WwG%GKhoZ#lK)-_8zQ~Oo&fq&B&jP?*Js#-i2cWISPeXD@6U-yMpbK4+RLLO`Ff%Fw9;-Y zIl4Hq!d?7H zC2vVCPM4Qf{!`Y$MA(($Qdls=O*;I7-N0AYnD&>g?aHikgx1t*9kch76r{ack~E97 zUHRgGn5@z8)B2}BFKE}amR@WqY0oAEB_KNL+Yfb4{Vu;b65V?2RUB)J!Tp+S!m*yd zwGO?b+1Qp)=A5U7muvk7$9Tvi`JuSg7RZ&b69uY{?+jp4$M~$9jpuY88=eyLT?w_b zC~gQml3`kIt5z@F;HH~W-`L&!RL9Kd{XMfV-aNlBcENShH(ixVFK$o!Cv3Oogo%J^ z$bpZov67q=q&Mxn9uE_?&ky$^T=fv_39BdE4S6Wm9Q`u4j`BTQr`k9rG2dhY^6D%T zho#PYot@Un5q5F$td}oH-=c8v;Wd5F)}oi=iuPQWxscKK2Q@wtf_UL=(t}o))VMhl zcRo4~c8i~M8)C877+A$~NFi$-Rn?8N`3*l?oSR(FZ{3aMq1z;XFiw4!`?i?*rfV!5 z-_>H*Uuw1R#!BLGQIcDRUj){wl+Sbj=7oEqQ+yN|s~N{a>Qta4i?!xn4~9cspn8Dz zG=lBeaq8{L5}JsfIszZc`;G)jswahFev>5M$ne~0e{@ezn{I!o@d98T>QEu+E}qUSC3y*nHeW;y%$>}(;?L6_9e?nI`M+Sm(=WW62G?( z(bKr{`MniKub*c%fl88K#vx9oVlCes{*|%nS&B%keS1911%A$g$V(=gRTiT*BRA*1 zU(WOw!5g7_P8o7cKIAhvbym8TDEv-$#g}g}o+zH&pd965 z>5mz<>oyVBo8fJ7Zm&iCmW~j%?D%c@KO$P$t(dJ8;W09LljZMBYP$ODQW5iE5%BJr zz1{`E{u@z3Ak+7}KWJ&+#CD|_h{%Qz3TYbB`Z5-zcC4pa4Zr#^t~0BtxXKS33&Ud? z#@tZ{4Q|>rKzGYC{Rw%<=5WLyw^W)mUBrO(eYT6i7jk@);K4}9>vKa6TIfKhU7W}q z1drZD{|ZH=L2vUje@UbxWprwE1)c+rRPyXM#vCwqG$1*TN^l9&aMSie-~o|M+E_u~W!k zWsn(r6~NQxB4f{-ab|xV$!KgQEM|`P7Oyh)cX5rcL)r18)n1KMx!e0K0rVaQJA>AO z#Iqym;|yE?qt1MH?vDs#k4CYI77f{Bk(X@@7^}9O-S25!O?B9B$BcbfSRqy~y6tcD zpfD@x!F$mG`?3h{H9`Q=k0wp01~49>SL?f!BcE*in7yLU|fslmT(;gR# zDovTa>@R*h;c*TDbWZsyogHOep3ctsfH{ls*Uyow=u(NosqkywJIf=tAnk}-L(HjK z0Y+w$6838w!#CQ}&{{}~@JXQ6np{Lh=%!<|$M#N8m36Z-in5oH`yz1|{OPDw6KzGt zc4xrTZkO4r8Dv{G`c3wvQUf z=yCBbqbX45++_9`8!|$UGJ8QeI#8rH{dtOng#GcA3^oTUOt*F8en`BNPJp8Wq21%^ zUaz=)RtK{-{|NSZ&?Vigds8v)t7{cS*%`a8rZ5Tnw$kf(cNG3<&r{0jQ?Xz`M)dsb z`R;m(j#+!Rc_PzFL-AQMa%rSzo*@>8X%B$yC70heBu%)$B<2~Ka(kuWP(X|?q1}ng z#Yq%qxAwSDe0JLLr=j*fBn!zs9{8r}V_9#1l3NUnbV;|hrh8V#yX;!Rbb_yYWa)Ew zH)CLkjY5BqY5x{H%?P@*XZ9$&wQ+x((o%C8J|9lme=@6elyXnL@&=;PYj}gSea|oR z!bp{evg2sUjsG|c^qHPy-` zm?)#*x_T1;SbnZ+*PM_f@+HDnbn8%t11-^lK?v<(48(U|%>vYXzvj-5XTDDSB%Y30 z(W>GiyS1+an5^2XCb!)_wrJ|hU`a_y%9VR6+ni!Htx%V_BBR|@dBgp#5;#hHr!!< z>~p6_1MuQdDFw#EO2AL3eL6meQ7{@hd2E#dMy&xr< z5_J*N$D(oF+yJfucHwpDzIyU4G7wpADTd1Y^>fSkep}pf0dHs2cjKz1V7E9{e zehijNTP!O1c)}S zF&uZyh4L6uyA1K*X|F*>oP~M(erZwbSZB~Q6@pjsd-->_4*u9s;X?PHH&iG6kmKm- zwVZzs#A_5K=cPHy(B&;B-C*JH+H4?89Np`f3pG9)Smz|l49 zu-bS3DdbcO8Reh!g)qw2?~jxZvnZb&%%*#s0cWCxRQyZu9Wu&&^|g0oldiUbc8sdR}DyW z?ytbSs>k4ylP)*u#0nkCrwnjCIofW?Tf^IQGvFBFhw+}gv3wrf+wp^B3Rz_p&P^b<5DZRbGz{fRq^7rv!4NEdg$BOlsG*2ajJ}3P56% z86>_*t3Ope2Z89lBQ0>7f+C3tOa||N9MzAIH?aOksNc-*QYBjoc-%x^o1j)&? zT0oD!(krcW+*@}`S3uk%VUTQ$G+U8v-6NhL$E;bXfnjJ6Iv{U><% zqjWK&w(9^-`h2DX@;a0a;?P&%zo6jcI{L#y&SvYRafK5bl}z+rsNulz_>Ei6b_h(Y zEE|(?G>rz4+d-ct3d|(g-lkSCLxIW0*=sKh6+l>Xf41{|2Y`v`vH3Hxq7TO9OILg1 zr2WP`YIb(kS4j$L7A8MESNt*4cC0Rw@j*2+d+MJp+C2Tf1u*Z))Q(P{Sev$ViEdp4 zyg_gh8YrY-XHl0hM@dxYXRzSUmrdy9cIO_KI`INWIDVUs^fLfRnWh{t^UIzK*P{lg zZ5coG!YXvRaR}lqdb%5BS9%Fqgf#i_U_%EjM2z3z)>;>p$N<81&`_X}z6B+mA4BSATpkVu4v}*qFVnZ3s}}4K?%M1ul1uQr8p$W;VV9 zx1tIXDPp2);H&=}ufp+k#@;Bn@Ltur7Md#P%0|UB)7H;0-vMV}C*Th)QUK@y}c>1$?6@R|`D_I_X zt<0?yxW;7y>W0P8uX7VigR*so;&m^sMrKG~?FHb4=Jth5pR^y&%2GdEiT;1%sN5vo zD(^|3fpRC`%IAwVm#?5Zn}Cawm!B(dR!M!M;W!_cEpqH^K{)^_Z}kCP?E!Zsf*`-F9T8DN z;*H>QW}j|^P}PrQ1}7}xtM!we{YRK0ho||yDvG5rr{TFCUr{LhkEK`a}*nZ)KXd`{q$}A#OCbZ zdDkkmtfEH$r@M)Kl)9~Prm@?PIzT%I>N~$>}P$ z%9U+6r( zymmOXzW{#7Wl=33RfMiYi04?7yu!oHxj6C!*P{dve$}k)k0iV@h(L5sl`kVpO4%m} z;DoDIb9yL0gINMcg*lq+sbJnDQonlR{evYwu-*4|u``I5gvAepsD7~MnX#aK{xdQ4 zB~EU}+QhYJL{Q1IcT^Y@qtATmNa6%+*>j(U2L_6a)}@{C$DnXjI^x_9>WY956*@kg z`#W7p9z?Pi5S0PsmX3IR6CAVa-@8jZu zKU}71i{63nMcuA0A}Yh%j2LsT(Bk90LVc?MPUqeMw+>)t3AmW4x8|o$%U|ZdkunQE zLtW@czE~KNjFc8yhKm{*>k+lX**L+44@ z7GLal5*0J>-NmKy-i!U@Rka7l{N_#^l)-ylcXTjYmE^T2RyKf4I=VdZDLg7*e_eDE zI?)0RU>*y|*jAf43JFc1LXmrOQk)R1gqt>{^qeeybMaBe4=jgETbfb@T|l6@1p=`A zHA&Yf5Y{0+d6!cM<}Mk2+YkF@c>~G-uQN0eSjYid@3yBh?Idt6{M|$b2=NlIoMI3t z`j1YRKb=mG!rn}IljQMSg$JfryQeCrDr4%0CN}{h*VN&gBgC6d(}#-Nx80sQI| ztGw*iAt`7EhYOy~_)c;3Mt*8P;N+msg)zyQB5jW7;INN?UomL?)gCB6^^3|`*k(9^i`yUh}`Pr zhFd2_XF&uKhPANV1XUSo8XujaRkiLnKbH%|RY;>SD$WxF-LtvS09T~k{@NE5!F}zq z(3O*dmqakd@c?w&0?dHIJU5Gn=mTfj^O*WEWNX+Gi992?gl>-h-zp z#{a-DH&#?|vycpygDW0!X1CRwttOMVspfQ|&hKmx=5ZVPbK<;QcE{7tfWR~DZh@JY zE=~_bag)+=CDW4)uTS{*hk}m}UFaN_ItUh}*rhNoqd&vOCeMKZ{H~7FxGjSpA#)5w zTFR`-gx`}qG;KApySOFIMDgu{l5?ydfIDI%z@e3w;h62P`fYsRzjrS6(xAp?+Fc=F z=4j;_0E_Ae`oVBN7@#wQpm?!Gn-?B* zUldiTeb(xtahjx&0{lOn@ju{hx@NG;=s}t&$+a3Z?qq<^~-+jtUcP<{yXo<-dWAuJ;{k@M;WHEN#iVOu_rlq5^*(l5YLYr=~{S~o}Pq=#g>N3V` zWzytNuo@0Ndk662wUal7FW%X?@yO6_zM^PWa!=wE?ZFL;2)NOXZ)IFHmzO)w)u@`2wa0?JxI`@s-lW2xwOzZ5} zAMG{PL3-!ZR6*VD?~h=waU@_rNe~raWZ3rBw_EhieNbdGenu7QG<#%CaToBuB(Z%-x0lmfXtWdy>624<@?aJFY`=^?Tiv+l(k#ybi#;5m+jmRtliI)b+E ztm2A>;li7Z`%L6LSXm^GB=_FoiW9cb;m&31Qk%$H9lWCa~{GB(e$Z8&axZrh}o{`?o`3O zbKX}%?S=Q^kJ~G_;k%#ChtF%?iG!hVO^XNbF%He5UF9xG5q8ArG0wS&n1oh_2L^9& zfv>Py-!avf3KA(y$2d4-k7>mJ{r+$16np%b_q2lj#oAsL>xJbpjO{U>n6YR@Q3?Bt z{=FjhwlQ7<-O=x?{@kXgKWb|NFZ@GIcpSYOMmqBPg|At@DX5ovx!Jq96W1TZq{Nh5 zu+|YwYZ_*zCPOYAe^B=98}{8O-`oz_`ObKV|2tps@!7M~%-XIky;<9C6n~I1W(h2g zwG(aJ4q{-{i1Du68v5>Cwx0cJ?Sk%cTiN;CT8_lE+*<3k$5XR*M}sb@6kKA9KesI` z0TCumrzaN$3np&xKHla?oXp1k>~SUbp!RDE+7=Sf^RFecT+GDF+=`{&D>*>|9C-QU z^A614Re@u?eb1+mQ1%t$*WW|jHa@t_-}+QwE=FNJ3C9t1^=ZY zHu}6pFbAoE*-FsLg6_ZfOzW~_dGO3R)nel_rv;%%$YP*N)nb4H z9L>rhHs|cDCdQ>LX~2s@CT tJ|JcbsdxOBOzF<_|LxwG$O{Mqd8kG))hmnp%pvfnrJ<)@p!Ov2{{Y6zbb Date: Mon, 13 Jun 2022 10:58:02 +0800 Subject: [PATCH 039/130] =?UTF-8?q?update=20translation=20for=20isocut?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E6=8C=87=E5=8D=97.md=20at=2064ca75a?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../docs/TailorCustom/figures/lack_pack.png | Bin 0 -> 33182 bytes .../docs/TailorCustom/isocut-usage-guide.md | 568 +++++++++++++++++- docs/en/docs/secGear/api-description.md | 2 +- .../public_sys-resources/icon-note.gif | Bin 0 -> 394 bytes 4 files changed, 564 insertions(+), 6 deletions(-) create mode 100644 docs/en/docs/TailorCustom/figures/lack_pack.png create mode 100644 docs/en/docs/secGear/public_sys-resources/icon-note.gif diff --git a/docs/en/docs/TailorCustom/figures/lack_pack.png b/docs/en/docs/TailorCustom/figures/lack_pack.png new file mode 100644 index 0000000000000000000000000000000000000000..a4b7f1da15da70f63a86aae360e89017c2b98f2d GIT binary patch literal 33182 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 ] [ -r <*rpm_path*> ] < *source_iso* > < *dest_iso* > +**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] [ -k <*file_path*> ] < *source_iso* > < *dest_iso* > #### Parameter Description @@ -115,6 +116,7 @@ Run the `isocut` command to use the image tailoring and customization tool. The | --help \| -h | No| Queries the help information about the command.| | -t <*temp_path*> | No| Specifies the temporary directory *temp_path* for running the tool, which is an absolute path. The default value is **/tmp**.| | -r <*rpm_path*> | No| Specifies the path of the RPM packages to be added to the ISO image.| +| -k <*file_path*> | No | Specifies the kickstart template path if kickstart is used for automatic installation. | | *source_iso* | Yes| Path and name of the ISO source image to be tailored. If no path is specified, the current path is used by default.| | *dest_iso* | Yes| Specifies the path and name of the new ISO image created by the tool. If no path is specified, the current path is used by default.| @@ -126,7 +128,7 @@ The RPM packages of the new image can be: - Packages contained in an official ISO image. In this case, the RPM packages to be installed are specified in the configuration file **/etc/isocut/rpmlist**. The configuration format is *software_package_name.architecture*. For example, **kernel.aarch64**. -- Specified in addition. In this case, the RPM packages are stored in the path that is specified by the `-r` parameter when running the `isocut` command. +- Specified in addition. In this case, use the `-r` parameter to specify the path in which the RPM packages are stored when running the `isocut` command and add the RPM package names to the **/etc/isocut/rpmlist** configuration file. (See the name format above.) @@ -135,7 +137,132 @@ The RPM packages of the new image can be: >- When customizing an image, if an RPM package specified in the configuration file cannot be found, the RPM package will not be added to the image. >- If the dependency of the RPM package is incorrect, an error may be reported when running the tailoring and customization tool. - +### kickstart Functions + +You can use kickstart to install images automatically by using the `-k` parameter to specify a kickstart file when running the **isocut** command. + +The isocut tool provides a kickstart template (**/etc/isocut/anaconda-ks.cfg**). You can modify the template as required. + +#### Modifying the kickstart Template + +If you need to use the kickstart template provided by the isocut tool, perform the following modifications: + +- Configure the root user password and the GRUB2 password in the **/etc/isocut/anaconda-ks.cfg** file. Otherwise, the automatic image installation will pause during the password setting process, waiting for you to manually enter the passwords. +- If you want to specify additional RPM packages and use kickstart for automatic installation, specify the RPM packages in the **%packages** field in both the **/etc/isocut/rpmlist** file and the kickstart file. + +See the next section for details about how to modify the kickstart file. + +##### Configuring Initial Passwords + +###### Setting the Initial Password of the **root** User + +Set the initial password of the **root** user as follows in the **/etc/isocut/anaconda-ks.cfg** file. Replace **${pwd}** with the encrypted password. + +```shell +rootpw --iscrypted ${pwd} +``` + +Obtain the initial password of the **root** user as follows (**root** permissions are required): + +1. Add a user for generating the password, for example, **testUser**. + + ``` shell script + $ sudo useradd testUser + ``` + +2. Set the password for the **testUser** user. Run the following command to set the password as prompted: + + ``` shell script + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. View the **/etc/shadow** file to obtain the encrypted password. The encrypted password is the string between the two colons (:) following the **testUser** user name. (******* is used as an example.) + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:***:19052:0:90:7:35:: + ``` + +4. Run the following command to replace the **pwd** field in the **/etc/isocut/anaconda-ks.cfg** file with the encrypted password (replace __***__ with the actual password): + ``` shell script + rootpw --iscrypted *** + ``` + +###### Configuring the Initial GRUB2 Password + +Add the following configuration to the **/etc/isocut/anaconda-ks.cfg** file to set the initial GRUB2 password: Replace **${pwd}** with the encrypted password. + +```shell +%addon com_huawei_grub_safe --iscrypted --password='${pwd}' +%end +``` + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The **root** permissions are required for configuring the initial GRUB password. +> - The default user corresponding to the GRUB password is **root**. +> +> - The `grub2-set-password` command must exist in the system. If the command does not exist, install it in advance. + +1. Run the following command and set the GRUB2 password as prompted: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. After the command is executed, the **user.cfg** file is generated in the current directory. The content starting with **grub.pbkdf2.sha512** is the encrypted GRUB2 password. + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.*** + ``` + +3. Add the following information to the **/etc/isocut/anaconda-ks.cfg** file. Replace ******* with the encrypted GRUB2 password. + + ```shell + %addon com_huawei_grub_safe --iscrypted --password='grub.pbkdf2.sha512.***' + %end + ``` + +##### Configuring the %packages Field + +If you want to specify additional RPM packages and use kickstart for automatic installation, specify the RPM packages in the **%packages** field in both the **/etc/isocut/rpmlist** file and the kickstart file. + +This section describes how to specify RPM packages in the **/etc/isocut/anaconda-ks.cfg** file. + +The default configurations of **%packages** in the **/etc/isocut/anaconda-ks.cfg** file are as follows: + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +%end +``` + +Add specified RPM packages to the **%packages** configurations in the following format: + +*software_package_name.architecture*. For example, **kernel.aarch64**. + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +kernel.aarch64 +%end +``` ### Operation Guide @@ -200,3 +327,434 @@ The RPM packages of the new image can be: ```shell sudo isocut -t /home/temp -r /home/rpms /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso ``` + **Scenario 3**: The kickstart file is used for automatic installation. You need to modify the **/etc/isocut/anaconda-ks.cfg** file. + ```shell + sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-20.03-LTS-SP3-aarch64-dvd.iso /home/result/new.iso + ``` + + +## FAQs + +### The System Fails to Be Installed Using an Image Tailored Based on the Default RPM Package List + +#### Context + +When isocut is used to tailor an image, the **/etc/isocut/rpmlist** configuration file is used to specify the software packages to be installed. + +Images of different OS versions contain different software packages. As a result, some packages may be missing during image tailoring. +Therefore, the **/etc/isocut/rpmlist** file contains only the kernel software package by default, +ensuring that the image can be successfully tailored. + +#### Symptom + +The ISO image is successfully tailored using the default configuration, but fails to be installed. + +An error message is displayed during the installation, indicating that packages are missing: + +![](./figures/lack_pack.png) + +#### Possible Cause + +The ISO image tailored based on the default RPM package list lacks necessary RPM packages during installation. +The missing RPM packages are displayed in the error message, and may vary depending on the version. + +#### Solution + +1. Add the missing packages. + + 1. Find the missing RPM packages based on the error message. + 2. Add the missing RPM packages to the **/etc/isocut/rpmlist** configuration file. + 3. Tailor and install the ISO image again. + + For example, if the missing packages are those in the example error message, modify the **rpmlist** configuration file as follows: + ```shell + $ cat /etc/isocut/rpmlist + kernel.aarch64 + lvm2.aarch64 + chrony.aarch64 + authselect.aarch64 + shim.aarch64 + efibootmgr.aarch64 + grub2-efi-aa64.aarch64 + dosfstools.aarch64 + ``` +# isocut Usage Guide + +- [Introduction](#introduction) +- [Software and Hardware Requirements](#software-and-hardware-requirements) +- [Installation](#Installation) +- [Tailoring and Customizing an Image](#tailoring-and-customizing-an-image) + - [Command Description](#command-description) + - [Software Package Source](#software-package-source) + - [Operation Guide](#operation-guide) + + +## Introduction +The size of an openEuler image is large, and the process of downloading or transferring an image is time-consuming. In addition, when an openEuler image is used to install the OS, all RPM packages contained in the image are installed. You cannot choose to install only the required software packages. + +In some scenarios, you do not need to install the full software package provided by the image, or you need to install additional software packages. Therefore, openEuler provides an image tailoring and customization tool. You can use this tool to customize an ISO image that contains only the required RPM packages based on an openEuler image. The software packages can be the ones contained in an official ISO image or specified in addition to meet custom requirements. + +This document describes how to install and use the openEuler image tailoring and customization tool. + +## Software and Hardware Requirements + +The hardware and software requirements of the computer to make an ISO file using the openEuler tailoring and customization tool are as follows: + +- The CPU architecture is AArch64 or x86_64. +- The operating system is openEuler 22.03 LTS. +- You are advised to reserve at least 30 GB drive space for running the tailoring and customization tool and storing the ISO image. + +## Installation + +The following uses openEuler 22.03 LTS on the AArch64 architecture as an example to describe how to install the ISO image tailoring and customization tool. + +1. Ensure that openEuler 22.03 LTS has been installed on the computer. + + ``` shell script + $ cat /etc/openEuler-release + openEuler release 22.03 LTS + ``` + +2. Download the ISO image (must be an **everything** image) of the corresponding architecture and save it to any directory (it is recommended that the available space of the directory be greater than 20 GB). In this example, the ISO image is saved to the **/home/isocut_iso** directory. + + The download address of the AArch64 image is as follows: + + https://repo.openeuler.org/openEuler-22.03-LTS/ISO/aarch64/openEuler-22.03-LTS-everything-aarch64-dvd.iso + + > **Note:** + > The download address of the x86_64 image is as follows: + > + > https://repo.openeuler.org/openEuler-22.03-LTS/ISO/x86_64/openEuler-22.03-LTS-everything-x86_64-dvd.iso + +3. Create a **/etc/yum.repos.d/local.repo** file to configure the Yum source. The following is an example of the configuration file. **baseurl** is the directory for mounting the ISO image. + + ``` shell script + [local] + name=local + baseurl=file:///home/isocut_mount + gpgcheck=0 + enabled=1 + ``` + +4. Run the following command as the **root** user to mount the image to the **/home/isocut_mount** directory (ensure that the mount directory is the same as **baseurl** configured in the **repo** file) as the Yum source: + + ```shell + sudo mount -o loop /home/isocut_iso/openEuler-22.03-LTS-everything-aarch64-dvd.iso /home/isocut_mount + ``` + +5. Make the Yum source take effect. + + ```shell + yum clean all + yum makecache + ``` + +6. Install the image tailoring and customization tool as the **root** user. + + ```shell + sudo yum install -y isocut + ``` + +7. Run the following command as the **root** user to verify that the tool has been installed successfully: + + ```shell + $ sudo isocut -h + Checking input ... + usage: isocut [-h] [-t temporary_path] [-r rpm_path] [-k file_path] source_iso dest_iso + + Cut EulerOS iso to small one + + positional arguments: + source_iso source iso image + dest_iso destination iso image + + optional arguments: + -h, --help show this help message and exit + -t temporary_path temporary path + -r rpm_path extern rpm packages path + -k file_path kickstart file + ``` + + + +## Tailoring and Customizing an Image + +This section describes how to use the image tailoring and customization tool to create an image by tailoring or adding RPM packages to an openEuler image. + +### Command Description + +#### Format + +Run the `isocut` command to use the image tailoring and customization tool. The command format is as follows: + +**isocut** [ --help | -h ] [ -t <*temp_path*> ] [ -r <*rpm_path*> ] [ -k <*file_path*> ] < *source_iso* > < *dest_iso* > + +#### Parameter Description + +| Parameter| Mandatory| Description| +| ------------ | -------- | -------------------------------------------------------- | +| --help \| -h | No| Queries the help information about the command.| +| -t <*temp_path*> | No| Specifies the temporary directory *temp_path* for running the tool, which is an absolute path. The default value is **/tmp**.| +| -r <*rpm_path*> | No| Specifies the path of the RPM packages to be added to the ISO image.| +| -k <*file_path*> | No | Specifies the kickstart template path if kickstart is used for automatic installation. | +| *source_iso* | Yes| Path and name of the ISO source image to be tailored. If no path is specified, the current path is used by default.| +| *dest_iso* | Yes| Specifies the path and name of the new ISO image created by the tool. If no path is specified, the current path is used by default.| + + + +### Software Package Source + +The RPM packages of the new image can be: + +- Packages contained in an official ISO image. In this case, the RPM packages to be installed are specified in the configuration file **/etc/isocut/rpmlist**. The configuration format is *software_package_name.architecture*. For example, **kernel.aarch64**. + +- Specified in addition. In this case, use the `-r` parameter to specify the path in which the RPM packages are stored when running the `isocut` command and add the RPM package names to the **/etc/isocut/rpmlist** configuration file. (See the name format above.) + + + + >![](./public_sys-resources/icon-note.gif) **NOTE:** + > + >- When customizing an image, if an RPM package specified in the configuration file cannot be found, the RPM package will not be added to the image. + >- If the dependency of the RPM package is incorrect, an error may be reported when running the tailoring and customization tool. + +### kickstart Functions + +You can use kickstart to install images automatically by using the `-k` parameter to specify a kickstart file when running the **isocut** command. + +The isocut tool provides a kickstart template (**/etc/isocut/anaconda-ks.cfg**). You can modify the template as required. + +#### Modifying the kickstart Template + +If you need to use the kickstart template provided by the isocut tool, perform the following modifications: + +- Configure the root user password and the GRUB2 password in the **/etc/isocut/anaconda-ks.cfg** file. Otherwise, the automatic image installation will pause during the password setting process, waiting for you to manually enter the passwords. +- If you want to specify additional RPM packages and use kickstart for automatic installation, specify the RPM packages in the **%packages** field in both the **/etc/isocut/rpmlist** file and the kickstart file. + +See the next section for details about how to modify the kickstart file. + +##### Configuring Initial Passwords + +###### Setting the Initial Password of the **root** User + +Set the initial password of the **root** user as follows in the **/etc/isocut/anaconda-ks.cfg** file. Replace **${pwd}** with the encrypted password. + +```shell +rootpw --iscrypted ${pwd} +``` + +Obtain the initial password of the **root** user as follows (**root** permissions are required): + +1. Add a user for generating the password, for example, **testUser**. + + ``` shell script + $ sudo useradd testUser + ``` + +2. Set the password for the **testUser** user. Run the following command to set the password as prompted: + + ``` shell script + $ sudo passwd testUser + Changing password for user testUser. + New password: + Retype new password: + passwd: all authentication tokens updated successfully. + ``` + +3. View the **/etc/shadow** file to obtain the encrypted password. The encrypted password is the string between the two colons (:) following the **testUser** user name. (******* is used as an example.) + + ``` shell script + $ sudo cat /etc/shadow | grep testUser + testUser:***:19052:0:90:7:35:: + ``` + +4. Run the following command to replace the **pwd** field in the **/etc/isocut/anaconda-ks.cfg** file with the encrypted password (replace __***__ with the actual password): + ``` shell script + rootpw --iscrypted *** + ``` + +###### Configuring the Initial GRUB2 Password + +Add the following configuration to the **/etc/isocut/anaconda-ks.cfg** file to set the initial GRUB2 password: Replace **${pwd}** with the encrypted password. + +```shell +%addon com_huawei_grub_safe --iscrypted --password='${pwd}' +%end +``` + +> ![](./public_sys-resources/icon-note.gif) NOTE: +> +> - The **root** permissions are required for configuring the initial GRUB password. +> - The default user corresponding to the GRUB password is **root**. +> +> - The `grub2-set-password` command must exist in the system. If the command does not exist, install it in advance. + +1. Run the following command and set the GRUB2 password as prompted: + + ```shell + $ sudo grub2-set-password -o ./ + Enter password: + Confirm password: + grep: .//grub.cfg: No such file or directory + WARNING: The current configuration lacks password support! + Update your configuration with grub2-mkconfig to support this feature. + ``` + +2. After the command is executed, the **user.cfg** file is generated in the current directory. The content starting with **grub.pbkdf2.sha512** is the encrypted GRUB2 password. + + ```shell + $ sudo cat user.cfg + GRUB2_PASSWORD=grub.pbkdf2.sha512.*** + ``` + +3. Add the following information to the **/etc/isocut/anaconda-ks.cfg** file. Replace ******* with the encrypted GRUB2 password. + + ```shell + %addon com_huawei_grub_safe --iscrypted --password='grub.pbkdf2.sha512.***' + %end + ``` + +##### Configuring the %packages Field + +If you want to specify additional RPM packages and use kickstart for automatic installation, specify the RPM packages in the **%packages** field in both the **/etc/isocut/rpmlist** file and the kickstart file. + +This section describes how to specify RPM packages in the **/etc/isocut/anaconda-ks.cfg** file. + +The default configurations of **%packages** in the **/etc/isocut/anaconda-ks.cfg** file are as follows: + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +%end +``` + +Add specified RPM packages to the **%packages** configurations in the following format: + +*software_package_name.architecture*. For example, **kernel.aarch64**. + +```shell +%packages --multilib --ignoremissing +acl.aarch64 +aide.aarch64 +...... +NetworkManager.aarch64 +kernel.aarch64 +%end +``` + +### Operation Guide + + + +>![](./public_sys-resources/icon-note.gif) **NOTE:** +> +>- Do not modify or delete the default configuration items in the **/etc/isocut/rpmlist** file. +>- All `isocut` operations require **root** permissions. +>- The source image to be tailored can be a basic image or **everything** image. In this example, the basic image **openEuler-22.03-LTS-aarch64-dvd.iso** is used. +>- In this example, assume that the new image is named **new.iso** and stored in the **/home/result** directory, the temporary directory for running the tool is **/home/temp**, and the additional RPM packages are stored in the **/home/rpms** directory. + + + +1. Open the configuration file **/etc/isocut/rpmlist** and specify the RPM packages to be installed (from the official ISO image). + + ``` shell script + sudo vi /etc/isocut/rpmlist + ``` + +2. Ensure that the space of the temporary directory for running the image tailoring and customization tool is greater than 8 GB. The default temporary directory is** /tmp**. You can also use the `-t` parameter to specify another directory as the temporary directory. The path of the directory must be an absolute path. In this example, the **/home/temp** directory is used. The following command output indicates that the available drive space of the **/home** directory is 38 GB, which meets the requirements. + + ```shell + $ df -h + Filesystem Size Used Avail Use% Mounted on + devtmpfs 1.2G 0 1.2G 0% /dev + tmpfs 1.5G 0 1.5G 0% /dev/shm + tmpfs 1.5G 23M 1.5G 2% /run + tmpfs 1.5G 0 1.5G 0% /sys/fs/cgroup + /dev/mapper/openeuler_openeuler-root 69G 2.8G 63G 5% / + /dev/sda2 976M 114M 796M 13% /boot + /dev/mapper/openeuler_openeuler-home 61G 21G 38G 35% /home + ``` + +3. Tailor and customize the image. + + **Scenario 1**: All RPM packages of the new image are from the official ISO image. + + ``` shell script + $ sudo isocut -t /home/temp /home/isocut_iso/openEuler-22.03-LTS-aarch64-dvd.iso /home/result/new.iso + Checking input ... + Checking user ... + Checking necessary tools ... + Initing workspace ... + Copying basic part of iso image ... + Downloading rpms ... + Finish create yum conf + finished + Regenerating repodata ... + Checking rpm deps ... + Getting the description of iso image ... + Remaking iso ... + Adding checksum for iso ... + Adding sha256sum for iso ... + ISO cutout succeeded, enjoy your new image "/home/result/new.iso" + isocut.lock unlocked ... + ``` + If the preceding information is displayed, the custom image **new.iso** is successfully created. + + **Scenario 2**: The RPM packages of the new image are from the official ISO image and additional packages in **/home/rpms**. + + ```shell + sudo isocut -t /home/temp -r /home/rpms /home/isocut_iso/openEuler-22.03-LTS-aarch64-dvd.iso /home/result/new.iso + ``` + **Scenario 3**: The kickstart file is used for automatic installation. You need to modify the **/etc/isocut/anaconda-ks.cfg** file. + ```shell + sudo isocut -t /home/temp -k /etc/isocut/anaconda-ks.cfg /home/isocut_iso/openEuler-22.03-LTS-aarch64-dvd.iso /home/result/new.iso + ``` + + +## FAQs + +### The System Fails to Be Installed Using an Image Tailored Based on the Default RPM Package List + +#### Context + +When isocut is used to tailor an image, the **/etc/isocut/rpmlist** configuration file is used to specify the software packages to be installed. + +Images of different OS versions contain different software packages. As a result, some packages may be missing during image tailoring. +Therefore, the **/etc/isocut/rpmlist** file contains only the kernel software package by default, +ensuring that the image can be successfully tailored. + +#### Symptom + +The ISO image is successfully tailored using the default configuration, but fails to be installed. + +An error message is displayed during the installation, indicating that packages are missing: + +![](./figures/lack_pack.png) + +#### Possible Cause + +The ISO image tailored based on the default RPM package list lacks necessary RPM packages during installation. +The missing RPM packages are displayed in the error message, and may vary depending on the version. + +#### Solution + +1. Add the missing packages. + + 1. Find the missing RPM packages based on the error message. + 2. Add the missing RPM packages to the **/etc/isocut/rpmlist** configuration file. + 3. Tailor and install the ISO image again. + + For example, if the missing packages are those in the example error message, modify the **rpmlist** configuration file as follows: + ```shell + $ cat /etc/isocut/rpmlist + kernel.aarch64 + lvm2.aarch64 + chrony.aarch64 + authselect.aarch64 + shim.aarch64 + efibootmgr.aarch64 + grub2-efi-aa64.aarch64 + dosfstools.aarch64 + ``` diff --git a/docs/en/docs/secGear/api-description.md b/docs/en/docs/secGear/api-description.md index ec94310aa..4b06af500 100644 --- a/docs/en/docs/secGear/api-description.md +++ b/docs/en/docs/secGear/api-description.md @@ -10,7 +10,7 @@ Creates an enclave API. Initialization API. The function calls different TEE creation functions based on the type to initialize the enclave context in different TEE solutions. This API is called by the REE. ->![](./public_sys-resources/icon-note.gif) **说明:** +>![](./public_sys-resources/icon-note.gif) **Note:** > Due to Intel SGX restrictions, memory mapping contention exists when multiple thread invoke cc_enclave_create concurrently. As a result, the creation of the enclave API may fail. Avoid concurrent invocations of cc_enclave_create in your code. **Function Declarations:** diff --git a/docs/en/docs/secGear/public_sys-resources/icon-note.gif b/docs/en/docs/secGear/public_sys-resources/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 -- Gitee From bf3458e324a3b3cc9cdb3a60e1c6b1ef9eeb6851 Mon Sep 17 00:00:00 2001 From: mayunlong Date: Tue, 28 Jun 2022 17:32:19 +0800 Subject: [PATCH 040/130] =?UTF-8?q?update=20=E5=AF=B9=E6=8E=A5libvirt.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\257\271\346\216\245libvirt.md" | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" "b/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" index d655ecb9f..3b22a8384 100644 --- "a/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" +++ "b/docs/zh/docs/StratoVirt/\345\257\271\346\216\245libvirt.md" @@ -460,7 +460,7 @@ XML 中还有一些体系架构相关的配置,如 pflash、主板等。 /path/to/standard_vm_kernel console=hvc0 root=/dev/vda reboot=k panic=1 rw /path/to/pflash - /path/to/OVMF_VARS + /path/to/OVMF_VARS @@ -626,7 +626,7 @@ libvirt 使用 virsh 命令来管理虚拟机,当 StratoVirt 平台和 libvirt ### 管理虚拟机生命周期 -假设用户已经按照需要完成一个名为 stratovirt 的虚拟机配置文件 st.xml ,则对应生命周期管理的命令如下: +假设用户已经按照需要完成一个名为 StratoVirt 的虚拟机配置文件 st.xml ,则对应生命周期管理的命令如下: - 创建虚拟机 @@ -634,40 +634,40 @@ libvirt 使用 virsh 命令来管理虚拟机,当 StratoVirt 平台和 libvirt virsh create st.xml ``` - 虚拟机创建完成后,可以通过 **virsh list** 命令查看,会存在一个名为 stratovirt 的虚拟机。 + 虚拟机创建完成后,可以通过 **virsh list** 命令查看,会存在一个名为 StratoVirt 的虚拟机。 - 挂起虚拟机 ```shell - virsh suspend stratovirt + virsh suspend StratoVirt ``` - 虚拟机挂起后,虚拟机暂停运行。可以通过 **virsh list** 命令查看,虚拟机 stratovirt 的状态为 paused 。 + 虚拟机挂起后,虚拟机暂停运行。可以通过 **virsh list** 命令查看,虚拟机 StratoVirt 的状态为 paused 。 - 恢复虚拟机 ``` - virsh resume stratovirt + virsh resume StratoVirt ``` - 虚拟机恢复后,可以通过 **virsh list** 命令查看,虚拟机 stratovirt 的状态为 running 。 + 虚拟机恢复后,可以通过 **virsh list** 命令查看,虚拟机 StratoVirt 的状态为 running 。 - 销毁虚拟机 ``` - virsh destroy stratovirt + virsh destroy StratoVirt ``` - 虚拟机销毁后,使用 **virsh list** 查看虚拟机,发现虚拟机 stratovirt 不存在。 + 虚拟机销毁后,使用 **virsh list** 查看虚拟机,发现虚拟机 StratoVirt 不存在。 ### 登录虚拟机 -虚拟机创建完成后,可以通过 **virsh console** 登录虚拟机内部操作虚拟机。假设虚拟机名称为 stratovirt,参考命令如下: +虚拟机创建完成后,可以通过 **virsh console** 登录虚拟机内部操作虚拟机。假设虚拟机名称为 StratoVirt,参考命令如下: ``` -virsh console stratovirt +virsh console StratoVirt ``` -- Gitee From 2c6114b7a406d00abfd06a278b88ae26593aa272 Mon Sep 17 00:00:00 2001 From: "Xinle.Guo" Date: Fri, 24 Jun 2022 14:21:40 +0800 Subject: [PATCH 041/130] stratovirt: remove strating vm with json file StratoVirt does not support json file to start virtual machine. Delete related content from docs. Signed-off-by: Xinle.Guo --- ...37\346\234\272\347\256\241\347\220\206.md" | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" index ce0609811..17944d23d 100644 --- "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" +++ "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\347\256\241\347\220\206.md" @@ -72,7 +72,7 @@ StratoVirt可以对虚拟机进行启动、暂停、恢复、退出等生命周 ### 创建并启动虚拟机 -根据虚拟机配置可知,可以通过命令行参数或json文件指定虚拟机配置,并在主机通过stratovirt命令创建并启动虚拟机。 +通过命令行参数指定虚拟机配置,创建并启动虚拟机。 - 使用命令行参数给出虚拟机配置,创建并启动虚拟机的命令如下: @@ -80,23 +80,9 @@ StratoVirt可以对虚拟机进行启动、暂停、恢复、退出等生命周 $ /path/to/stratovirt -[参数1] [参数选项] -[参数2] [参数选项] ... ``` - - -- 使用json文件给出虚拟机配置,创建并启动虚拟机的命令如下: - -``` -$ /path/to/stratovirt \ - -config /path/to/json \ - -qmp unix:/path/to/socket -``` - -其中,/path/to/json为json配置文件的路径。/path/to/socket为用户指定的socket文件(如/tmp/stratovirt.socket),使用上述命令会自动创建socket文件。为确保虚拟机能够正常启动,在创建socket文件前确保该文件不存在。 - - - -> ![](./figures/zh-cn_image_0218587436.png) +> ![](./public_sys-resources/icon-note.gif)说明: > -> 虚拟机启动后,内部会有eth0和eth1两张网卡。这两张网卡预留用于网卡热插拔。热插的第一张网卡是eth0,热插的第二张网卡是eth1,目前只支持热插2张virtio-net网卡。 +> 轻量虚拟启动后,内部会有eth0和eth1两张网卡。这两张网卡预留用于网卡热插拔。热插的第一张网卡是eth0,热插的第二张网卡是eth1,目前只支持热插两张virtio-net网卡。 @@ -120,7 +106,7 @@ StratoVirt当前采用QMP管理虚拟机,暂停、恢复、退出虚拟机等 -> ![](./figures/zh-cn_image_0218587436.png) +> ![](./public_sys-resources/icon-note.gif)说明: > > QMP提供了stop、cont、quit和query-status等来管理和查询虚拟机状态。 > -- Gitee From 73a5b3347a3c9a74dbebd46ffbd0e2a121d208e5 Mon Sep 17 00:00:00 2001 From: YeXiao Date: Mon, 27 Jun 2022 16:05:32 +0800 Subject: [PATCH 042/130] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0:St?= =?UTF-8?q?ratoVirt=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97-=E5=87=86=E5=A4=87?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=8E=AF=E5=A2=83=201.=20alpine-mini=20rootf?= =?UTF-8?q?s=E4=B8=8B=E8=BD=BD=E8=B7=AF=E5=BE=84=E6=9B=B4=E6=96=B0=202.=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8E=A8=E8=8D=90=E5=86=85=E6=A0=B8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=9E=E6=8E=A5=E6=9B=B4=E6=96=B0=203.=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...77\347\224\250\347\216\257\345\242\203.md" | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" index f9890b5e5..43e7d2e59 100644 --- "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" +++ "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" @@ -4,7 +4,7 @@ ## 使用说明 - StratoVirt仅支持运行于x86_64和AArch64处理器架构下并启动相同架构的Linux虚拟机。 -- 建议在 openEuler 21.09 版本编译、调测和部署该版本 StratoVirt。 +- 建议在 openEuler 22.03 版本编译、调测和部署该版本 StratoVirt。 - StratoVirt支持以非root权限运行。 ## 环境要求 @@ -50,17 +50,17 @@ 1. 获取openEuler的kernel源代码,参考命令如下: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. 查看并切换kernel的版本到5.10,参考命令如下: +2. 查看并切换kernel的版本到openEuler-22.03-LTS,参考命令如下: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. 配置并编译Linux kernel。可使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将其复制到kernel路径下并重命名为`.config`。也可通过以下命令进行交互,根据提示完成kernel配置。 +3. 配置并编译Linux kernel。目前有两种方式可以生成配置文件:1. 使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将指定版本的推荐文件复制到kernel路径下并重命名为`.config`, 并执行命令`make olddefconfig`更新到最新的默认配置(否则后续编译可能有选项需要手动选择)。2. 通过以下命令进行交互,根据提示完成kernel配置,可能会提示缺少指定依赖,按照提示使用`yum install`命令进行安装。 ``` $ make menuconfig @@ -109,21 +109,21 @@ rootfs镜像是一种文件系统镜像,在StratoVirt启动时可以装载带 4. 获取对应处理器架构的最新alpine-mini rootfs。 - - 如果是AArch64处理器架构,参考命令如下: + - 对于AArch64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-aarch64.tar.gz ,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - 如果是x86_64处理器架构,参考命令如下: + - 对于x86_64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取指定架构最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-x86_64.tar.gz,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` -- Gitee From af410494cc9d4d03f31ca50d7e9148a9e27a22aa Mon Sep 17 00:00:00 2001 From: zhouli57 Date: Tue, 7 Jun 2022 19:55:48 +0800 Subject: [PATCH 043/130] StratoVirt: update StratoVirt version Signed-off-by: zhouli57 --- docs/en/docs/StratoVirt/Install_StratoVirt.md | 2 +- "docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/StratoVirt/Install_StratoVirt.md b/docs/en/docs/StratoVirt/Install_StratoVirt.md index b9a9fd8a1..4751e1131 100644 --- a/docs/en/docs/StratoVirt/Install_StratoVirt.md +++ b/docs/en/docs/StratoVirt/Install_StratoVirt.md @@ -31,7 +31,7 @@ To use StratoVirt virtualization, it is necessary to install StratoVirt. Before ``` $ stratovirt -version - StratoVirt 2.0.0 + StratoVirt 2.1.0 ``` diff --git "a/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" "b/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" index 81a8d9d21..fdfc80929 100644 --- "a/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" +++ "b/docs/zh/docs/StratoVirt/\345\256\211\350\243\205StratoVirt.md" @@ -33,7 +33,7 @@ ``` $ stratovirt -version - StratoVirt 2.0.0 + StratoVirt 2.1.0 ``` -- Gitee From ec847e9d74e8a81b762b8ca6cf5fc94cc0ba883e Mon Sep 17 00:00:00 2001 From: YeXiao Date: Mon, 27 Jun 2022 16:05:32 +0800 Subject: [PATCH 044/130] =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=9B=B4=E6=96=B0:St?= =?UTF-8?q?ratoVirt=E7=94=A8=E6=88=B7=E6=8C=87=E5=8D=97-=E5=87=86=E5=A4=87?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E7=8E=AF=E5=A2=83=201.=20alpine-mini=20rootf?= =?UTF-8?q?s=E4=B8=8B=E8=BD=BD=E8=B7=AF=E5=BE=84=E6=9B=B4=E6=96=B0=202.=20?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8E=A8=E8=8D=90=E5=86=85=E6=A0=B8=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E8=BF=9E=E6=8E=A5=E6=9B=B4=E6=96=B0=203.=20=E7=94=9F?= =?UTF-8?q?=E6=88=90=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/en/docs/StratoVirt/Prepare_env.md | 26 +++++++++---------- ...77\347\224\250\347\216\257\345\242\203.md" | 26 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/en/docs/StratoVirt/Prepare_env.md b/docs/en/docs/StratoVirt/Prepare_env.md index 55689ef71..54f80ed27 100644 --- a/docs/en/docs/StratoVirt/Prepare_env.md +++ b/docs/en/docs/StratoVirt/Prepare_env.md @@ -4,7 +4,7 @@ ## Usage - StratoVirt can run on VMs with the x86_64 or AArch64 processor architecture. -- You are advised to compile, debug, and deploy StratoVirt on openEuler 21.09. +- You are advised to compile, debug, and deploy StratoVirt on openEuler 22.03 LTS. - StratoVirt can run with non-root permissions. ## Environment Requirements @@ -50,17 +50,17 @@ StratoVirt of the current version supports only the PE kernel image of the x86_6 1. Run the following commands to obtain the kernel source code of openEuler: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. Run the following command to check and switch to the kernel version 5.10: +2. Run the following command to check and switch to the kernel version openEuler-22.03-LTS: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. Configure and compile the Linux kernel. It is better to use the recommended configuration file ([Obtain configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy it to the kernel directory, and rename it as **.config**. You can also run the following command to configure the kernel as prompted: +3. Configure and compile the Linux kernel. It is better to use the recommended configuration file ([Obtain configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy it to the kernel directory, and rename it as **.config**. And run the command 'make olddefconfig' to update to the latest default configuration (otherwise, there may be options for subsequent compilation that need to be manually selected). You can also run the following command to configure the kernel as prompted: ``` $ make menuconfig @@ -107,21 +107,21 @@ The rootfs image is a file system image. When StratoVirt is started, the ext4 im 4. Obtain the latest alpine-mini rootfs of the corresponding processor architecture. - - If the AArch64 processor architecture is used, run the following command: + - If the AArch64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-aarch64.tar.gz, the reference command is as follows: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - If the x86_64 processor architecture is used, run the following command: + - If the x86_64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-x86_64.tar.gz, the reference command is as follows: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` diff --git "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" index f9890b5e5..5c17d7213 100644 --- "a/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" +++ "b/docs/zh/docs/StratoVirt/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" @@ -4,7 +4,7 @@ ## 使用说明 - StratoVirt仅支持运行于x86_64和AArch64处理器架构下并启动相同架构的Linux虚拟机。 -- 建议在 openEuler 21.09 版本编译、调测和部署该版本 StratoVirt。 +- 建议在 openEuler 22.03 LTS 版本编译、调测和部署该版本 StratoVirt。 - StratoVirt支持以非root权限运行。 ## 环境要求 @@ -50,17 +50,17 @@ 1. 获取openEuler的kernel源代码,参考命令如下: ``` - $ git clone https://gitee.com/openeuler/kernel + $ git clone https://gitee.com/openeuler/kernel.git $ cd kernel ``` -2. 查看并切换kernel的版本到5.10,参考命令如下: +2. 查看并切换kernel的版本到openEuler-22.03-LTS,参考命令如下: ``` - $ git checkout kernel-5.10 + $ git checkout openEuler-22.03-LTS ``` -3. 配置并编译Linux kernel。可使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将其复制到kernel路径下并重命名为`.config`。也可通过以下命令进行交互,根据提示完成kernel配置。 +3. 配置并编译Linux kernel。目前有两种方式可以生成配置文件:1. 使用推荐配置([获取配置文件](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)),将指定版本的推荐文件复制到kernel路径下并重命名为`.config`, 并执行命令`make olddefconfig`更新到最新的默认配置(否则后续编译可能有选项需要手动选择)。2. 通过以下命令进行交互,根据提示完成kernel配置,可能会提示缺少指定依赖,按照提示使用`yum install`命令进行安装。 ``` $ make menuconfig @@ -109,21 +109,21 @@ rootfs镜像是一种文件系统镜像,在StratoVirt启动时可以装载带 4. 获取对应处理器架构的最新alpine-mini rootfs。 - - 如果是AArch64处理器架构,参考命令如下: + - 对于AArch64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-aarch64.tar.gz ,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.12.0-aarch64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-aarch64.tar.gz - $ rm alpine-minirootfs-3.12.0-aarch64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-aarch64.tar.gz + $ rm alpine-minirootfs-3.16.0-aarch64.tar.gz ``` - - 如果是x86_64处理器架构,参考命令如下: + - 对于x86_64处理器架构,从[alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/)网站获取指定架构最新alpine-mini rootfs,例如:alpine-minirootfs-3.16.0-x86_64.tar.gz,参考命令如下: ``` - $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.12.0-x86_64.tar.gz - $ tar -zxvf alpine-minirootfs-3.12.0-x86_64.tar.gz - $ rm alpine-minirootfs-3.12.0-x86_64.tar.gz + $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz + $ tar -zxvf alpine-minirootfs-3.16.0-x86_64.tar.gz + $ rm alpine-minirootfs-3.16.0-x86_64.tar.gz ``` -- Gitee From 6113ecfd6c0299d5a8813218d4bfbb6ad9e1580d Mon Sep 17 00:00:00 2001 From: xiusailong Date: Fri, 1 Jul 2022 10:43:01 +0800 Subject: [PATCH 045/130] update Gazelle.md --- docs/zh/docs/Gazelle/Gazelle.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/zh/docs/Gazelle/Gazelle.md b/docs/zh/docs/Gazelle/Gazelle.md index 61f298c06..3c1487c69 100644 --- a/docs/zh/docs/Gazelle/Gazelle.md +++ b/docs/zh/docs/Gazelle/Gazelle.md @@ -75,12 +75,12 @@ mkdir -p /mnt/hugepages mkdir -p /mnt/hugepages-2M chmod -R 700 /mnt/hugepages chmod -R 700 /mnt/hugepages-2M -mount -t hugetlbfs nodev /mnt/hugepages -mount -t hugetlbfs nodev /mnt/hugepages-2M +mount -t hugetlbfs nodev /mnt/hugepages -o pagesize=2M +mount -t hugetlbfs nodev /mnt/hugepages-2M -o pagesize=2M ``` ### 5. 应用程序使用Gazelle -有两种使能Gazelle方法,根据需要选择其一 +有两种使用Gazelle方法,根据需要选择其一 - 重新编译应用程序,链接Gazelle的库 修改应用makefile文件链接liblstack.so,示例如下: ``` @@ -256,8 +256,8 @@ Gazelle可能存在如下安全风险,用户需要根据使用场景评估风 - 风险点 属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致Gazelle程序crash。建议用户下的进程属于同一信任域。 -**流量限制** +**流量限制** Gazelle没有做流量限制,用户有能力发送最大网卡线速流量的报文到网络,可能导致网络流量拥塞。 -**进程仿冒** +**进程仿冒** 合法注册到ltran的两个lstack进程,进程A可仿冒进程B发送仿冒消息给ltran,修改ltran的转发控制信息,造成进程B通讯异常,进程B报文转发给进程A信息泄露等问题。建议lstack进程都为可信任进程。 -- Gitee From f09324f4a0127f52004a8fc640bd930d3241f921 Mon Sep 17 00:00:00 2001 From: z30023234 Date: Tue, 12 Jul 2022 17:25:14 +0800 Subject: [PATCH 046/130] add secGear desc --- .../\345\256\211\350\243\205secGear.md" | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git "a/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" "b/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" index 79b42ebe9..222b2a0ab 100644 --- "a/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" +++ "b/docs/zh/docs/secGear/\345\256\211\350\243\205secGear.md" @@ -1,14 +1,41 @@ # 安装 secGear -## 环境要求 +## 操作系统 -当前 secGear 仅支持以下软硬件,后续会逐步支持更多的软硬件。 +openEuler 21.03、openEuler 20.03 LTS SP2 或更高版本 -- 处理器:当前 secGear 仅支持 x86_64 处理器架构,且该处理器需要支持 Intel SGX (Intel Software Guard Extensions)功能 +## CPU 架构 -- 操作系统:openEuler 21.03 或更高版本 +#### x86_64 +需要有 Intel SGX ( Intel Software Guard Extensions ) 功能 + +#### AArch64 + + - 硬件要求 + + | 项目 | 版本 | + | ------ | --------------------------------------------- | + | 服务器 | TaiShan 200 服务器(型号 2280),仅限双路服务器 | + | 主板 | 鲲鹏主板 | + | BMC | 1711 单板(型号 BC82SMMAB) | + | CPU | 鲲鹏 920 处理器(型号 7260、5250、5220) | + | 机箱 | 不限,建议 8 盘或 12 盘 | + + 要求运行的泰山服务器已经预置了 TrustZone 特性,即预装 iTrustee 安全 OS 以及配套的 BMC、BIOS 固件。 + + - 运行环境要求 + + CA(Client Application)应用需要 REE(Rich Execution Environment)侧 patch 才能实现与 TEE(Trusted Execution Environment)侧的 TA(Trusted Application)应用通信,在安装 secGear 前,请先搭建运行环境,操作如下: + + 1. [搭建 TA/CA 应用运行环境](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0007.html#:~:text=%E6%90%AD%E5%BB%BA%3E%20%E6%90%AD%E5%BB%BA%E6%AD%A5%E9%AA%A4-,%E6%90%AD%E5%BB%BA%E6%AD%A5%E9%AA%A4,-%E6%9B%B4%E6%96%B0%E6%97%B6%E9%97%B4%EF%BC%9A2022) + + 2. 申请调测环境TA应用开发者证书 + + a. [生成 configs.xml 文件](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#:~:text=%E5%88%86%E4%BA%AB-,%E7%94%9F%E6%88%90configs.xml%E6%96%87%E4%BB%B6,-%E6%A0%B9%E6%8D%AEmanifest.txt) + + b. [申请 TA 开发者证书](https://support.huaweicloud.com/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#:~:text=%E5%86%85%E5%AE%B9%E4%BA%88%E4%BB%A5%E6%9B%BF%E6%8D%A2%E3%80%82-,TA%E5%BC%80%E5%8F%91%E8%80%85%E8%AF%81%E4%B9%A6%E7%94%B3%E8%AF%B7,-%E7%94%9F%E6%88%90%E6%9C%AC%E5%9C%B0%E5%AF%86) ## 安装指导 @@ -21,15 +48,9 @@ #yum install secGear-devel ``` - - -2. 查看安装是否成功。参考命令和回显如下表示安装成功。 +2. 查看安装是否成功。参考命令如下,若回显有对应软件包,表示安装成功: ```shell #rpm -q secGear - secGear-1.0-1.oe1.x86_64 #rpm -q secGear-devel - secGear-devel-1.0-1.oe1.x86_64 - ``` - - + ``` \ No newline at end of file -- Gitee From a6bbd96679e2a110353cd605ac5bc47f0c09c4fd Mon Sep 17 00:00:00 2001 From: z30023234 Date: Wed, 13 Jul 2022 09:29:44 +0800 Subject: [PATCH 047/130] fix invalid links --- ...1secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" index 2b3773d61..f74da9fee 100644 --- "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" +++ "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" @@ -419,7 +419,7 @@ 将设备公钥文件 rsa_public_key_cloud.pem 复制到 enclave 目录。此处的设备公钥用于使用临时生成的 aes 密钥对安全区动态库进行加密。 - 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/secGear/blob/master/examples/helloworld/enclave/rsa_public_key_cloud.pem + 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/itrustee_sdk/blob/master/build/signtools/cloud/rsa_public_key_cloud.pem -- Gitee From 016bd6a0d6fb4ff63547fe2ea008d0ec02252e1c Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Wed, 27 Jul 2022 16:10:04 +0800 Subject: [PATCH 048/130] update docs of master --- .../A-Tune/installation-and-deployment.md | 27 +++++---- .../Administration/basic-configuration.md | 44 +++++++++----- .../docs/StratoVirt/Interconnect_libvirt.md | 22 +++---- docs/en/docs/StratoVirt/Prepare_env.md | 8 +-- docs/en/docs/StratoVirt/VM_management.md | 41 +++++-------- ...-isolation-for-hybrid-deployed-services.md | 16 ++--- docs/en/docs/rubik/figures/icon-note.gif | Bin 0 -> 394 bytes docs/en/docs/rubik/http-apis.md | 6 +- .../docs/rubik/installation-and-deployment.md | 56 +++++++++--------- docs/en/docs/rubik/overview.md | 2 +- docs/en/docs/secGear/installing-secGear.md | 51 ++++++++++++---- .../docs/secGear/secGear-development-guide.md | 2 +- 12 files changed, 155 insertions(+), 120 deletions(-) create mode 100644 docs/en/docs/rubik/figures/icon-note.gif diff --git a/docs/en/docs/A-Tune/installation-and-deployment.md b/docs/en/docs/A-Tune/installation-and-deployment.md index c1a9b8117..0ed33848e 100644 --- a/docs/en/docs/A-Tune/installation-and-deployment.md +++ b/docs/en/docs/A-Tune/installation-and-deployment.md @@ -3,14 +3,19 @@ This chapter describes how to install and deploy A-Tune. - [Installation and Deployment](#installation-and-deployment) - - [Software and Hardware Requirements](#software-and-hardware-requirements) - - [Environment Preparation](#environment-preparation) - - [A-Tune Installation](#a-tune-installation) - - [Installation Modes](#installation-modes) - - [Installation Procedure](#installation-procedure) - - [A-Tune Deployment](#a-tune-deployment) - - [Starting A-Tune](#starting-a-tune) - - [Starting A-Tune engine](#starting-a-tune-engine) + - [Software and Hardware Requirements](#software-and-hardware-requirements) + - [Hardware Requirement](#hardware-requirement) + - [Software Requirement](#software-requirement) + - [Environment Preparation](#environment-preparation) + - [A-Tune Installation](#a-tune-installation) + - [Installation Modes](#installation-modes) + - [Installation Procedure](#installation-procedure) + - [A-Tune Deployment](#a-tune-deployment) + - [Overview](#overview) + - [Example](#example) + - [Example](#example-1) + - [Starting A-Tune](#starting-a-tune) + - [Starting A-Tune engine](#starting-a-tune-engine) @@ -31,7 +36,7 @@ For details about installing an openEuler OS, see _openEuler 21.03 Installation ## A-Tune Installation -This chapter describes the installation modes and methods of the A-Tune. +This section describes the installation modes and methods of the A-Tune. ### Installation Modes @@ -116,7 +121,7 @@ To install the A-Tune, perform the following steps: ## A-Tune Deployment -This chapter describes how to deploy A-Tune. +This section describes how to deploy A-Tune. @@ -337,7 +342,7 @@ After the A-Tune is installed, you need to start the A-Tune service. ![](./figures/en-us_image_0214540398.png) -## Starting A-Tune engine +## Starting A-Tune Engine To use AI functions, you need to start the A-Tune engine service. diff --git a/docs/en/docs/Administration/basic-configuration.md b/docs/en/docs/Administration/basic-configuration.md index 617937b9b..5b1b5782e 100644 --- a/docs/en/docs/Administration/basic-configuration.md +++ b/docs/en/docs/Administration/basic-configuration.md @@ -3,22 +3,34 @@ - [Basic Configuration](#basic-configuration) - - [Setting the System Locale](#setting-the-system-locale) - - [Displaying the Current Locale Status](#displaying-the-current-locale-status) - - [Listing Available Locales](#listing-available-locales) - - [Setting the Locale](#setting-the-locale) - - [Setting the Keyboard Layout](#setting-the-keyboard-layout) - - [Displaying the Current Settings](#displaying-the-current-settings) - - [Listing Available Keyboard Layouts](#listing-available-keyboard-layouts) - - [Setting the Keyboard Layout](#setting-the-keyboard-layout-1) - - [Setting the Date and Time](#setting-the-date-and-time) - - [Using the timedatectl Command](#using-the-timedatectl-command) - - [Using the date Command](#using-the-date-command) - - [Using the hwclock Command](#using-the-hwclock-command) - - [Setting kdump](#setting-kdump) - - [Setting the Memory Reserved for kdump](#setting-the-memory-reserved-for-kdump) - - [Recommended Reserved Memory](#recommended-reserved-memory) - - [Disabling Network Drivers](#disabling-network-drivers) + - [Setting the System Locale](#setting-the-system-locale) + - [Displaying the Current Locale Status](#displaying-the-current-locale-status) + - [Listing Available Locales](#listing-available-locales) + - [Setting the Locale](#setting-the-locale) + - [Setting the Keyboard Layout](#setting-the-keyboard-layout) + - [Displaying the Current Settings](#displaying-the-current-settings) + - [Listing Available Keyboard Layouts](#listing-available-keyboard-layouts) + - [Setting the Keyboard Layout](#setting-the-keyboard-layout-1) + - [Setting the Date and Time](#setting-the-date-and-time) + - [Using the timedatectl Command](#using-the-timedatectl-command) + - [Displaying the Current Date and Time](#displaying-the-current-date-and-time) + - [Synchronizing the System Clock with a Remote Server](#synchronizing-the-system-clock-with-a-remote-server) + - [Changing the Current Date](#changing-the-current-date) + - [Changing the Current Time](#changing-the-current-time) + - [Changing the Time Zone](#changing-the-time-zone) + - [Using the date Command](#using-the-date-command) + - [Displaying the Current Date and Time](#displaying-the-current-date-and-time-1) + - [Changing the Current Time](#changing-the-current-time-1) + - [Changing the Current Date](#changing-the-current-date-1) + - [Using the hwclock Command](#using-the-hwclock-command) + - [Real-Time Clock and System Clock](#real-time-clock-and-system-clock) + - [Displaying the Current Date and Time](#displaying-the-current-date-and-time-2) + - [Setting the Date and Time](#setting-the-date-and-time-1) + - [Setting kdump](#setting-kdump) + - [Setting the Memory Reserved for kdump](#setting-the-memory-reserved-for-kdump) + - [Parameter Formats of the Memory Reserved for kdump](#parameter-formats-of-the-memory-reserved-for-kdump) + - [Recommended Reserved Memory](#recommended-reserved-memory) + - [Disabling Network Drivers](#disabling-network-drivers) ## Setting the System Locale diff --git a/docs/en/docs/StratoVirt/Interconnect_libvirt.md b/docs/en/docs/StratoVirt/Interconnect_libvirt.md index 8d0788ab1..8cfa7d0b4 100644 --- a/docs/en/docs/StratoVirt/Interconnect_libvirt.md +++ b/docs/en/docs/StratoVirt/Interconnect_libvirt.md @@ -501,7 +501,7 @@ Configure a server named StratoVirt with 8 GiB memory, 1 GiB huge pages, and fou /path/to/standard_vm_kernel console=hvc0 root=/dev/vda reboot=k panic=1 rw /path/to/pflash - /path/to/OVMF_VARS + /path/to/OVMF_VARS @@ -667,7 +667,7 @@ libvirt uses `virsh` commands to manage VMs. After the StratoVirt platform is in ### VM Lifecycle Management -If you have created a VM configuration file named **stratovirt** in st.xml format, you can use the following commands for VM lifecycle management: +If you have created a VM configuration file named **StratoVirt** in st.xml format, you can use the following commands for VM lifecycle management: - Creating a VM. @@ -675,40 +675,40 @@ If you have created a VM configuration file named **stratovirt** in st.xml forma virsh create st.xml ``` - After the VM is created, you can run the `virsh list` command to check whether a VM named **stratovirt** exists. + After the VM is created, you can run the `virsh list` command to check whether a VM named **StratoVirt** exists. - Suspending a VM. ```shell - virsh suspend stratovirt + virsh suspend StratoVirt ``` - After the VM is suspended, it stops running. You can run the `virsh list` command to check whether the status of VM **stratovirt** is **paused**. + After the VM is suspended, it stops running. You can run the `virsh list` command to check whether the status of VM **StratoVirt** is **paused**. - Resuming a VM. ``` - virsh resume stratovirt + virsh resume StratoVirt ``` - After the VM is resumed, you can run the `virsh list` command to check whether the status of VM **stratovirt** is **running**. + After the VM is resumed, you can run the `virsh list` command to check whether the status of VM **StratoVirt** is **running**. - Destroying a VM. ``` - virsh destroy stratovirt + virsh destroy StratoVirt ``` - After the VM is destroyed, you can run the `virsh list` command to check that VM **stratovirt** does not exist. + After the VM is destroyed, you can run the `virsh list` command to check that VM **StratoVirt** does not exist. ### VM Login -After the VM is created, you can run the `virsh console` command to log in to it to perform specific operations. If the VM name is **stratovirt**, run the following command: +After the VM is created, you can run the `virsh console` command to log in to it to perform specific operations. If the VM name is **StratoVirt**, run the following command: ``` -virsh console stratovirt +virsh console StratoVirt ``` diff --git a/docs/en/docs/StratoVirt/Prepare_env.md b/docs/en/docs/StratoVirt/Prepare_env.md index 54f80ed27..5b827dd29 100644 --- a/docs/en/docs/StratoVirt/Prepare_env.md +++ b/docs/en/docs/StratoVirt/Prepare_env.md @@ -60,7 +60,7 @@ StratoVirt of the current version supports only the PE kernel image of the x86_6 $ git checkout openEuler-22.03-LTS ``` -3. Configure and compile the Linux kernel. It is better to use the recommended configuration file ([Obtain configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy it to the kernel directory, and rename it as **.config**. And run the command 'make olddefconfig' to update to the latest default configuration (otherwise, there may be options for subsequent compilation that need to be manually selected). You can also run the following command to configure the kernel as prompted: +3. Configure and compile the Linux kernel. You are advised to use the [recommended configuration file](https://gitee.com/openeuler/stratovirt/tree/master/docs/kernel_config)). Copy the file to the kernel directory, rename it to **.config**, and run the `make olddefconfig` command to update to the latest default configuration (otherwise, you may need to manually select options for subsequent compilation). Alternatively, you can run the following command to configure the kernel as prompted. The system may display a message indicating that specific dependencies are missing. Run the `yum install` command to install the dependencies as prompted. ``` $ make menuconfig @@ -107,7 +107,7 @@ The rootfs image is a file system image. When StratoVirt is started, the ext4 im 4. Obtain the latest alpine-mini rootfs of the corresponding processor architecture. - - If the AArch64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-aarch64.tar.gz, the reference command is as follows: + - If the AArch64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-aarch64.tar.gz, the reference commands are as follows: ``` $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/aarch64/alpine-minirootfs-3.16.0-aarch64.tar.gz @@ -116,7 +116,7 @@ The rootfs image is a file system image. When StratoVirt is started, the ext4 im ``` - - If the x86_64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-x86_64.tar.gz, the reference command is as follows: + - If the x86_64 processor architecture is used, you can get the latest rootfs from the [alpine](http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/). For example, alpine-minirootfs-3.16.0-x86_64.tar.gz, the reference commands are as follows: ``` $ wget http://dl-cdn.alpinelinux.org/alpine/latest-stable/releases/x86_64/alpine-minirootfs-3.16.0-x86_64.tar.gz @@ -125,7 +125,7 @@ The rootfs image is a file system image. When StratoVirt is started, the ext4 im ``` -5. Run the following command to create a simple **/sbin/init** for the ext4 file image: +5. Run the following commands to create a simple **/sbin/init** for the ext4 file image: ``` $ rm sbin/init; touch sbin/init && cat > sbin/init < ![](./public_sys-resources/note.png) +> ![](./public_sys-resources/icon-note.gif) > -> After the VM is started, there are two NICs: eth0 and eth1. The two NICs are reserved for hot plugging: eth0 first and then eth1. Currently, only two virtio-net NICs can be hot plugged. +> After the lightweight VM is started, there are two NICs: eth0 and eth1. The two NICs are reserved for hot plugging: eth0 first and then eth1. Currently, only two virtio-net NICs can be hot plugged. ### Connecting to a VM -StratoVirt uses QMP to manage VMs. To suspend, resume, or exit a VM, connect it the StratoVirt through QMP first. +StratoVirt uses QMP to manage VMs. To stop, resume, or exit a VM, connect it the StratoVirt through QMP first. Open a new CLI (CLI B) on the host and run the following command to connect to the api-channel as the **root** user: @@ -107,21 +98,21 @@ After the connection is set up, you will receive a greeting message from StratoV You can now manage the VM by entering the QMP commands in CLI B. -> ![](./public_sys-resources/note.png) +> ![](./public_sys-resources/icon-note.gif) > -> QMP provides stop, cont, quit, and query-status commands to manage and query VM statuses. +> QMP provides **stop**, **cont**, **quit**, and **query-status** commands to manage and query VM statuses. > > All QMP commands for managing VMs are entered in CLI B. `<-` indicates the command input, and `->` indicates the QMP returned result. -### Suspending a VM +### Stopping a VM -QMP provides the stop command to suspend a VM, that is, to suspend all vCPUs of the VM. The command syntax is as follows: +QMP provides the **stop** command to stop a VM, that is, to stop all vCPUs of the VM. The command syntax is as follows: **{"execute":"stop"}** **Example:** -The stop command and the command output are as follows: +The **stop** command and the command output are as follows: ``` <- {"execute":"stop"} @@ -131,13 +122,13 @@ The stop command and the command output are as follows: ### Resuming a VM -QMP provides the cont command to resume a suspended VM, that is, to resume all vCPUs of the VM. The command syntax is as follows: +QMP provides the **cont** command to resume a stopped VM, that is, to resume all vCPUs of the VM. The command syntax is as follows: **{"execute":"cont"}** **Example:** -The cont command and the command output are as follows: +The **cont** command and the command output are as follows: ``` <- {"execute":"cont"} @@ -147,7 +138,7 @@ The cont command and the command output are as follows: ### Exiting a VM -QMP provides the quit command to exit a VM, that is, to exit the StratoVirt process. The command syntax is as follows: +QMP provides the **quit** command to exit a VM, that is, to exit the StratoVirt process. The command syntax is as follows: **{"execute":"quit"}** @@ -495,7 +486,7 @@ Query the actual memory of the VM: A VM memory snapshot stores the device status and memory information of a VM in a snapshot file. If the VM is damaged, you can use the snapshot to restore it to the time when the snapshot was created, improving system reliability. -StratoVirt allows you to create snapshots for suspended VMs and create VMs in batches with a snapshot file as the VM template. As long as a snapshot is created after a VM is started and enters the user mode, the quick startup can skip the kernel startup and user-mode service initialization phases and complete the VM startup in milliseconds. +StratoVirt allows you to create snapshots for stopped VMs and create VMs in batches with a snapshot file as the VM template. As long as a snapshot is created after a VM is started and enters the user mode, the quick startup can skip the kernel startup and user-mode service initialization phases and complete the VM startup in milliseconds. ### Mutually Exclusive Features @@ -514,7 +505,7 @@ For StratoVirt VMs, perform the following steps to create a storage snapshot: 1. Create and start a VM. -2. Run the QMP command on the host to suspend the VM. +2. Run the QMP command on the host to stop the VM. ```shell <- {"execute":"stop"} @@ -523,7 +514,7 @@ For StratoVirt VMs, perform the following steps to create a storage snapshot: ``` -3. Confirm that the VM is suspended. +3. Confirm that the VM is stopped. ```shell <- {"execute":"query-status"} diff --git a/docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md b/docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md index d22445615..669a51b6a 100644 --- a/docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md +++ b/docs/en/docs/rubik/example-of-isolation-for-hybrid-deployed-services.md @@ -5,8 +5,8 @@ Check whether the kernel supports isolation of hybrid deployed services. ```bash -# Check whether isolation of hybrid deployed services is enabled in the **/boot/config-** system configuration. -# If **CONFIG_QOS_SCHED=y**, the function is enabled. Example: +# Check whether isolation of hybrid deployed services is enabled in the /boot/config- system configuration. +# If CONFIG_QOS_SCHED=y, the function is enabled. Example: cat /boot/config-5.10.0-60.18.0.50.oe2203.x86_64 | grep CONFIG_QOS CONFIG_QOS_SCHED=y ``` @@ -47,13 +47,13 @@ Use the clickhouse-benchmark tool to test the performance and collect statistics **Offline Service Stress** -Stress is a CPU-intensive test tool. You can specify the **--cpu** parameter to start multiple concurrent CPU-intensive tasks to increase the stress on the system. +Stress is a CPU-intensive test tool. You can specify the **--cpu** option to start multiple concurrent CPU-intensive tasks to increase the stress on the system. -### Usage +### Usage Instructions 1) Start a ClickHouse container (online service). -2) Access the container and run the **clickhouse-benchmark** command. Set the number of concurrent threads to 10, the number of query times to 10000, and the total query time to 30s. +2) Access the container and run the **clickhouse-benchmark** command. Set the number of concurrent queries to **10**, the number of queries to **10000**, and time limit to **30**. 3) Start a Stress container (offline service) at the same time and concurrently execute 10 CPU-intensive tasks to increase the stress on the environment. @@ -135,7 +135,7 @@ Independently execute the online service ClickHouse. sh test_demo.sh no_offline no_isolation ``` -The QoS **baseline data** (QPS/P50/P90/P99) of the online service is as follows: +The baseline QoS data (QPS/P50/P90/P99) of the online service is as follows: ```json { @@ -159,7 +159,7 @@ The QoS **baseline data** (QPS/P50/P90/P99) of the online service is as follows: } ``` -Start the offline service Stress, disable isolation of hybrid deployed services, and execute the **test_demo.sh** script. +Execute the **test_demo.sh** script to start the offline service Stress and run the test with the isolation function disabled. ```bash # **with_offline** indicates that the offline service Stress is enabled. @@ -190,7 +190,7 @@ sh test_demo.sh with_offline no_isolation } ``` -Start the offline service Stress, enable isolation of hybrid deployed services, and execute the **test_demo.sh** script. +Execute the **test_demo.sh** script to start the offline service Stress and run the test with the isolation function enabled. ```bash # **with_offline** indicates that the offline service Stress is enabled. diff --git a/docs/en/docs/rubik/figures/icon-note.gif b/docs/en/docs/rubik/figures/icon-note.gif new file mode 100644 index 0000000000000000000000000000000000000000..6314297e45c1de184204098efd4814d6dc8b1cda GIT binary patch literal 394 zcmZ?wbhEHblx7fPSjxcg=ii?@_wH=jwxy=7CMGH-B`L+l$wfv=#>UF#$gv|VY%C^b zCQFtrnKN(Bo_%|sJbO}7RAORe!otL&qo<>yq_Sq+8Xqqo5h0P3w3Lvb5E(g{p01vl zxR@)KuDH0l^z`+-dH3eaw=XqSH7aTIx{kzVBN;X&hha0dQSgWuiw0NWUvMRmkD|> literal 0 HcmV?d00001 diff --git a/docs/en/docs/rubik/http-apis.md b/docs/en/docs/rubik/http-apis.md index e5d315a0a..f7f475205 100644 --- a/docs/en/docs/rubik/http-apis.md +++ b/docs/en/docs/rubik/http-apis.md @@ -8,7 +8,7 @@ The open APIs of Rubik are all HTTP APIs, including the API for setting or updat ### API for Setting or Updating the Pod Priority -Rubik provides the function of setting or updating the pod priority. External systems can call this API to send pod information. Rubik sets the priority based on the received pod information to isolate resources. The API calling format is as follows: +Rubik provides the function of setting or updating the pod priority. External systems can call this API to send pod information. Rubik sets the priority based on the received pod information to isolate resources. The API call format is as follows: ```bash HTTP POST /run/rubik/rubik.sock @@ -41,7 +41,7 @@ curl -v -H "Accept: application/json" -H "Content-type: application/json" -X POS ### API for Detecting Availability -As an HTTP service, Rubik provides an API for detecting whether Rubik is running. +As an HTTP service, Rubik provides an API for detecting whether it is running. API format: HTTP/GET /ping @@ -55,7 +55,7 @@ If **ok** is returned, the Rubik service is running. ### API for Querying Version Information -Rubik allows you to query the current Rubik version number through an HTTP request. +Rubik allows you to query the Rubik version number through an HTTP request. API format: HTTP/GET /version diff --git a/docs/en/docs/rubik/installation-and-deployment.md b/docs/en/docs/rubik/installation-and-deployment.md index 6a713ec22..9515677ad 100644 --- a/docs/en/docs/rubik/installation-and-deployment.md +++ b/docs/en/docs/rubik/installation-and-deployment.md @@ -2,13 +2,13 @@ ## Overview -This document describes how to install and deploy the Rubik component. +This chapter describes how to install and deploy the Rubik component. ## Software and Hardware Requirements ### Hardware -* Architectures: x86 and AArch64 +* Architecture: x86 or AArch64 * Drive: 1 GB or more * Memory: 100 MB or more @@ -27,10 +27,10 @@ This document describes how to install and deploy the Rubik component. Rubik is deployed on each Kubernetes node as a DaemonSet. Therefore, you need to perform the following steps to install the Rubik RPM package on each node. -1. Configure the Yum repositories openEuler 22.03-LTS and openEuler 22.03-LTS:EPOL (Rubik component is available only in the EPOL repository). +1. Configure the Yum repositories openEuler 22.03-LTS and openEuler 22.03-LTS:EPOL (the Rubik component is available only in the EPOL repository). ``` - # openEuler 22.03-LTS officially released repository + # openEuler 22.03-LTS official repository name=openEuler22.03 baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/everything/$basearch/ enabled=1 @@ -39,27 +39,27 @@ Rubik is deployed on each Kubernetes node as a DaemonSet. Therefore, you need to ``` ``` - # openEuler 22.03-LTS:EPOL officially released repository + # openEuler 22.03-LTS:EPOL official repository name=Epol baseurl=https://repo.openeuler.org/openEuler-22.03-LTS/EPOL/$basearch/ enabled=1 gpgcheck=0 ``` -2. Install Rubik as the **root** user. +2. Install Rubik with **root** permissions. ```shell sudo yum install -y rubik ``` -> ![](D:\Typora-image\icon-note.gif)**Note**: +> ![](./figures/icon-note.gif)**Note**: > -> Files related to the Rubik tool are installed in the **/var/lib/rubik** directory. +> Files related to Rubik are installed in the **/var/lib/rubik** directory. ## Deploying Rubik -Rubik runs as a container in a Kubernetes cluster in hybrid deployment scenarios. It is used to isolate and restrict resources for services with different priorities to prevent offline services from interfering with online services, improving the overall resource utilization and ensuring the service quality of online services. Currently, Rubik supports isolation and restriction of CPU and memory resources, which must be used together with the openEuler 22.03-LTS kernel. To enable the memory priority feature (that is, to implement memory resource tiering for services with different priorities), you need to set **/proc/sys/vm/memcg_qos_enable**. The value can be **0** or **1**. The default value **0** indicates that the feature is disabled, and the value **1** indicates that the feature is enabled. +Rubik runs as a container in a Kubernetes cluster in hybrid deployment scenarios. It is used to isolate and restrict resources for services with different priorities to prevent offline services from interfering with online services, improving the overall resource utilization and ensuring the quality of online services. Currently, Rubik supports isolation and restriction of CPU and memory resources, and must be used together with the openEuler 22.03-LTS kernel. To enable or disable the memory priority feature (that is, memory tiering for services with different priorities), you need to set the value in the **/proc/sys/vm/memcg_qos_enable** file. The value can be **0** or **1**. The default value **0** indicates that the feature is disabled, and the value **1** indicates that the feature is enabled. ```bash sudo echo 1 > /proc/sys/vm/memcg_qos_enable @@ -67,13 +67,13 @@ sudo echo 1 > /proc/sys/vm/memcg_qos_enable ### Deploying Rubik DaemonSet -1. Use the Docker or isula-build engine to build Rubik images. Because Rubik is deployed as a DaemonSet, each node requires a Rubik image. After building an image on a node, use the `docker save/load` command to load the Rubik image to each node of Kubernetes. Alternatively, build a Rubik image on each node. The following uses isula-build as an example. The command is as follows: +1. Use the Docker or isula-build engine to build Rubik images. Because Rubik is deployed as a DaemonSet, each node requires a Rubik image. After building an image on a node, use the **docker save** and **docker load** commands to load the Rubik image to each node of Kubernetes. Alternatively, build a Rubik image on each node. The following uses isula-build as an example. The command is as follows: ```sh isula-build ctr-img build -f /var/lib/rubik/Dockerfile --tag rubik:0.1.0 . ``` -2. On the Kubernetes master node, change the Rubik image name in the `/var/lib/rubik/rubik-daemonset.yaml` file to the name of the image built in the previous step. +1. On the Kubernetes master node, change the Rubik image name in the **/var/lib/rubik/rubik-daemonset.yaml** file to the name of the image built in the previous step. ```yaml ... @@ -84,13 +84,13 @@ containers: ... ``` -3. On the Kubernetes master node, run the `kubectl` command to deploy the Rubik DaemonSet. Rubik is automatically deployed on all Kubernetes nodes. +3. On the Kubernetes master node, run the **kubectl** command to deploy the Rubik DaemonSet so that Rubik will be automatically deployed on all Kubernetes nodes. ```sh kubectl apply -f /var/lib/rubik/rubik-daemonset.yaml ``` -4. Run the `kubectl get pods -A` command to check whether Rubik has been deployed on each node in the cluster. (The number of rubik-agents is the same as the number of nodes and all rubik-agents are in the Running state.) +4. Run the **kubectl get pods -A** command to check whether Rubik has been deployed on each node in the cluster. (The number of rubik-agents is the same as the number of nodes and all rubik-agents are in the Running status.) ```sh [root@localhost rubik]# kubectl get pods -A @@ -102,14 +102,14 @@ kube-system rubik-agent-76ft6 1/1 Running ## Common Configuration Description -The Rubik deployed using the preceding method is started with the default configuration. You can modify the Rubik configuration as required by modifying the **config.json** section in the **rubik-daemonset.yaml** file and then redeploy the Rubik DaemonSet. +The Rubik deployed using the preceding method is started with the default configurations. You can modify the Rubik configurations as required by modifying the **config.json** section in the **rubik-daemonset.yaml** file and then redeploy the Rubik DaemonSet. -This section describes common configurations of **config.json**. +This section describes common configurations in **config.json**. ### Configuration Item Description ```yaml -# The configuration items are in the **config.json** section of the **rubik-daemonset.yaml** file. +# The configuration items are in the config.json section of the rubik-daemonset.yaml file. { "autoConfig": true, "autoCheck": false, @@ -133,21 +133,21 @@ This section describes common configurations of **config.json**. ### Automatic Configuration of Pod Priorities -If **autoConfig** is set to **true** in the Rubik configuration to enable automatic pod awareness, you only need to specify the priority in **annotation** in the YAML file when deploying the service pod. After the deployment, Rubik automatically detects the creation and update of the pods on the current node, and sets the pod priorities based on the configured priorities. +If **autoConfig** is set to **true** in **config.json** to enable automatic pod awareness, you only need to specify the priority using annotations in the YAML file when deploying the service pods. After being deployed successfully, Rubik automatically detects the creation and update of the pods on the current node, and sets the pod priorities based on the configured priorities. ### Pod Priority Configuration Depending on kubelet -The automatic configuration of the pod priority depends on the event notification created by **api-server pod**, which has a certain delay. The pod priority cannot be configured before the process is started. As a result, the service performance may fluctuate. You can disable the automatic priority configuration option by modifying the kubelet source code. After the container cgroup is created and before the container process is started, call the Rubik HTTP API to configure the pod priorities. For details about how to use the HTTP API, see [HTTP APIs](./http-apis.md). +Automatic pod priority configuration depends on the pod creation event notifications from the API server, which have a certain delay. The pod priority cannot be configured before the process is started. As a result, the service performance may fluctuate. To avoid this problem, you can disable the automatic priority configuration option and modify the kubelet source code, so that pod priorities can be configured using Rubik HTTP APIs after the cgroup of each container is created and before each container process is started. For details about how to use the HTTP APIs, see [HTTP APIs](./http-apis.md). ### Automatic Verification of Pod Priorities Rubik supports consistency check on the pod QoS priority configurations of the current node during startup. It checks whether the configuration in the Kubernetes cluster is consistent with the pod priority configuration of Rubik. This function is disabled by default. You can enable or disable it using the **autoCheck** option. If this function is enabled, Rubik automatically verifies and corrects the pod priority configuration of the current node when it is started or restarted. -## Example of Configuring Rubik for Offline Services +## Configuring Rubik for Online and Offline Services -After Rubik is successfully deployed, you can modify the YAML file of a service based on the following configuration example to specify the offline service. Then Rubik can configure the priority of the service after the service is deployed to isolate resources. +After Rubik is successfully deployed, you can modify the YAML file of a service to specify the service type based on the following configuration example. Then Rubik can configure the priority of the service after it is deployed to isolate resources. -The following is an example of deploying the online service Nginx: +The following is an example of deploying an online Nginx service: ```yaml apiVersion: v1 @@ -156,7 +156,7 @@ metadata: name: nginx namespace: qosexample annotations: - volcano.sh/preemptable: "false" # If **volcano.sh/preemptable** is set to **true**, the service is an offline service. If it is set to **false**, the service is an online service. The default value is **false**. + volcano.sh/preemptable: "false" # If volcano.sh/preemptable is set to true, the service is an offline service. If it is set to false, the service is an online service. The default value is false. spec: containers: - name: nginx @@ -174,9 +174,9 @@ spec: - The maximum number of concurrent HTTP requests that Rubik can receive is 1,000 QPS. If the number of concurrent HTTP requests exceeds the upper limit, an error is reported. -- The maximum number of pods in a single request received by Rubik is 100. If the number of pods exceeds the threshold, an error is reported. +- The maximum number of pods in a single request received by Rubik is 100. If the number of pods exceeds the upper limit, an error is reported. -- Only one Rubik can be deployed on each Kubernetes node. Multiple Rubiks may conflict with each other. +- Only one set of Rubik instances can be deployed on each Kubernetes node. Multiple sets of Rubik instances may conflict with each other. - Rubik does not provide port access and can communicate only through sockets. @@ -188,12 +188,12 @@ spec: - Services cannot be switched from a low priority (offline services) to a high priority (online services). For example, if service A is set to an offline service and then to an online service, Rubik reports an error. -- When a container is mounted to a directory, the service side must ensure that the minimum permission on the Rubik local socket directory **/run/Rubik** is 700. +- When directories are mounted to a Rubik container, the minimum permission on the Rubik local socket directory **/run/Rubik** is **700** on the service side. -- When the Rubik server is available, the timeout interval of a single request is 120s. If the Rubik process enters the T (suspended or tracing) or D (uninterruptible sleep) state, the server becomes unavailable. In this case, the Rubik service does not respond to any request. To avoid this problem, set the timeout interval on the client to avoid infinite waiting. +- When the Rubik service is available, the timeout interval of a single request is 120s. If the Rubik process enters the T (stopped or being traced) or D (uninterruptible sleep) state, the service becomes unavailable. In this case, the Rubik service does not respond to any request. To avoid this problem, set the timeout interval on the client to avoid infinite waiting. -- If hybrid deployment is used, the original **cgroup cpu share** function has the following restrictions: +- If hybrid deployment is used, the original CPU share funtion of cgroup has the following restrictions: - If both online and offline tasks are running on the CPU, the CPU share configuration of offline tasks cannot take effect. + If both online and offline tasks are running on the CPU, the CPU share configuration of offline tasks does not take effect. If the current CPU has only online or offline tasks, the CPU share configuration takes effect. diff --git a/docs/en/docs/rubik/overview.md b/docs/en/docs/rubik/overview.md index bcf79fc62..7c9aa04a5 100644 --- a/docs/en/docs/rubik/overview.md +++ b/docs/en/docs/rubik/overview.md @@ -4,7 +4,7 @@ Low server resource utilization has always been a recognized challenge in the industry. With the development of cloud native technologies, hybrid deployment of online (high-priority) and offline (low-priority) services becomes an effective means to improve resource utilization. -In hybrid service deployment scenarios, Rubik container scheduling properly schedules resources based on QoS levels to greatly improve resource utilization while ensuring the quality of online services. +In hybrid service deployment scenarios, Rubik can properly schedule resources based on Quality if Service (QoS) levels to greatly improve resource utilization while ensuring the quality of online services. Rubik supports the following features: diff --git a/docs/en/docs/secGear/installing-secGear.md b/docs/en/docs/secGear/installing-secGear.md index 187729577..a8c2d5ecd 100644 --- a/docs/en/docs/secGear/installing-secGear.md +++ b/docs/en/docs/secGear/installing-secGear.md @@ -1,29 +1,56 @@ # Installing secGear -## Environment Requirements -Currently, the secGear supports only the following software and hardware. More software and hardware will be available in the furture. +## OS -- Processor: The secGear supports only the x86_64 processor architecture, and the processor must support the Intel Software Guard Extensions (Intel SGX) function. +openEuler 21.03, openEuler 20.03 LTS SP2, or later -- Operating system: openEuler 21.03 or later +## CPU Architecture + +#### x86_64 + +The Intel Software Guard Extensions (Intel SGX) function is required. + +#### AArch64 + + - Hardware + + | Item | Version | + | ------ | --------------------------------------------- | + | Server| TaiShan 200 server (model 2280, dual sockets)| + | Mainboard | Kunpeng board | + | BMC | 1711 board (model BC82SMMAB) | + | CPU | Kunpeng 920 processor (model 7260, 5250, or 5220) | + | Chassis | No special requirements; an 8- or 12-drive chassis recommended | + + The TrustZone feature, including the iTrustee secure OS, BMC firmware, and BIOS firmware, has been installed on the server. + + - Environment Requirements + + The patch in the rich execution environment (REE) is required by a client application (CA) to communicate with a trusted application (TA) in the trusted execution environment (TEE). Before installing secGear, set up the environment as follows: + + 1. [Setting Up the TA and CA Operating Environment](https://support.huaweicloud.com/intl/en-us/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0007.html) + + 2. Applying for a TA Developer Certificate in a Debugging Environment + + a. [Creating a configs.xml File](https://support.huaweicloud.com/intl/en-us/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#section0) + + b. [Applying for a TA Developer Certificate](https://support.huaweicloud.com/intl/en-us/dpmg-tz-kunpengcctrustzone/kunpengtrustzone_04_0009.html#section1) ## Installation Guide -To use the secGear confidential computing programming framework, you need to install the secGear and secGear-devel development packages. Before the installation, ensure that the openEuler yum repository has been configured. +To use the secGear confidential computing programming framework, you need to install the secGear and secGear-devel development packages. Before the installation, ensure that the openEuler Yum source has been configured. -1. Run the following command as user root to install the secGear component: +1. Install the secGear component with **root** permissions: ```shell #yum install secGear #yum install secGear-devel - ``` + ``` -2. Check whether the secGear is successfully installed. If the following command output is displayed, the installation is successful. +2. Run the following commands to check whether the installation is successful. If the command output contains the corresponding software package, the installation is successful. - ```shell - #rpm -q secGear - secGear-1.0-1.oe1.x86_64 + k + #rpm -q secGear #rpm -q secGear-devel - secGear-devel-1.0-1.oe1.x86_64 ``` diff --git a/docs/en/docs/secGear/secGear-development-guide.md b/docs/en/docs/secGear/secGear-development-guide.md index 3068c7b13..442e4136f 100644 --- a/docs/en/docs/secGear/secGear-development-guide.md +++ b/docs/en/docs/secGear/secGear-development-guide.md @@ -412,7 +412,7 @@ Applications developed using secGear comply with the following unified directory Copy the device public key file rsa_public_key_cloud.pem to the enclave directory. The device public key is used to encrypt the dynamic library in the security zone by using the temporarily generated AES key. - Note: The rsa_public_key_cloud.pem file is downloaded from . + Note: The rsa_public_key_cloud.pem file is downloaded from . 7. Compile the program. -- Gitee From f6dfd0907462e57a309fd2adde0b50621eef56e1 Mon Sep 17 00:00:00 2001 From: luhuaxin Date: Thu, 28 Jul 2022 01:27:41 +0800 Subject: [PATCH 049/130] Add chapter for ShangMi features --- ...5\257\206\345\272\224\347\224\250\351\205\215\347\275\256.md" | 1 + 1 file changed, 1 insertion(+) create mode 100644 "docs/zh/docs/ShangMiFeature/\345\225\206\345\257\206\345\272\224\347\224\250\351\205\215\347\275\256.md" diff --git "a/docs/zh/docs/ShangMiFeature/\345\225\206\345\257\206\345\272\224\347\224\250\351\205\215\347\275\256.md" "b/docs/zh/docs/ShangMiFeature/\345\225\206\345\257\206\345\272\224\347\224\250\351\205\215\347\275\256.md" new file mode 100644 index 000000000..1333ed77b --- /dev/null +++ "b/docs/zh/docs/ShangMiFeature/\345\225\206\345\257\206\345\272\224\347\224\250\351\205\215\347\275\256.md" @@ -0,0 +1 @@ +TODO -- Gitee From 36bf70cf1cc217b62fd006415ddd9a4d7a74c542 Mon Sep 17 00:00:00 2001 From: GoldJohnKing Date: Thu, 28 Jul 2022 13:55:47 +0800 Subject: [PATCH 050/130] fix wrong tag of docker image --- docs/en/docs/Embedded/container-build-guide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/docs/Embedded/container-build-guide.md b/docs/en/docs/Embedded/container-build-guide.md index ee6e8e6af..c716bfc3a 100644 --- a/docs/en/docs/Embedded/container-build-guide.md +++ b/docs/en/docs/Embedded/container-build-guide.md @@ -53,7 +53,7 @@ sudo yum install docker Run the `docker pull` command to pull the image from Huawei Cloud to the host machine: ``` -docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest +docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:22.03-lts ``` ### Preparing the Container Build Environment @@ -65,7 +65,7 @@ docker pull swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-contai Run the docker run command to start the container. To ensure that the container can run in the background and access the Internet after being started, you are advised to run the following command to start the container: ``` -docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest bash +docker run -idt --network host swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:22.03-lts bash ``` Parameter description: @@ -74,7 +74,7 @@ Parameter description: - -d: starts a container in daemon mode in the background. - -t: allocates a pseudo-tty and binds it to the standard input of the container. - \--network: connects the container to the network of the host machine. -- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:lastest (image_name:image_version) +- swr.cn-north-4.myhuaweicloud.com/openeuler-embedded/openeuler-container:22.03-lts (image_name:image_version) - bash: method for accessing a container. #### 2. Check the ID of the started container. -- Gitee From 307b3584a3928c40a2ab2909d9f88e4e9de0a154 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Fri, 29 Jul 2022 13:52:05 +0800 Subject: [PATCH 051/130] update docs of master --- .../Administration/basic-configuration.md | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/docs/en/docs/Administration/basic-configuration.md b/docs/en/docs/Administration/basic-configuration.md index 5b1b5782e..2429a349a 100644 --- a/docs/en/docs/Administration/basic-configuration.md +++ b/docs/en/docs/Administration/basic-configuration.md @@ -35,7 +35,7 @@ ## Setting the System Locale -System locale settings are stored in the /etc/locale.conf file and can be modified by the localectl command. These settings are read at system boot by the systemd daemon. +System locale settings are stored in the **/etc/locale.conf** file and can be modified by the **localectl** command. These settings are read at system boot by the systemd daemon. ### Displaying the Current Locale Status @@ -71,13 +71,13 @@ zh_CN.UTF-8 ### Setting the Locale -To set the language environment, run the following command as the user **root**. In the command, _locale_ indicates the language type to be set. Run the **localectl list-locales** command to obtain the value range. Change the value based on the site requirements. +To set the language environment, run the following command as the **root** user. In the command, _locale_ indicates the language type to be set. Run the **localectl list-locales** command to obtain the value range. Change the value as required. ``` # localectl set-locale LANG=locale ``` -For example, if you want to use Simplified Chinese as the locale, run the following command as the user **root**: +For example, if you want to use Simplified Chinese as the locale, run the following command as the **root** user: ``` # localectl set-locale LANG=zh_CN.UTF-8 @@ -85,11 +85,11 @@ For example, if you want to use Simplified Chinese as the locale, run the follow > ![](./public_sys-resources/icon-note.gif) **NOTE:** -> After the modification, log in again or run the command `source /etc/locale.conf` as the user **root** to update the configuration file for the modification to take effect: +> After the modification, log in again or run the **source /etc/locale.conf** command as user **root** to update the configuration file for the modification to take effect: ## Setting the Keyboard Layout -Keyboard layout settings are stored in the /etc/locale.conf file and can be modified by the localectl command. These settings are read at early boot by the systemd daemon. +Keyboard layout settings are stored in the **/etc/locale.conf** file and can be modified by the **localectl** command. These settings are read at early boot by the systemd daemon. ### Displaying the Current Settings @@ -125,7 +125,7 @@ cn ### Setting the Keyboard Layout -To set the keyboard layout, run the following command as the user **root**. In the command, _map_ indicates the keyboard layout to be set. Run the **localectl list-keymaps** command to obtain the value range. Change it based on the site requirements. +To set the keyboard layout, run the following command as the **root** user. In the command, _map_ indicates the keyboard layout to be set. Run the **localectl list-keymaps** command to obtain the value range. Change it as required. ``` $ localectl set-keymap map @@ -144,7 +144,7 @@ $ localectl status ## Setting the Date and Time -This topic describes how to set the system date, time, and time zone by using timedatectl, date, and hwclock commands. +This topic describes how to set the system date, time, and time zone by using the **timedatectl**, **date**, and **hwclock** commands. ### Using the timedatectl Command @@ -171,7 +171,7 @@ System clock synchronized: no #### Synchronizing the System Clock with a Remote Server -Your system clock can be automatically synchronized with a remote server using the Network Time Protocol (NTP). Run the following command as the user **root** to enable or disable NTP. The value of _boolean_ is **yes** or **no**, indicating that the NTP is enabled or disabled for automatic system clock synchronization. Change the value based on the site requirements. +Your system clock can be automatically synchronized with a remote server using the Network Time Protocol (NTP). Run the following command as the **root** user to enable or disable NTP. The value of _boolean_ is **yes** or **no**, indicating that the NTP is enabled or disabled for automatic system clock synchronization. Change the value as required. > ![](./public_sys-resources/icon-note.gif) **NOTE:** If the remote NTP server is enabled to automatically synchronize the system clock, you cannot manually change the date and time. If you need to manually change the date or time, ensure that automatic NTP system clock synchronization is disabled. You can run the **timedatectl set-ntp no** command to disable the NTP service. @@ -191,13 +191,13 @@ For example, to enable automatic remote time synchronization, run the following > ![](./public_sys-resources/icon-note.gif) **NOTE:** Before changing the date, ensure that automatic NTP system clock synchronization has been disabled. -Run the following command as the user **root** to change the current date. In the command, _YYYY_ indicates the year, _MM_ indicates the month, and _DD_ indicates the day. Change them based on the site requirements. +Run the following command as the **root** user to change the current date. In the command, _YYYY_ indicates the year, _MM_ indicates the month, and _DD_ indicates the day. Change them as required. ``` # timedatectl set-time YYYY-MM-DD ``` -For example, to change the current date to August 14, 2019, run the following command as the user **root**: +For example, to change the current date to August 14, 2019, run the following command as the **root** user: ``` # timedatectl set-time '2019-08-14' @@ -208,7 +208,7 @@ For example, to change the current date to August 14, 2019, run the following co > ![](./public_sys-resources/icon-note.gif) **NOTE:** Before changing the time, ensure that automatic NTP system clock synchronization has been disabled. -To change the current time, run the following command as the user **root**. In the command, _HH_ indicates the hour, _MM_ indicates the minute, and _SS_ indicates the second. Change them based on the site requirements. +To change the current time, run the following command as the **root** user. In the command, _HH_ indicates the hour, _MM_ indicates the minute, and _SS_ indicates the second. Change them as required. ``` # timedatectl set-time HH:MM:SS @@ -228,7 +228,7 @@ To list all available time zones, run the following command: $ timedatectl list-timezones ``` -To change the current time zone, run the following command as the user **root**. In the command, _time\_zone_ indicates the time zone to be set. Change it based on the site requirements. +To change the current time zone, run the following command as the **root** user. In the command, _time\_zone_ indicates the time zone to be set. Change it as required. ``` # timedatectl set-timezone time_zone @@ -277,13 +277,13 @@ To display the current date and time, run the following command: $ date ``` -By default, the **date** command displays the local time. To display the time in Coordinated Universal Time (UTC), run the command with the --utc or -u command line option: +By default, the **date** command displays the local time. To display the time in Coordinated Universal Time (UTC), run the command with the **--utc** or **-u** command line option: ``` $ date --utc ``` -You can also customize the format of the displayed information by providing the + "format" option on the command line: +You can also customize the format of the displayed information by providing the **+"format"** option on the command line: ``` $ date +"format" @@ -371,19 +371,19 @@ Example commands and outputs: #### Changing the Current Time -To change the current time, run the date command with the --set or -s option as the root user: Run the following command as the user **root**. In the command, _HH_ indicates the hour, _MM_ indicates the minute, and _SS_ indicates the second. Change them based on the site requirements. +To change the current time, run the **date** command with the **--set** or **-s** option as the **root** user. In the command, _HH_ indicates the hour, _MM_ indicates the minute, and _SS_ indicates the second. Change them as required. ``` # date --set HH:MM:SS ``` -By default, the date command sets the local time. To set the system clock in UTC instead, run the command with the --utc or -u command line option: +By default, the **date** command sets the local time. To set the system clock in UTC instead, run the command with the **--utc** or **-u** command line option: ``` # date --set HH:MM:SS --utc ``` -For example, to change the current time to 23:26:00, run the following command as the user **root**: +For example, to change the current time to 23:26:00, run the following command as the **root** user: ``` # date --set 23:26:00 @@ -391,13 +391,13 @@ For example, to change the current time to 23:26:00, run the following command a #### Changing the Current Date -To change the current date, run the command with the --set or -s command line option. Run the following command as the user **root**. In the command, _YYYY_ indicates the year, _MM_ indicates the month, and _DD_ indicates the day. Change them based on the site requirements. +To change the current date, run the command with the **--set** or **-s** command line option as the **root** user. In the command, _YYYY_ indicates the year, _MM_ indicates the month, and _DD_ indicates the day. Change them as required. ``` # date --set YYYY-MM-DD ``` -For example, to change the current date to November 2, 2019, run the following command as the user **root**: +For example, to change the current date to November 2, 2019, run the following command as the **root** user: ``` # date --set 2019-11-02 @@ -405,7 +405,7 @@ For example, to change the current date to November 2, 2019, run the following c ### Using the hwclock Command -You can run the hwclock command to set the real time clock (RTC). +You can run the **hwclock** command to set the real time clock (RTC). #### Real-Time Clock and System Clock @@ -418,7 +418,7 @@ When Linux starts, it reads the RTC and sets the system clock time based on the #### Displaying the Current Date and Time -To display the current RTC date and time, run the following command as the user **root**: +To display the current RTC date and time, run the following command as the **root** user: ``` # hwclock @@ -433,7 +433,7 @@ Example command output: #### Setting the Date and Time -Run the following command as the user **root** to change the date and time of the current hardware. In the command, _dd_ indicates the day, _mm_ indicates the month, _yyyy_ indicates the year, _HH_ indicates the hour, and _MM_ indicates the minute. Change them based on the site requirements. +Run the following command as the **root** user to change the date and time of the current hardware. In the command, _dd_ indicates the day, _mm_ indicates the month, _yyyy_ indicates the year, _HH_ indicates the hour, and _MM_ indicates the minute. Change them as required. ``` # hwclock --set --date "dd mm yyyy HH:MM" @@ -475,6 +475,6 @@ The memory reserved for kdump must be added to the bootargs in the **/boot/efi/E ### Disabling Network Drivers -In the kdump configuration file **/etc/kdump.conf**, the dracut parameters can be used to set the tailored driver module. You can configure the network driver to the tailored driver list to prevent the kdump file system from loading the driver. After the configuration file is modified, restart the kdump service for the modification to take effect. Set the dracut parameters as follows: +In the kdump configuration file **/etc/kdump.conf**, the **dracut** parameters can be used to set the tailored driver module. You can configure the network driver to the tailored driver list to prevent the kdump file system from loading the driver. After the configuration file is modified, restart the kdump service for the modification to take effect. Set the **dracut** parameters as follows: `dracut_args --omit-drivers "mdio-gpi usb_8dev et1011c rt2x00usb bcm-phy-lib mac80211_hwsim rtl8723be rndis_host hns3_cae amd vrf rtl8192cu mt76x02-lib int51x1 ppp_deflate team_mode_loadbalance smsc911x aweth bonding mwifiex_usb hnae dnet rt2x00pci vaser_pci hdlc_ppp marvell rtl8xxxu mlxsw_i2c ath9k_htc rtl8150 smc91x cortina at803x rockchip cxgb4 spi_ks8995 mt76x2u smsc9420 mdio-cavium bnxt_en ch9200 dummy macsec ice mt7601u rtl8188ee ixgbevf net1080 liquidio_vf be2net mlxsw_switchx2 gl620a xilinx_gmii2rgmii ppp_generic rtl8192de sja1000_platform ath10k_core cc770_platform realte igb c_can_platform c_can ethoc dm9601 smsc95xx lg-vl600 ifb enic ath9 mdio-octeon ppp_mppe ath10k_pci cc770 team_mode_activebackup marvell10g hinic rt2x00lib mlx4_en iavf broadcom igc c_can_pci alx rtl8192se rtl8723ae microchip lan78xx atl1c rtl8192c-common almia ax88179_178a qed netxen_nic brcmsmac rt2800usb e1000 qla3xxx mdio-bitbang qsemi mdio-mscc-miim plx_pci ipvlan r8152 cx82310_eth slhc mt76x02-usb ems_pci xen-netfront usbnet pppoe mlxsw_minimal mlxsw_spectrum cdc_ncm rt2800lib rtl_usb hnae3 ath9k_common ath9k_hw catc mt76 hns_enet_drv ppp_async huawei_cdc_ncm i40e rtl8192ce dl2 qmi_wwan mii peak_usb plusb can-dev slcan amd-xgbe team_mode_roundrobin ste10Xp thunder_xcv pptp thunder_bgx ixgbe davicom icplus tap tun smsc75xx smsc dlci hns_dsaf mlxsw_core rt2800mmi softing uPD60620 vaser_usb dp83867 brcmfmac mwifiex_pcie mlx4_core micrel team macvlan bnx2 virtio_net rtl_pci zaurus hns_mdi libcxgb hv_netvsc nicvf mt76x0u teranetics mlxfw cdc_eem qcom-emac pppox mt76-usb sierra_net i40evf bcm87xx mwifiex pegasus rt2x00mmi sja1000 ena hclgevf cnic cxgb4vf ppp_synctty iwlmvm team_mode_broadcast vxlan vsockmon hdlc_cisc rtl8723-common bsd_comp fakelb dp83822 dp83tc811 cicada fm10 8139t sfc hs geneve hclge xgene-enet-v2 cdc_mbim hdlc asix netdevsim rt2800pci team_mode_random lxt ems_usb mlxsw_pci sr9700 mdio-thunder mlxsw_switchib macvtap atlantic cdc_ether mcs7830 nicpf mdi peak_pci atl1e cdc_subset ipvtap btcoexist mt76x0-common veth slip iwldvm bcm7xxx vitesse netconsole epic100 myri10ge r8169 qede microchip_t1 liquidi bnx2x brcmutil mwifiex_sdi mlx5_core rtlwifi vmxnet3 nlmon hns3 hdlc_raw esd_usb2 atl2 mt76x2-common iwlwifi mdio-bcm-unimac national ath rtwpci rtw88 nfp rtl8821ae fjes thunderbolt-net 8139cp atl1 mscc vcan dp83848 dp83640 hdlc_fr e1000e ipheth net_failover aquantia rtl8192ee igbvf rocker intel-xway tg3" --omit "ramdisk network ifcfg qemu-net" --install "chmod" --nofscks` \ No newline at end of file -- Gitee From 15481d8ad5ae79ebe63f5d1e4361928b2682b4cc Mon Sep 17 00:00:00 2001 From: Rock Date: Fri, 29 Jul 2022 08:37:13 +0000 Subject: [PATCH 052/130] update docs/en/docs/SecHarden/system-services.md. --- docs/en/docs/SecHarden/system-services.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/docs/SecHarden/system-services.md b/docs/en/docs/SecHarden/system-services.md index 8f90f6925..bcccd6573 100644 --- a/docs/en/docs/SecHarden/system-services.md +++ b/docs/en/docs/SecHarden/system-services.md @@ -279,7 +279,7 @@ To harden a client, perform the following steps:

- -- Gitee From 00df1ea711c30c4f96c42b6e4525ed789f0451ab Mon Sep 17 00:00:00 2001 From: Rock Date: Fri, 29 Jul 2022 09:11:40 +0000 Subject: [PATCH 053/130] =?UTF-8?q?update=20docs/zh/docs/SecHarden/?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=9C=8D=E5=8A=A1.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\347\263\273\347\273\237\346\234\215\345\212\241.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/SecHarden/\347\263\273\347\273\237\346\234\215\345\212\241.md" "b/docs/zh/docs/SecHarden/\347\263\273\347\273\237\346\234\215\345\212\241.md" index 13049d470..2689e678f 100644 --- "a/docs/zh/docs/SecHarden/\347\263\273\347\273\237\346\234\215\345\212\241.md" +++ "b/docs/zh/docs/SecHarden/\347\263\273\347\273\237\346\234\215\345\212\241.md" @@ -278,7 +278,7 @@ SSH(Secure Shell)是目前较可靠,专为远程登录会话和其他网 - -- Gitee From d847ad4beedf3881a5b2885a14d4607650df3cc0 Mon Sep 17 00:00:00 2001 From: Fisher Date: Sat, 30 Jul 2022 16:39:13 +0800 Subject: [PATCH 054/130] Fix issue I57T4V --- ...\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" "b/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" index 7f47246ec..f3aac6447 100644 --- "a/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" +++ "b/docs/zh/docs/Virtualization/\347\256\241\347\220\206\350\231\232\346\213\237\346\234\272.md" @@ -29,7 +29,7 @@ - 未定义(undefined):虚拟机未定义或未创建,即libvirt认为该虚拟机不存在。 - 关闭状态(shut off):虚拟机已经被定义但未运行,或者虚拟机被终止。 -- 运行中(running):虚拟机处于运行状态。 +- 运行(running):虚拟机处于运行状态。 - 暂停(paused):虚拟机运行被挂起,其运行状态被临时保存在内存中,可以恢复到运行状态。 - 保存(saved):与暂停(paused)状态类似,其运行状态被保存在持久性存储介质中,可以恢复到运行状态。 - 崩溃(crashed):通常是由于内部错误导致虚拟机崩溃,不可恢复到运行状态。 -- Gitee From d902f89783b2a77537c63f985f04353e9f9a36aa Mon Sep 17 00:00:00 2001 From: Fisher Date: Sat, 30 Jul 2022 16:54:26 +0800 Subject: [PATCH 055/130] Fix issue I57QBM --- ...31\232\346\213\237\346\234\272\351\205\215\347\275\256.md" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index 9c858c51b..0337ebbe5 100644 --- "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -192,8 +192,8 @@ XML配置文件使用disk元素配置存储设备,disk常见的属性如[表1] - - - - @@ -1172,21 +1172,21 @@ The configuration differences in /etc/sysconfig/network are as follows: - - - @@ -1216,14 +1216,14 @@ The differences in /etc/sysconfig/network-scripts/ifcfg- are as - - @@ -1249,21 +1249,21 @@ The differences in /etc/sysconfig/network-scripts/ifcfg- are as - - - @@ -1273,11 +1273,11 @@ The differences in /etc/sysconfig/network-scripts/ifcfg- are as

Vendor

-shared

默认选项,可省略。

-
  • 可以生成动态库文件。
  • 进行动态编译,优先链接动态库,只有没有动态库是才会链接同名的静态库。
+
  • 可以生成动态库文件。
  • 进行动态编译,优先链接动态库,只有没有动态库时才会链接同名的静态库。

-

虚拟网卡状态

virsh domifstat <VMInstance>

+

virsh domifstat <VMInstance> <interface>

查询网卡名称可以使用virsh domiflist命令。

SSH key exchange algorithms.

curve25519-sha256,curve25519-sha256@@libssh.org,diffie-hellman-group-exchange-sha256

+

curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

Yes

设置SSH密钥交换算法

curve25519-sha256,curve25519-sha256@@libssh.org,diffie-hellman-group-exchange-sha256

+

curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256

  

block:块设备

file:文件设备

-

dir: 目录路径

-

network:网络磁盘

+

dir:目录路径

+

network:网络磁盘

device

-- Gitee From cd11c9e5ef6ed2c8be84307def1cf8d6d749a255 Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:16:19 +0800 Subject: [PATCH 056/130] Fix issue I57OGB --- ...31\232\346\213\237\345\214\226\347\273\204\344\273\266.md" | 4 ++-- docs/zh/menu/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename "docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" => "docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226\347\273\204\344\273\266.md" (98%) diff --git "a/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" "b/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226\347\273\204\344\273\266.md" similarity index 98% rename from "docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" rename to "docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226\347\273\204\344\273\266.md" index 09e042fc2..038ad6a42 100644 --- "a/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" +++ "b/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226\347\273\204\344\273\266.md" @@ -1,9 +1,9 @@ -# 安装虚拟化 +# 安装虚拟化组件 本章介绍在openEuler中安装虚拟化组件的方法。 -- [安装虚拟化](#安装虚拟化) +- [安装虚拟化组件](#安装虚拟化组件) - [最低硬件要求](#最低硬件要求) - [安装虚拟化核心组件](#安装虚拟化核心组件) - [安装方法](#安装方法) diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 0ba65f344..45371146f 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -58,7 +58,7 @@ headless: true - [附录]({{< relref "./docs/SecHarden/附录.md" >}}) - [虚拟化用户指南]({{< relref "./docs/Virtualization/virtualization.md" >}}) - [认识虚拟化]({{< relref "./docs/Virtualization/认识虚拟化.md" >}}) - - [安装虚拟化]({{< relref "./docs/Virtualization/安装虚拟化.md" >}}) + - [安装虚拟化组件]({{< relref "./docs/Virtualization/安装虚拟化组件.md" >}}) - [准备使用环境]({{< relref "./docs/Virtualization/准备使用环境.md" >}}) - [虚拟机配置]({{< relref "./docs/Virtualization/虚拟机配置.md" >}}) - [管理虚拟机]({{< relref "./docs/Virtualization/管理虚拟机.md" >}}) -- Gitee From 6a359c661d17c970a654c364b5652d4343bd056d Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:20:40 +0800 Subject: [PATCH 057/130] Fix issue I57OF2 --- ...\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" index 988bf7f8a..3011fa510 100644 --- "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" +++ "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" @@ -71,7 +71,7 @@ openEuler软件包中提供的虚拟化相关组件: - 更高的可用性和更好的运维手段 - 虚拟化提供热迁移,快照,热升级,容灾自动恢复等运维手段,可以在不影响用户的情况下对物理资源进行删除、升级或变更,提高了业务连续性,同时可以实现自动化运维。 + 虚拟化提供热迁移、快照、热升级、容灾自动恢复等运维手段,可以在不影响用户的情况下对物理资源进行删除、升级或变更,提高了业务连续性,同时可以实现自动化运维。 - 提高安全性 -- Gitee From 573377838180adcb943d49a5651f33ac8d8cbd6e Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:24:56 +0800 Subject: [PATCH 058/130] Fix issue I57O9T --- ...\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" index 988bf7f8a..d8cd580b9 100644 --- "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" +++ "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" @@ -22,7 +22,7 @@ 这种模型中,物理资源是由宿主机操作系统管理,宿主机操作系统是传统的操作系统,如Linux,Windows等,宿主机操作系统不提供虚拟化能力,提供虚拟化能力的VMM作为系统的一个驱动或者软件运行在宿主操作系统上,VMM通过调用host OS的服务获得资源,实现处理器,内存和I/O设备的模拟,这种模型的虚拟化实现有KVM、Virtual Box等。 -KVM(Kernel-based Virtual Machine)即基于内核的虚拟机,是Linux的一个内核模块,该内核模块使Linux成为一个hypervisor。KVM架构如[图2](#fig310953013541)所示。KVM本身未模拟任何硬件设备,它用于使能硬件提供的虚拟化能力,比如Intel VT-x, AMD-V, ARM virtualization extensions等。主板、内存及I/O等设备的模拟由用户态的QEMU完成。用户态QEMU配合内核KVM模块共同完成虚拟机的硬件模拟,客户操作系统运行在QEMU和KVM模拟的硬件上。 +KVM(Kernel-based Virtual Machine)即基于内核的虚拟机,是Linux的一个内核模块,该内核模块使Linux成为一个hypervisor。KVM架构如[图2](#fig310953013541)所示。KVM本身未模拟任何硬件设备,它用于使能硬件提供的虚拟化能力,比如Intel VT-x, AMD-V, ARM virtualization extensions等。主板、内存及I/O等设备的模拟由用户态的QEMU完成。用户态QEMU配合内核KVM模块共同完成虚拟机的硬件模拟,客户机操作系统运行在QEMU和KVM模拟的硬件上。 **图 2** KVM架构图 ![](./figures/kvm-architecture.png) -- Gitee From ec4ab200af46885ebd382f270d8ed026c18ce09e Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:40:15 +0800 Subject: [PATCH 059/130] Fix issue I57R00 --- ...\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index 9c858c51b..1bd49a6b3 100644 --- "a/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/Virtualization/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -601,7 +601,7 @@ controller:控制器元素,表示一个总线。 - video:媒体设备 - 属性type:媒体设备类型。AArch架构常用属性值为virtio,x86\_64架构通常使用属性值为vga或cirrus。 + 属性type:媒体设备类型。AArch64架构常用属性值为virtio,x86\_64架构通常使用属性值为vga或cirrus。 子元素model:video的子元素,用于指定媒体设备类型。 -- Gitee From eb863cc89609991a4279feefe70bed34bba8d598 Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 19:35:31 +0800 Subject: [PATCH 060/130] Fix issue I57Q92 --- .../figures/virtual-network-structure.png | Bin 15231 -> 14046 bytes .../figures/virtual-network-structure.png | Bin 20681 -> 15979 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/Virtualization/figures/virtual-network-structure.png b/docs/en/docs/Virtualization/figures/virtual-network-structure.png index 8a884a9212f8e35f545cfa01dc7320d145844390..4d57a184352c1a3558eeac56499888b2b98b31f1 100644 GIT binary patch literal 14046 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 VwVmzJ0A_=n4;*tO?+d*8zX12txflQd literal 15231 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 z zc=Vm(s8N*LE(mr%*U==brx#y;E5gI76&fUMgnzVJH+MAyv-6p9(<4Nc6jTCE!2E-&m_xTx5Uq5O(V(`QI#Nv-(F z+FSmQwaF!`BN)V`#5p+CoxNYXOg}xRBPgApZ`5>1!IzvLKrrVYBaQp5D1&+bQ9*2L ze^eGX-szXmn;`|mHaUrPb!SI+qI>OdR5`bGm+o2(uRZ~r&b_Pfmii4^>n6n4sca+F z+0hT{2=@ zAoHqLS*D(t&CPvx(OKAA{hdi7XLyYJ!Tcw0oA|usD;0}n!=ppQWZrWzKP95H$HlST zc{&$jId#0d@~o1m30EHVD7jXfkfB$OX!qY-yIMMEKCiXsZ@U=WpyCRjK@ix(WB#&x zlQ4OOhMJ%T$+*kdI{^Nsx@e$a$q{av&Y+I?+f%*aCKS}Km_}uE4&U5s36}Y6MO(R8R>bst9A6Z_cwP0*GN^7 z{qU-z=wL^s4ChkcyWV3L$wjpVm;vc!YDSxEbe?n08V_IXm+95CVAZnd9pg7Wcl(e< z4V}X_2nSmLcq(xV{e+e1UBsPSK|s8E=BT5Yjm#l`(dlunz?)5?LI z!fjn?%;#bjRh~eo`aVjq)Vn#_zw1@c`RwYIj8mMtSMf1swS$hfLrePJ{x*hqyy23l z&a|GoYyRHA1xi9s;kBFgL_b5p%cEoFuG7e%2E>Hd-HgN5Jkr{L z#Hkaz?)3I=ZVO7#KK-cMYdTZP9F=OczarjhtVsF#!fvi-r*7pi-0ZQ#b~keC2(UH3RY)H zH~+5<1_Uf}qCw;!({i_2XYW<>Fs59KML?I<#al|mSJYqRpm@vjR08ZpqjwniT0V{P zyb1hc_5Bx%#n^@~Fmh4yzIUz8yl8b&z!vdNL~rGvE{ejEtCC?_4B*bkVB|jM!Tg7I zeC*&Lq((^Bo+8V#Eq;s0EL>6lr?XD>Dv4v`JVf*dP%&xgJ&GGFbpby(K2huNfmi6C zUIu#O&_W5tqAx~$0ssLLNA`X5ZxBDJ9^JKiIQP)mh(t3Wpr{LUpeJ2`QpNQ8^xfy| z;qy7oz0i5HA$=%|s;Ngv;wF4~+xfOY(on5SnvnXeDov{kE-P+J`dBM;y9?^9`KzIeb_Oma2CA}TQEBFw)jid+9Ff7?+H32jJ%^)@>CcBSy^f=%0A-AY%8A-=%ZT2!!^s+pmkqL*D+;55 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 -- Gitee From 61060fdfe2477653cef3d4b80b5332efb0f3cded Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 19:45:20 +0800 Subject: [PATCH 061/130] Fix issue I57T5G --- .../figures/status-transition-diagram.png | Bin 86518 -> 16195 bytes .../figures/status-transition-diagram.png | Bin 22222 -> 17327 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/en/docs/Virtualization/figures/status-transition-diagram.png b/docs/en/docs/Virtualization/figures/status-transition-diagram.png index acbf4df149f57f43fbbcbb746980bd4748fb71d9..f0e9bb814b155e4abde372c93677a97f207b5475 100644 GIT binary patch literal 16195 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 literal 86518 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 literal 22222 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 E5A<&ZDF6Tf -- Gitee From dd21425ebe15b10c8cd7ef7404b51c379d882685 Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 20:17:11 +0800 Subject: [PATCH 062/130] Fix issue I4ZQ5K --- docs/en/docs/Virtualization/virtualization-installation.md | 5 +++++ ...6\211\350\243\205\350\231\232\346\213\237\345\214\226.md" | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docs/en/docs/Virtualization/virtualization-installation.md b/docs/en/docs/Virtualization/virtualization-installation.md index fb4374b6d..88e10ed85 100644 --- a/docs/en/docs/Virtualization/virtualization-installation.md +++ b/docs/en/docs/Virtualization/virtualization-installation.md @@ -36,6 +36,11 @@ The minimum hardware requirements for installing virtualization components on op # yum install -y qemu ``` + >![](./public_sys-resources/icon-caution.gif) ** Notice: ** + >The QEMU component runs as the user qemu and user group qemu by default. If you do not understand the rights management of Linux user and users groups, you may encounter insufficient rights when creating and starting virtual machines. There are two solutions: + >Solution 1: Modify the QEMU configuration file. Open the QEMU configuration file with the following command, `sudo vim /etc/libvirt/qemu.conf`, find the following two fields, `user = "root"` and `group = "root"`, uncomment (ie delete the preceding `#`), save and exit. + >Solution 2: Modify the owner of the virtual machine file. First, you need to ensure that the user qemu has access to the folder where the virtual machine files are stored. Use the following command to modify the owner of the file, `sudo chown qemu:qemu xxx.qcow2`, and modify all virtual machine files that need to be read and written. + 2. Install the libvirt component. ``` diff --git "a/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" "b/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" index 09e042fc2..1c6015ac3 100644 --- "a/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" +++ "b/docs/zh/docs/Virtualization/\345\256\211\350\243\205\350\231\232\346\213\237\345\214\226.md" @@ -40,6 +40,11 @@ # yum install -y qemu ``` + >![](./public_sys-resources/icon-caution.gif) **注意:** + >QEMU组件默认以用户qemu和用户组qemu运行,如果您不了解Linux用户组、用户的权限管理,后续创建和启动虚拟机时可能会遇到权限不足问题,以下有两种解决方法: + >第一种方法:修改QEMU配置文件。使用以下命令打开QEMU配置文件,`sudo vim /etc/libvirt/qemu.conf`,找到以下两个字段,`user = "root"`和`group = "root"`,取消注释(即删除前面的`#`号),保存并退出。 + >第二种方法:修改虚拟机文件的所有者。首先需要保证用户qemu拥有访问存放虚拟机文件的文件夹权限,使用以下命令修改文件的所有者,`sudo chown qemu:qemu xxx.qcow2`,修改所有需要读写的虚拟机文件即可。 + 2. 安装libvirt组件。 ``` -- Gitee From 56639bbc638aca3328479e3875782836aac0dd72 Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:31:43 +0800 Subject: [PATCH 063/130] Fix issue I57O6U --- ...\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" index 988bf7f8a..d1363db02 100644 --- "a/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" +++ "b/docs/zh/docs/Virtualization/\350\256\244\350\257\206\350\231\232\346\213\237\345\214\226.md" @@ -4,7 +4,7 @@ 在计算机技术中,虚拟化是一种资源管理技术,它将计算机的各种实体资源(处理器、内存、磁盘、网络适配器等)予以抽象,转换后呈现并可供分割、组合为一个或多个计算机配置环境。这种资源管理技术打破了实体结构不可分割的障碍,使这些资源在虚拟化后不受现有资源的架设方式、地域或物理配置限制,从而让用户可以更好地应用计算机硬件资源,提高资源利用率。 -虚拟化使得一台物理服务器上可以运行多台虚拟机,虚拟机共享物理机的处理器、内存、I/O资源等,但逻辑上虚拟机之间是互相隔离的。在虚拟化技术中,通常将这个物理服务器称为宿主机,宿主机上运行的虚拟机也叫客户机,虚拟机内部运行的操作系统称为客户机操作系统。在宿主机和虚拟机之间存在一层叫虚拟化层的软件,用于实现虚拟硬件的模拟,通常这个虚拟化层被称为虚拟机监视器,如下图所示: +虚拟化使得一台物理服务器上可以运行多台虚拟机,虚拟机共享物理机的处理器、内存、I/O设备等资源,但逻辑上虚拟机之间是互相隔离的。在虚拟化技术中,通常将这个物理服务器称为宿主机,宿主机上运行的虚拟机也叫客户机,虚拟机内部运行的操作系统称为客户机操作系统。在宿主机和虚拟机之间存在一层叫虚拟化层的软件,用于实现虚拟硬件的模拟,通常这个虚拟化层被称为虚拟机监视器,如下图所示: **图 1** 虚拟化架构 ![](./figures/virtualized-architecture.png) -- Gitee From 4d3c85e4d545619fba6c2c3c6ead9806902e40f5 Mon Sep 17 00:00:00 2001 From: wengyu1 Date: Sat, 30 Jul 2022 17:36:37 +0800 Subject: [PATCH 064/130] Fix issue I57OKM --- ...\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Virtualization/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" "b/docs/zh/docs/Virtualization/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" index 9baf47f4a..d16a496c4 100644 --- "a/docs/zh/docs/Virtualization/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" +++ "b/docs/zh/docs/Virtualization/\345\207\206\345\244\207\344\275\277\347\224\250\347\216\257\345\242\203.md" @@ -12,7 +12,7 @@ ### 概述 -虚拟机镜像是一个文件,包含了已经完成安装并且可启动操作系统的虚拟磁盘。虚拟机镜像具有不同格式,常见的有raw格式和qcow2格式。qcow2格式镜像相比raw格式,具有占用更小的空间,支持快照、Copy-On-Write、AES加密、zlib压缩等特性,但性能略逊于raw格式镜像。镜像文件的制作借助于qemu-img工具,本节以qcow2格式镜像文件为例,介绍虚拟机镜像制作过程。 +虚拟机镜像是一个文件,包含了已经完成安装并且可启动操作系统的虚拟磁盘。虚拟机镜像具有不同格式,常见的有raw格式和qcow2格式。与raw格式镜像相比,qcow2格式镜像占用更小的空间,支持快照、Copy-On-Write、AES加密、zlib压缩等特性,但性能略逊于raw格式镜像。镜像文件的制作借助于qemu-img工具,本节以qcow2格式镜像文件为例,介绍虚拟机镜像制作过程。 ### 制作镜像 -- Gitee From bfba679c6dd5e2cc0f0c0b02022c851bfbb2ffea Mon Sep 17 00:00:00 2001 From: "Xinle.Guo" Date: Mon, 1 Aug 2022 10:02:09 +0800 Subject: [PATCH 065/130] =?UTF-8?q?StratoVirt:=20=E5=88=A0=E9=99=A4stratov?= =?UTF-8?q?irt=E6=96=87=E6=A1=A3=E9=94=99=E8=AF=AF=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E6=A0=87=E7=82=B9=E7=AC=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xinle.Guo --- ...\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index 435fb0f09..fd98b1fd1 100644 --- "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -76,7 +76,7 @@ StratoVirt 能够运行的最小配置为: | -append | console=ttyS0 root=/dev/vda reboot=k panic=1 rw | 配置内核命令行参数,标准虚拟化AArch64平台使用console=ttyAMA0,而不是ttyS0. | | -initrd | /path/to/initrd.img | 配置initrd文件 | | -smp | [cpus=]个数 | 配置cpu个数,范围[1, 254] | -| -m | 内存大小MiB)、内存大小GiB,默认单位M。 | 配置内存大小,范围[256MiB, 512GiB] | +| -m | 内存大小MiB、内存大小GiB,默认单位MiB | 配置内存大小,范围[256MiB, 512GiB] | | -qmp | unix:/path/to/socket,server,nowait | 配置api-channel,运行前须保证socket文件不存在 | | -D | /path/to/logfile | 配置日志文件 | | -pidfile | /path/to/pidfile | 配置pid文件,必须和-daemonize一起使用。运行前须保证pid文件不存在 | -- Gitee From 7e923033c5fbf6c10a80bf2b5ac9c21952db9c0d Mon Sep 17 00:00:00 2001 From: uran0sH Date: Mon, 1 Aug 2022 10:17:12 +0800 Subject: [PATCH 066/130] stratovirt: update stratovirt introduction Signed-off-by: uran0sH --- docs/en/docs/StratoVirt/StratoVirt_introduction.md | 4 ++-- .../zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/StratoVirt/StratoVirt_introduction.md b/docs/en/docs/StratoVirt/StratoVirt_introduction.md index 48ed4979b..3fd1bd928 100644 --- a/docs/en/docs/StratoVirt/StratoVirt_introduction.md +++ b/docs/en/docs/StratoVirt/StratoVirt_introduction.md @@ -46,6 +46,6 @@ Figure 1 shows the overall architecture. ## Restrictions -- Only the Linux operating system is supported; The recommended kernel version is 4.19; -- Only Linux is supported as the operating system of the VM, and the recommended kernel version is 4.19; +- Only the Linux operating system is supported; The recommended kernel version is 4.19, 5.10; +- Only Linux is supported as the operating system of the VM, and the recommended kernel version is 4.19, 5.10; - Supports a maximum of 254 CPUs; diff --git "a/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" "b/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" index 26f48c670..9842e25a6 100644 --- "a/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" +++ "b/docs/zh/docs/StratoVirt/StratoVirt\344\273\213\347\273\215.md" @@ -46,6 +46,6 @@ StratoVirt核心架构自顶向下分为三层: #### 约束 -- 仅支持Linux操作系统,推荐内核版本为4.19; -- 虚拟机操作系统仅支持Linux,内核版本建议为4.19; +- 仅支持Linux操作系统,推荐内核版本为4.19, 5.10; +- 虚拟机操作系统仅支持Linux,内核版本建议为4.19, 5.10; - 最大支持254个CPU; -- Gitee From ffa9a3c196044b31d71b5a44d925434ef463c480 Mon Sep 17 00:00:00 2001 From: "Xinle.Guo" Date: Mon, 1 Aug 2022 09:50:34 +0800 Subject: [PATCH 067/130] =?UTF-8?q?stratovirt:=20=E4=B8=BAVFIO=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=96=87=E6=A1=A3=E5=A2=9E=E5=8A=A0=E6=89=93=E5=BC=80?= =?UTF-8?q?IOMMU=E5=8A=9F=E8=83=BD=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Xinle.Guo --- docs/en/docs/StratoVirt/StratoVirt_VFIO_instructions.md | 9 +++++++++ ... \344\275\277\347\224\250\350\257\264\346\230\216.md" | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/docs/en/docs/StratoVirt/StratoVirt_VFIO_instructions.md b/docs/en/docs/StratoVirt/StratoVirt_VFIO_instructions.md index 93c974394..a47145edf 100644 --- a/docs/en/docs/StratoVirt/StratoVirt_VFIO_instructions.md +++ b/docs/en/docs/StratoVirt/StratoVirt_VFIO_instructions.md @@ -36,6 +36,15 @@ To use device passthrough, a host must meet the following requirements: iommu: Default domain type: Translated ``` + Enable IOMMU: + + 1.Add boot parameters for linux kernel: `intel_iommu=on iommu=pt`; + ```shell + vim /boot/grub2/grub.cfg + linux /vmlinuz-5.15.0+ root=/dev/mapper/openeuler-root ro resume=/dev/mapper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap crashkernel=512M intel_iommu=on iommu=pt + ``` + 2.Reboot Host OS; + 2. Load the vfio-pci kernel module. ```shell diff --git "a/docs/zh/docs/StratoVirt/StratoVirt VFIO \344\275\277\347\224\250\350\257\264\346\230\216.md" "b/docs/zh/docs/StratoVirt/StratoVirt VFIO \344\275\277\347\224\250\350\257\264\346\230\216.md" index e938587f4..1df98b326 100644 --- "a/docs/zh/docs/StratoVirt/StratoVirt VFIO \344\275\277\347\224\250\350\257\264\346\230\216.md" +++ "b/docs/zh/docs/StratoVirt/StratoVirt VFIO \344\275\277\347\224\250\350\257\264\346\230\216.md" @@ -35,6 +35,14 @@ iommu: Default domain type: Translated ``` + 开启IOMMU: + + 1.为linux内核增加启动参数: `intel_iommu=on iommu=pt`; + ```shell + vim /boot/grub2/grub.cfg + linux /vmlinuz-5.15.0+ root=/dev/mapper/openeuler-root ro resume=/dev/mapper/openeuler-swap rd.lvm.lv=openeuler/root rd.lvm.lv=openeuler/swap crashkernel=512M intel_iommu=on iommu=pt + ``` + 2.重启Host OS; 2. 加载 vfio-pci 内核模块 -- Gitee From 11cb0af4cde6d3ea0efbc709848a8ee435a4f493 Mon Sep 17 00:00:00 2001 From: Vanient Date: Sat, 30 Jul 2022 17:41:56 +0800 Subject: [PATCH 068/130] =?UTF-8?q?docs:=E4=BF=AE=E6=94=B9rubik=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=B8=AD=E6=8F=8F=E8=BF=B0=E4=B8=8D=E5=90=88=E7=90=86?= =?UTF-8?q?=E7=9A=84=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Vanient --- ...\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" index 3669c4294..3520e7c2a 100644 --- "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" +++ "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -2,7 +2,7 @@ ## 概述 -本文档主要介绍rubik组件的安装以及部署方式。 +本章节主要介绍rubik组件的安装以及部署方式。 ## 软硬件要求 -- Gitee From f6d1b14ae6682a40e83bcb4b0fb99646df616752 Mon Sep 17 00:00:00 2001 From: mmdou2 Date: Mon, 1 Aug 2022 12:17:06 +0000 Subject: [PATCH 069/130] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=91=BD=E4=BB=A4=E4=B9=8B=E9=97=B4=E7=BC=BA=E5=B0=91=E7=A9=BA?= =?UTF-8?q?=E6=A0=BC=E5=AF=BC=E8=87=B4=E5=91=BD=E4=BB=A4=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=A4=B1=E8=B4=A5=E7=9A=84=E9=97=AE=E9=A2=98=20=E5=85=B3?= =?UTF-8?q?=E8=81=94issues=E4=B8=BA=20#I5HNPZ?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\207\206\345\244\207\350\257\201\344\271\246.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" "b/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" index 9ac080a5e..1ff573239 100644 --- "a/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" +++ "b/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" @@ -273,7 +273,7 @@ EOF # generate ca echo "generate: ${nodes[$i]} ${IPs[$i]}" - cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -hostname=${nodes[$i]},${IPs[$i]}-profile=kubernetes ${nodes[$i]}-csr.json | cfssljson -bare ${nodes[$i]} + cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -hostname=${nodes[$i]},${IPs[$i]} -profile=kubernetes ${nodes[$i]}-csr.json | cfssljson -bare ${nodes[$i]} done ``` -- Gitee From 2de76d68044b1fc41553776002ebc66e622bfff1 Mon Sep 17 00:00:00 2001 From: Vanient Date: Tue, 2 Aug 2022 12:01:31 +0800 Subject: [PATCH 070/130] docs:rubik typo fix Signed-off-by: Vanient --- ...\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" index 3520e7c2a..32fe79714 100644 --- "a/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" +++ "b/docs/zh/docs/rubik/\345\256\211\350\243\205\344\270\216\351\203\250\347\275\262.md" @@ -79,7 +79,7 @@ isula-build ctr-img build -f /var/lib/rubik/Dockerfile --tag rubik:0.1.0 . ... containers: - name: rubik-agent - image: rubik:0.1.0 # 此处镜像名需与上一步构建的rubuik镜像名一致 + image: rubik:0.1.0 # 此处镜像名需与上一步构建的rubik镜像名一致 imagePullPolicy: IfNotPresent ... ``` -- Gitee From 0d86817580aef54a37a21676d56e5e9ca73c4ed3 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 06:56:52 +0000 Subject: [PATCH 071/130] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20contribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/contribute/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/contribute/.keep diff --git a/docs/contribute/.keep b/docs/contribute/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From 1bfae97f6468aea30ff2fd628591eb548102f636 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 06:57:18 +0000 Subject: [PATCH 072/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?docs/contribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/contribute/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 docs/contribute/.keep diff --git a/docs/contribute/.keep b/docs/contribute/.keep deleted file mode 100644 index e69de29bb..000000000 -- Gitee From 13ae203e601105828fdcefc4540e4383d6b1d3a0 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 06:57:33 +0000 Subject: [PATCH 073/130] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20contribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 contribute/.keep diff --git a/contribute/.keep b/contribute/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From 3f211167d52b14f0a615673456611723cac455f4 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:15:39 +0000 Subject: [PATCH 074/130] =?UTF-8?q?add=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...31\344\275\234\350\247\204\350\214\203.md" | 200 ++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 "contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" new file mode 100644 index 000000000..b01e1cab2 --- /dev/null +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -0,0 +1,200 @@ +# 写作规范 + +## 命名 + +对于新增文档,请在对应的文件目录下新增MarkDown文档(即以.md结尾的文件)。文档命名需要根据文档的内容声明。 + +- 新增文档名称不能与已有文档重名,如果有请重新命名。 +- 新增文档之后,需要在menu文件夹下的index文件中新增对应的目录,否则新增文件无法显示。目录层级不建议超过三级。 +- 文件名中不能包含括号,会导致文件目录无法正常显示。可以将括号修改为可识别的下划线(\_)或者中划线(-)。 + +## 目录 + +文档为以.md结尾的文件,存储在https://gitee.com/openEuler/docs路径下。 + +docs文件夹中包含以下内容: + +- zh:全量版中文资料。 +- en:全量版英文资料。 + +根据文档所属的手册,选择对应的文件夹。不同手册所在文件夹请参见下表。 + +| 文件夹 | 手册 | +|-----|----| +| A-Tune | A-Tune用户指南 | +| Adminnistration | 管理员指南 | +| ApplicationDev | 应用开发指南 | +| Container | 容器用户指南 | +| Installation | 安装指南 | +| Quickstart | 快速入门 | +| Releasenotes | 发行说明 | +| SecHarden | 安全加固指南 | +| Virtualization | 虚拟化应用指南 | +| userguide | openEuler工具集用户指南 | +| StratoVirt | StratoVrit虚拟化用户指南 | + +## 内容 + +- 提交内容必须是与openEuler特性相关内容。 +- 内容不能包含敏感信息、有强烈的种族歧视或性别歧视的内容。 +- 提交的内容必须是原创内容,不得侵犯他人知识产权。 +- 提交的内容必须客观、真实,不允许使用夸大宣传等词汇。 + +## 标题 + +- 标题尽量采用简洁的语句概况反映章节的中心内容,注意不要省略必要的信息。例如:xxx概述,如果用概述来代替,就会导致读者无法从标题中获取到有用信息。 +- 操作类文档标题尽量用动宾结构(例如:申请权限)。 +- 相同级别,相同类型的标题结构保持一致。 +- 标题不使用标点符号结尾。 +- 标题中尽量采用圆括号来表示补充说明。 + +## 文档结构 + +- **操作类文档** + + 操作类文档写明步骤、注意事项、前提条件等,以便能对其他开发者起到帮助。 + + 以[使用合并方式更新和插入数据](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/StratoVirt/%E5%87%86%E5%A4%87%E4%BD%BF%E7%94%A8%E7%8E%AF%E5%A2%83.html)为例,可以参考如下文档结构: + + - 使用说明 + + 说明此操作在什么场景下使用可以解决用户的什么问题。 + + - 环境要求 + + 执行此操作需要用户准备的软硬件环境、权限以及其它约束条件。 + + - 操作步骤 + + 具体的操作步骤,需要注意如下事项: + + - 建议一步一个操作步骤,不建议多个操作步骤合并在一个步骤中描写。 + - 如果操作可选,要明确可选条件。 + - 开发步骤中,涉及调用接口(例如使用了工具或者SQL语句),需要对使用的接口进行说明。 + + - 结果验证 + + 说明如何验证操作结果正确。如果验证操作与步骤强相关,可以在步骤中描述。例如,执行SQL语句的返回信息。 + + +- **介绍类文档** + + 介绍性文档言简意赅介绍原理、使用场景、使用方法、约束等。 + + 以开发指南中[逻辑复制](https://opengauss.org/zh/docs/latest/docs/Developerguide/%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6.html)为例,文档结构可以参考如下: + + - 概述(概念及原理介绍) + - 功能(支持的接口列表) + - 开发流程(如何使用及相应步骤) + - 编程实例(提供具体代码示例) + - 注意事项 + + >![](public_sys-resources/icon-note.gif) **说明:** + >以上内容较多时,可以分多个文档作为子章节描述。 + +- **参考类文档** + + 参考类文档说明接口的功能、命令、参数说明、代码示例等内容。 + + 以[ABORT](https://opengauss.org/zh/docs/latest/docs/Developerguide/ABORT.html)为例,文档结构可以参考如下: + + - 功能描述 + + 说明该接口作用。 + + - 注意事项 + + 使用该接口的约束条件。 + + - 语法格式 + - 参数说明 + - 示例 + + >![](public_sys-resources/icon-note.gif) **说明:** + >[https://gitee.com/opengauss/docs/tree/master/contribute/template](https://gitee.com/opengauss/docs/tree/master/contribute/template)目录下有参考类文档模板,包含特性说明、SQL参考、CUC参考、工具参考。 + + +## 图片 + +- 图片统一存放到文档同级目录下的figures文件夹中。例如,[产品描述](https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription)中的手册中使用的图片,统一存储在[https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription/figures](https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription/figures) 路径下。该文件夹下的文件引用图片时,使用相对引用,例如,\`!\[逻辑架构图\]\(figures/openGauss逻辑架构图.png\) \`。 +- 请使用原创图片,避免存在知识产权侵权风险。 +- 图形清晰可辨识,图形信息完整,例如流程图有“开始”和“结束”。 +- 图形逻辑清晰。 +- 图文配合使用,切忌图文分离。 +- 图片格式首选png,此外也接受jpg。图片的高不超过640px,宽不超过 393px,图片大小建议不超过150K。 +- 中文用中文插图,英文用英文插图。 +- 图片建议根据内容命名,只用数字序列不利于后续图片的继承。 +- 如果是截图,请在允许的范围内只保留有用的信息。图形中需要突出的关键信息,可增加红色框线或者文字备注说明。 + +## 代码 + +代码示例说明了如何实现特定功能,开发人员使用代码示例来编写和调试代码。代码要求如下: + +- 代码的逻辑和语法正确。 +- 代码的输入和输出尽可能的分开。 +- 保证代码中关键步骤要有注释说明。 +- SQL命令请包含提示符openGauss=\#,以将SQL语句与其它命令区分开。 +- 代码源于具体实例。 + +## 注释符号 + +文档中会出现以下注释符号,代表不同的使用场景和提示程度。如果需要提示用户注意的信息,可以根据重要程度选择对应的注释符号。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

符号

+

说明

+

引用方法

+

+

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

+
>![](public_sys-resources/icon-danger.gif) **危险:**      
+>正文内容
+

+

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

+
>![](public_sys-resources/icon-warning.gif) **警告:**      
+>正文内容
+

+

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

+
>![](public_sys-resources/icon-caution.gif) **注意:**      
+>正文内容
+

+

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

+

“须知”不涉及人身伤害。

+
>![](public_sys-resources/icon-notice.gif) **须知:**      
+>正文内容
+

+

对正文中重点信息的补充说明。

+

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

+
>![](public_sys-resources/icon-note.gif) **说明:**      
+>正文内容
+
+ +## 链接 + +链接需要确保指向的目标文件存在,否则会造成链接跳转不正常。 + -- Gitee From 095e24fd3f48aa30a6438a890fc443cab503b022 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:30:36 +0000 Subject: [PATCH 075/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...31\344\275\234\350\247\204\350\214\203.md" | 40 +------------------ 1 file changed, 2 insertions(+), 38 deletions(-) diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index b01e1cab2..153c231f5 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -10,7 +10,7 @@ ## 目录 -文档为以.md结尾的文件,存储在https://gitee.com/openEuler/docs路径下。 +文档为以.md结尾的文件,存储在https://gitee.com/openEuler/docs 路径下。 docs文件夹中包含以下内容: @@ -77,46 +77,11 @@ docs文件夹中包含以下内容: 说明如何验证操作结果正确。如果验证操作与步骤强相关,可以在步骤中描述。例如,执行SQL语句的返回信息。 -- **介绍类文档** - - 介绍性文档言简意赅介绍原理、使用场景、使用方法、约束等。 - - 以开发指南中[逻辑复制](https://opengauss.org/zh/docs/latest/docs/Developerguide/%E9%80%BB%E8%BE%91%E5%A4%8D%E5%88%B6.html)为例,文档结构可以参考如下: - - - 概述(概念及原理介绍) - - 功能(支持的接口列表) - - 开发流程(如何使用及相应步骤) - - 编程实例(提供具体代码示例) - - 注意事项 - - >![](public_sys-resources/icon-note.gif) **说明:** - >以上内容较多时,可以分多个文档作为子章节描述。 - -- **参考类文档** - - 参考类文档说明接口的功能、命令、参数说明、代码示例等内容。 - - 以[ABORT](https://opengauss.org/zh/docs/latest/docs/Developerguide/ABORT.html)为例,文档结构可以参考如下: - - - 功能描述 - - 说明该接口作用。 - - - 注意事项 - - 使用该接口的约束条件。 - - - 语法格式 - - 参数说明 - - 示例 - - >![](public_sys-resources/icon-note.gif) **说明:** - >[https://gitee.com/opengauss/docs/tree/master/contribute/template](https://gitee.com/opengauss/docs/tree/master/contribute/template)目录下有参考类文档模板,包含特性说明、SQL参考、CUC参考、工具参考。 ## 图片 -- 图片统一存放到文档同级目录下的figures文件夹中。例如,[产品描述](https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription)中的手册中使用的图片,统一存储在[https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription/figures](https://gitee.com/opengauss/docs/tree/master/content/zh/docs/CharacteristicDescription/figures) 路径下。该文件夹下的文件引用图片时,使用相对引用,例如,\`!\[逻辑架构图\]\(figures/openGauss逻辑架构图.png\) \`。 +- 图片统一存放到文档同级目录下的figures文件夹中。例如,[A-Tune用户指南](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/A-Tune/A-Tune.html)中的手册中使用的图片,统一存储在[A-Tune](https://gitee.com/openeuler/docs/tree/stable2-22.03_LTS/docs/zh/docs/A-Tune/figures) 路径下。该文件夹下的文件引用图片时,使用相对引用。 - 请使用原创图片,避免存在知识产权侵权风险。 - 图形清晰可辨识,图形信息完整,例如流程图有“开始”和“结束”。 - 图形逻辑清晰。 @@ -133,7 +98,6 @@ docs文件夹中包含以下内容: - 代码的逻辑和语法正确。 - 代码的输入和输出尽可能的分开。 - 保证代码中关键步骤要有注释说明。 -- SQL命令请包含提示符openGauss=\#,以将SQL语句与其它命令区分开。 - 代码源于具体实例。 ## 注释符号 -- Gitee From a4e3cb78689bc29074c2b63f22a732800eb9896a Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:32:43 +0000 Subject: [PATCH 076/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\206\231\344\275\234\350\247\204\350\214\203.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index 153c231f5..910b221da 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -54,7 +54,7 @@ docs文件夹中包含以下内容: 操作类文档写明步骤、注意事项、前提条件等,以便能对其他开发者起到帮助。 - 以[使用合并方式更新和插入数据](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/StratoVirt/%E5%87%86%E5%A4%87%E4%BD%BF%E7%94%A8%E7%8E%AF%E5%A2%83.html)为例,可以参考如下文档结构: + 以[StratoVirt用户指南](https://docs.openeuler.org/zh/docs/22.03_LTS/docs/StratoVirt/%E5%87%86%E5%A4%87%E4%BD%BF%E7%94%A8%E7%8E%AF%E5%A2%83.html)为例,可以参考如下文档结构: - 使用说明 -- Gitee From 5d72bb1e9f6490e9d53d7a38aafb8b813bfd75bb Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:37:44 +0000 Subject: [PATCH 077/130] =?UTF-8?q?add=20contribute/MarkDown=E5=B8=B8?= =?UTF-8?q?=E7=94=A8=E8=AF=AD=E6=B3=95=E5=8F=82=E8=80=83.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...7\255\346\263\225\345\217\202\350\200\203" | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 "contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" diff --git "a/contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" "b/contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" new file mode 100644 index 000000000..f2f4a6098 --- /dev/null +++ "b/contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" @@ -0,0 +1,140 @@ +# MarkDown常用语法参考 + +## 标题 + +使用\#号标记:使用 \# 号可表示 1-6 级标题,一级标题对应一个 \# 号,二级标题对应两个 \# 号,以此类推。 + +``` +# 一级标题 +## 二级标题 +### 三级标题 +#### 四级标题 +##### 五级标题 +###### 六级标题 +``` + +## 字体 + +- 斜体:使用一个星号(\*)表示斜体。 + + ``` + *斜体文本* + ``` + +- 粗体:使用两个星号(\*\*)表示粗体。 + + ``` + **粗体文本** + ``` + +- 粗斜体:使用3个星号(\*\*\*)表示粗斜体。 + + ``` + ***粗斜体文本*** + ``` + + +## 列表 + +- 无序列表:无序列表使用星号(**\***)、加号(**+**)或是减号(**-**)作为列表标记,这些标记后面要添加一个空格,然后再填写内容。同一个无序列表,建议使用同一个符号。 + + ``` + * 第一项 + * 第二项 + * 第三项 + + + 第一项 + + 第二项 + + 第三项 + + + - 第一项 + - 第二项 + - 第三项 + ``` + + +- 有序列表:有序列表使用数字并加上 **.** 号来表示。 + + ``` + 1. 第一项 + 2. 第二项 + 3. 第三项 + ``` + + +- 嵌套列表:列表嵌套只需在子列表中的选项前面添加四个空格即可。 + + ``` + 1. 第一项: + - 第一项嵌套的第一个元素 + - 第一项嵌套的第二个元素 + 2. 第二项: + - 第二项嵌套的第一个元素 + - 第二项嵌套的第二个元素 + ``` + + +## 引用 + +Markdown 区块引用是在段落开头使用 **\>** 符号 ,然后后面紧跟一个**空格**符号。 + +``` +> 说明: +``` + +## 代码 + +- 行间代码:如果是段落上的一个函数或片段的代码可以用反引号把它包起来(**\`**)。 + +``` +`printf()` 函数 +``` + +- 代码块:可以用 **\`\`\`** 包裹一段代码。 + +``` +``` +select * from table; +``` +``` + +## 链接 + +链接使用方法如下: + +``` +[链接名称](链接地址) +``` + +## 图片 + +图片使用方法如下: + +``` +![alt 属性文本](图片地址) + +![alt 属性文本](图片地址 "可选标题") +``` + +- 开头一个感叹号 (!)。 +- 接着一个方括号,里面放上图片的替代文字。 +- 接着一个普通括号,里面放上图片的网址,最后还可以用引号包住并加上选择性的 'title' 属性的文字。 + +## 表格 + +Markdown 制作表格使用 **|** 来分隔不同的单元格,使用 **-** 来分隔表头和其他行。语法格式如下: + +``` +| 表头 | 表头 | +| ---- | ---- | +| 单元格 | 单元格 | +| 单元格 | 单元格 | +``` + +我们可以设置表格的对齐方式: + +- -: 设置内容和标题栏居右对齐。 +- :- 设置内容和标题栏居左对齐。 +- :-: 设置内容和标题栏居中对齐。 + -- Gitee From 048d355e0af356593d89b18a50e057a6b1345948 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:38:23 +0000 Subject: [PATCH 078/130] =?UTF-8?q?rename=20contribute/MarkDown=E5=B8=B8?= =?UTF-8?q?=E7=94=A8=E8=AF=AD=E6=B3=95=E5=8F=82=E8=80=83=20to=20contribute?= =?UTF-8?q?/MarkDown=E5=B8=B8=E7=94=A8=E8=AF=AD=E6=B3=95=E5=8F=82=E8=80=83?= =?UTF-8?q?.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...47\224\250\350\257\255\346\263\225\345\217\202\350\200\203.md" | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename "contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" => "contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203.md" (100%) diff --git "a/contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" "b/contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203.md" similarity index 100% rename from "contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203" rename to "contribute/MarkDown\345\270\270\347\224\250\350\257\255\346\263\225\345\217\202\350\200\203.md" -- Gitee From ca49101610a37252f20250a3ae24a5a0b393ab70 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 07:41:25 +0000 Subject: [PATCH 079/130] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20figures?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 contribute/figures/.keep diff --git a/contribute/figures/.keep b/contribute/figures/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From a80efce025964749c615361ffb970d2a47874ff3 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 09:36:06 +0000 Subject: [PATCH 080/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description.png | Bin 0 -> 1722 bytes contribute/figures/Warnings.png | Bin 0 -> 1125 bytes contribute/figures/dangerous.png | Bin 0 -> 1075 bytes contribute/figures/note.png | Bin 0 -> 1143 bytes contribute/figures/notice.png | Bin 0 -> 693 bytes ...31\344\275\234\350\247\204\350\214\203.md" | 69 ++++-------------- 6 files changed, 16 insertions(+), 53 deletions(-) create mode 100644 contribute/figures/Description.png create mode 100644 contribute/figures/Warnings.png create mode 100644 contribute/figures/dangerous.png create mode 100644 contribute/figures/note.png create mode 100644 contribute/figures/notice.png diff --git a/contribute/figures/Description.png b/contribute/figures/Description.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa7f168714924cf9f87a47191bbc1b7339458f6 GIT binary patch literal 1722 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 II;Vst0JszNk^lez literal 0 HcmV?d00001 diff --git a/contribute/figures/dangerous.png b/contribute/figures/dangerous.png new file mode 100644 index 0000000000000000000000000000000000000000..575bafbc1c7812a8a792ae3caca1ac38ec02d783 GIT binary patch literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 literal 0 HcmV?d00001 diff --git a/contribute/figures/note.png b/contribute/figures/note.png new file mode 100644 index 0000000000000000000000000000000000000000..0644ab8fb5b2d45425c6e0d62030c90888f2a037 GIT binary patch literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 literal 0 HcmV?d00001 diff --git a/contribute/figures/notice.png b/contribute/figures/notice.png new file mode 100644 index 0000000000000000000000000000000000000000..cc2cc962c775ce22ef8dccc06d0d78815463229b GIT binary patch literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku - - - - - - - - - - - - - - - - - - - - - - - - - - -

符号

-

说明

-

引用方法

-

-

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

-
>![](public_sys-resources/icon-danger.gif) **危险:**      
->正文内容
-

-

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

-
>![](public_sys-resources/icon-warning.gif) **警告:**      
->正文内容
-

-

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

-
>![](public_sys-resources/icon-caution.gif) **注意:**      
->正文内容
-

-

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

-

“须知”不涉及人身伤害。

-
>![](public_sys-resources/icon-notice.gif) **须知:**      
->正文内容
-

-

对正文中重点信息的补充说明。

-

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

-
>![](public_sys-resources/icon-note.gif) **说明:**      
->正文内容
-
+| 符号 | 说明 | 引用方法 | +|-----|----| +| ![](./figures/dangerous.png) | 表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。| >![](public_sys-resources/icon-danger.gif) **危险:** +>正文内容 | +| ![](./figures/Warnings.png) | 表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。| >![](public_sys-resources/icon-warning.gif) **警告:** +>正文内容 | +| ![](./figures/note.png) | 表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。 | >![](public_sys-resources/icon-caution.gif) **注意:** +>正文内容 | +| ![](./figures/notice.png) | 用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。 +“须知”不涉及人身伤害。 | >![](public_sys-resources/icon-notice.gif) **须知:** +>正文内容 | +| ![](./figures/Description.png) | 对正文中重点信息的补充说明。 + +“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。 | >![](public_sys-resources/icon-note.gif) **说明:** +>正文内容 | + ## 链接 -- Gitee From 4a732c240ade0984eea4ed295d12b0fdd7679151 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 09:38:29 +0000 Subject: [PATCH 081/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\206\231\344\275\234\350\247\204\350\214\203.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index 313e2625e..ba167ace2 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -105,7 +105,7 @@ docs文件夹中包含以下内容: 文档中会出现以下注释符号,代表不同的使用场景和提示程度。如果需要提示用户注意的信息,可以根据重要程度选择对应的注释符号。 | 符号 | 说明 | 引用方法 | -|-----|----| +|------|------|--------| | ![](./figures/dangerous.png) | 表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。| >![](public_sys-resources/icon-danger.gif) **危险:** >正文内容 | | ![](./figures/Warnings.png) | 表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。| >![](public_sys-resources/icon-warning.gif) **警告:** -- Gitee From b0016df9819196b3745316fd5ed3de36a3235951 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 09:44:21 +0000 Subject: [PATCH 082/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description1.png | Bin 0 -> 1722 bytes contribute/figures/Warnings1.png | Bin 0 -> 1125 bytes contribute/figures/dangerous1.png | Bin 0 -> 1075 bytes contribute/figures/note1.png | Bin 0 -> 1143 bytes contribute/figures/notice1.png | Bin 0 -> 693 bytes ...31\344\275\234\350\247\204\350\214\203.md" | 69 ++++++++++++++---- 6 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 contribute/figures/Description1.png create mode 100644 contribute/figures/Warnings1.png create mode 100644 contribute/figures/dangerous1.png create mode 100644 contribute/figures/note1.png create mode 100644 contribute/figures/notice1.png diff --git a/contribute/figures/Description1.png b/contribute/figures/Description1.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa7f168714924cf9f87a47191bbc1b7339458f6 GIT binary patch literal 1722 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 II;Vst0JszNk^lez literal 0 HcmV?d00001 diff --git a/contribute/figures/dangerous1.png b/contribute/figures/dangerous1.png new file mode 100644 index 0000000000000000000000000000000000000000..575bafbc1c7812a8a792ae3caca1ac38ec02d783 GIT binary patch literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 literal 0 HcmV?d00001 diff --git a/contribute/figures/note1.png b/contribute/figures/note1.png new file mode 100644 index 0000000000000000000000000000000000000000..0644ab8fb5b2d45425c6e0d62030c90888f2a037 GIT binary patch literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 literal 0 HcmV?d00001 diff --git a/contribute/figures/notice1.png b/contribute/figures/notice1.png new file mode 100644 index 0000000000000000000000000000000000000000..cc2cc962c775ce22ef8dccc06d0d78815463229b GIT binary patch literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku![](public_sys-resources/icon-danger.gif) **危险:** ->正文内容 | -| ![](./figures/Warnings.png) | 表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。| >![](public_sys-resources/icon-warning.gif) **警告:** ->正文内容 | -| ![](./figures/note.png) | 表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。 | >![](public_sys-resources/icon-caution.gif) **注意:** ->正文内容 | -| ![](./figures/notice.png) | 用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。 -“须知”不涉及人身伤害。 | >![](public_sys-resources/icon-notice.gif) **须知:** ->正文内容 | -| ![](./figures/Description.png) | 对正文中重点信息的补充说明。 - -“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。 | >![](public_sys-resources/icon-note.gif) **说明:** ->正文内容 | + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

符号

+

说明

+

引用方法

+

+

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

+
>![](public_sys-resources/icon-danger.gif) **危险:**      
+>正文内容
+

+

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

+
>![](public_sys-resources/icon-warning.gif) **警告:**      
+>正文内容
+

+

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

+
>![](public_sys-resources/icon-caution.gif) **注意:**      
+>正文内容
+

+

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

+

“须知”不涉及人身伤害。

+
>![](public_sys-resources/icon-notice.gif) **须知:**      
+>正文内容
+

+

对正文中重点信息的补充说明。

+

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

+
>![](public_sys-resources/icon-note.gif) **说明:**      
+>正文内容
+
## 链接 -- Gitee From b274b65e5c6ad5d6e38fa03c69b4b5046c366003 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 09:54:32 +0000 Subject: [PATCH 083/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description2.png | Bin 0 -> 1722 bytes contribute/figures/Warnings2.png | Bin 0 -> 1125 bytes contribute/figures/dangerous2.png | Bin 0 -> 1075 bytes contribute/figures/note2.png | Bin 0 -> 1143 bytes contribute/figures/notice2.png | Bin 0 -> 693 bytes ...31\344\275\234\350\247\204\350\214\203.md" | 69 ++++-------------- 6 files changed, 16 insertions(+), 53 deletions(-) create mode 100644 contribute/figures/Description2.png create mode 100644 contribute/figures/Warnings2.png create mode 100644 contribute/figures/dangerous2.png create mode 100644 contribute/figures/note2.png create mode 100644 contribute/figures/notice2.png diff --git a/contribute/figures/Description2.png b/contribute/figures/Description2.png new file mode 100644 index 0000000000000000000000000000000000000000..3aa7f168714924cf9f87a47191bbc1b7339458f6 GIT binary patch literal 1722 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 II;Vst0JszNk^lez literal 0 HcmV?d00001 diff --git a/contribute/figures/dangerous2.png b/contribute/figures/dangerous2.png new file mode 100644 index 0000000000000000000000000000000000000000..575bafbc1c7812a8a792ae3caca1ac38ec02d783 GIT binary patch literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 literal 0 HcmV?d00001 diff --git a/contribute/figures/note2.png b/contribute/figures/note2.png new file mode 100644 index 0000000000000000000000000000000000000000..0644ab8fb5b2d45425c6e0d62030c90888f2a037 GIT binary patch literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 literal 0 HcmV?d00001 diff --git a/contribute/figures/notice2.png b/contribute/figures/notice2.png new file mode 100644 index 0000000000000000000000000000000000000000..cc2cc962c775ce22ef8dccc06d0d78815463229b GIT binary patch literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku - - - - - - - - - - - - - - - - - - - - - - - - - - -

符号

-

说明

-

引用方法

-

-

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

-
>![](public_sys-resources/icon-danger.gif) **危险:**      
->正文内容
-

-

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

-
>![](public_sys-resources/icon-warning.gif) **警告:**      
->正文内容
-

-

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

-
>![](public_sys-resources/icon-caution.gif) **注意:**      
->正文内容
-

-

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

-

“须知”不涉及人身伤害。

-
>![](public_sys-resources/icon-notice.gif) **须知:**      
->正文内容
-

-

对正文中重点信息的补充说明。

-

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

-
>![](public_sys-resources/icon-note.gif) **说明:**      
->正文内容
-
+| 符号 | 说明 | 引用方法 | +|:--- |:---- |:--- | +| ![](./figures/dangerous2.png) | 表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。 |>![](public_sys-resources/icon-danger.gif) **危险:** +>正文内容 | +| ![](./figures/Warnings2.png) | 表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。 | >![](public_sys-resources/icon-warning.gif) **警告:** +>正文内容 | +| ![](./figures/note2.png)| 表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。 |>![](public_sys-resources/icon-caution.gif) **注意:** +>正文内容 | +| ![](./figures/notice2.png)| 用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。 + +“须知”不涉及人身伤害。 | >![](public_sys-resources/icon-notice.gif) **须知:** +>正文内容 | +| ![](./figures/Description2.png) | 对正文中重点信息的补充说明。 + +“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息 | >![](public_sys-resources/icon-note.gif) **说明:** +>正文内容 | ## 链接 -- Gitee From 876da49fc74da191f664158c7faaf9e9ba3fcbb2 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Thu, 4 Aug 2022 09:55:06 +0000 Subject: [PATCH 084/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...31\344\275\234\350\247\204\350\214\203.md" | 69 ++++++++++++++----- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index d24ff0f15..d82e2ea5f 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -105,22 +105,59 @@ docs文件夹中包含以下内容: 文档中会出现以下注释符号,代表不同的使用场景和提示程度。如果需要提示用户注意的信息,可以根据重要程度选择对应的注释符号。 -| 符号 | 说明 | 引用方法 | -|:--- |:---- |:--- | -| ![](./figures/dangerous2.png) | 表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。 |>![](public_sys-resources/icon-danger.gif) **危险:** ->正文内容 | -| ![](./figures/Warnings2.png) | 表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。 | >![](public_sys-resources/icon-warning.gif) **警告:** ->正文内容 | -| ![](./figures/note2.png)| 表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。 |>![](public_sys-resources/icon-caution.gif) **注意:** ->正文内容 | -| ![](./figures/notice2.png)| 用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。 - -“须知”不涉及人身伤害。 | >![](public_sys-resources/icon-notice.gif) **须知:** ->正文内容 | -| ![](./figures/Description2.png) | 对正文中重点信息的补充说明。 - -“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息 | >![](public_sys-resources/icon-note.gif) **说明:** ->正文内容 | + + + + + + + + + + + + + + + + + + + + + + + + + + + +

符号

+

说明

+

引用方法

+

+

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

+
>![](public_sys-resources/icon-danger.gif) **危险:**      
+>正文内容
+

+

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

+
>![](public_sys-resources/icon-warning.gif) **警告:**      
+>正文内容
+

+

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

+
>![](public_sys-resources/icon-caution.gif) **注意:**      
+>正文内容
+

+

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

+

“须知”不涉及人身伤害。

+
>![](public_sys-resources/icon-notice.gif) **须知:**      
+>正文内容
+

+

对正文中重点信息的补充说明。

+

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

+
>![](public_sys-resources/icon-note.gif) **说明:**      
+>正文内容
+
## 链接 -- Gitee From 748f688e0c8c079bc633ddd115decfb8644fe712 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:19:52 +0000 Subject: [PATCH 085/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Description.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description.png | Bin 1722 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Description.png diff --git a/contribute/figures/Description.png b/contribute/figures/Description.png deleted file mode 100644 index 3aa7f168714924cf9f87a47191bbc1b7339458f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1722 zcmeAS@N?(olHy`uVBq!ia0vp^en2e4!OXzG*l+6T3gj>r2e~^jtUD+363Agmcl32+ zVA$Bt{U?!?fq`jdfKLcW5dk0|z|X+IM?eusnjMJP*?HN4GzhSHz3p5<=RFK2K&VU;TWI!B-EP}>{=z=%{*)b4ha7%#1iTp1*kAX0D=E{m)Y zO%|vIXk*CPYF(hjgOVV>UAF>wh=DQOu6MI}{LHFYg5Ep1%` zBO?=2Gjj_|D{EUjdj|&>S2uSLPcLuZfWW|@py1H(@QBFRxcG$3tn8fJ-28&V!lL4m z($cc>ipr|$n%cVh`i6$)=9c!3uI|462@|JGnL2&O>^XDiE?Br|$KIVxoh|Cz5DjWe*MPHTeoiCzJ2H3 z{re9dK6?E4$&;tgo;`o@^3|)?Z{ECp`|kbw_a8of`uyeV_a8rh{`&pr@4tUrO)Ehe zjoo{7Hg)qx0dws-PZ!4!3;(xMeun!bN*v!Gd?-Szn!|Nrt4UhQ$$4vA zW=u)xx^rThu2AbH*C`$=awewSH(Ka+DM>_inabn6pQl&6e>CIel{qqf@^kFI&v{;X z@BQC-&-c8y{a$-v(ureEN+Ess$||i}H;GnF^H|_)8t%22(P@5}B5SF2+0@9R4vSBU zy0#@svK1Vxys;oc-|q!+@8LG=lJ#HMFlthPm)W@n_Q6aVD9e24U#2^ zzA9GHTiLIPnEEWbA6W3=3CraNmW^!7g{1a~UA$h^Qkg9(ec^zli%;$Rj{7DTyceue zDk`1TSI#lxmrjTL+vSgc{d`kw`dqtzv$jOS%2Vozp4`%v?GAoNH-B$m=70C|yPwRj zHY=U}8mpDO=i0fV1?>iQ$7R|Q56Ra@xL&Twi&Z{)QP@O%SHHgB!xp}Orp5YqPy5)1 z2JTALU|YNU>(56oi~HmBgySOb_q}cTVO6cLux3;10>;1MENm<~U%v}XUnY|rULf3P z^!rrO!iLEY-OBa6+rrJyf39`h_H5#k191&rv*)`viL8G#H9jS}fAyyK@e+w??rPsF6Qrc)sHDcfzGHc^%-r+c l^QC$ Date: Fri, 5 Aug 2022 02:19:58 +0000 Subject: [PATCH 086/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Description1.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description1.png | Bin 1722 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Description1.png diff --git a/contribute/figures/Description1.png b/contribute/figures/Description1.png deleted file mode 100644 index 3aa7f168714924cf9f87a47191bbc1b7339458f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1722 zcmeAS@N?(olHy`uVBq!ia0vp^en2e4!OXzG*l+6T3gj>r2e~^jtUD+363Agmcl32+ zVA$Bt{U?!?fq`jdfKLcW5dk0|z|X+IM?eusnjMJP*?HN4GzhSHz3p5<=RFK2K&VU;TWI!B-EP}>{=z=%{*)b4ha7%#1iTp1*kAX0D=E{m)Y zO%|vIXk*CPYF(hjgOVV>UAF>wh=DQOu6MI}{LHFYg5Ep1%` zBO?=2Gjj_|D{EUjdj|&>S2uSLPcLuZfWW|@py1H(@QBFRxcG$3tn8fJ-28&V!lL4m z($cc>ipr|$n%cVh`i6$)=9c!3uI|462@|JGnL2&O>^XDiE?Br|$KIVxoh|Cz5DjWe*MPHTeoiCzJ2H3 z{re9dK6?E4$&;tgo;`o@^3|)?Z{ECp`|kbw_a8of`uyeV_a8rh{`&pr@4tUrO)Ehe zjoo{7Hg)qx0dws-PZ!4!3;(xMeun!bN*v!Gd?-Szn!|Nrt4UhQ$$4vA zW=u)xx^rThu2AbH*C`$=awewSH(Ka+DM>_inabn6pQl&6e>CIel{qqf@^kFI&v{;X z@BQC-&-c8y{a$-v(ureEN+Ess$||i}H;GnF^H|_)8t%22(P@5}B5SF2+0@9R4vSBU zy0#@svK1Vxys;oc-|q!+@8LG=lJ#HMFlthPm)W@n_Q6aVD9e24U#2^ zzA9GHTiLIPnEEWbA6W3=3CraNmW^!7g{1a~UA$h^Qkg9(ec^zli%;$Rj{7DTyceue zDk`1TSI#lxmrjTL+vSgc{d`kw`dqtzv$jOS%2Vozp4`%v?GAoNH-B$m=70C|yPwRj zHY=U}8mpDO=i0fV1?>iQ$7R|Q56Ra@xL&Twi&Z{)QP@O%SHHgB!xp}Orp5YqPy5)1 z2JTALU|YNU>(56oi~HmBgySOb_q}cTVO6cLux3;10>;1MENm<~U%v}XUnY|rULf3P z^!rrO!iLEY-OBa6+rrJyf39`h_H5#k191&rv*)`viL8G#H9jS}fAyyK@e+w??rPsF6Qrc)sHDcfzGHc^%-r+c l^QC$ Date: Fri, 5 Aug 2022 02:20:06 +0000 Subject: [PATCH 087/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Warnings1.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Warnings1.png | Bin 1125 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Warnings1.png diff --git a/contribute/figures/Warnings1.png b/contribute/figures/Warnings1.png deleted file mode 100644 index 5daec9520108da4e48c154838015df05d2557070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1125 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAud@ma}qQuVo1yDbNHen~>ubALN=86EL+iSx#2=Os?#? zIQE5JLS^QnLfl+t3SvrPLK_14oirpxd3ja^iyJA3P4$(HFqD=OC~tqWs!6&i{1 za@(m(>dT9%iVFo8$jAxvnW)ML3kmAWOY~=YoLU#KU{Z2?u$zXIh^iRBzO;~p01qD* zCqFNjtPr1^uz;1Sq>Ym3>X`}43LJPjIfQw*+TCP!M2iY?b6F~hwWRwf$jjf@W-HFi zEh)&WBr2dGDa^*ft|cX`Ai{rflShcQn2U;tydXCR3rm2u_#_u$O>zESSBbblmta4) z4u9411n=45%K4e$Czji+n&`GDRJOA|(bGzShl_pR9D{~*?HD6TVCaRm?vV#l1tmd# z!T;$C7`7)ST>{$8S>O>_%)r3)8iW~}x_P4*7?_kiT^vI!{NGLu?3OYVIKEtu@$E|f zslMXRf0eQLy`Js(yI_O9*t($B%9U{uUEQa)Zn^(|>;II;mD+LZFYFU}w>@Xh%$AcW z>1si};VzeAStq7HS;6xtQt#xcTindc-o}&|*c~qFIJk3n$dM4Sqzel!N$h%+a`D@7 zpO1O0i8^yxRxTA$7dtt5lg{zPUk9EX(2)A) zt#?RszU#-`UMEz~uMdbw`8daDW?e?urQSOp>uxVOe(cv(Q?c5k%?heYQESvv|7=?2 z&X+TRF;6wFq*!qF`IkPMGLF~C7P~Ulgh-uqVzoK6$Ru!H@E4^!op*k|G@N#oZ{nGn z=RcOl6(5s$;~A;$n|*K6j31uLQgIeWSuIok3Y(psc2u=^No+}MxcBq3w_LqfaYx;p zJj>#E!ihg|SF21*7i~?Ea?SWEcF*-#@|4BudY0Zv(X~s{g1;I{IV@arx>SGnUzX(; z_Ago$Xl2H`*?;l_r>4zf@5PT-uZumA)m!a;a+N^1z@b$aDqgkzoiXv%;~<^YU-x0HVv&3aw#Y_=-d!ta;hg{bVeSRhe+N_ikDEs7G*6#@ z|1kgiRnOSBZ@YfFN}?Pum#<=O1CtPgr>mdK II;Vst0JszNk^lez -- Gitee From 274a22c63f23fc653a1dac3851c54388e40e269d Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:20:13 +0000 Subject: [PATCH 088/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Warnings.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Warnings.png | Bin 1125 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Warnings.png diff --git a/contribute/figures/Warnings.png b/contribute/figures/Warnings.png deleted file mode 100644 index 5daec9520108da4e48c154838015df05d2557070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1125 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAud@ma}qQuVo1yDbNHen~>ubALN=86EL+iSx#2=Os?#? zIQE5JLS^QnLfl+t3SvrPLK_14oirpxd3ja^iyJA3P4$(HFqD=OC~tqWs!6&i{1 za@(m(>dT9%iVFo8$jAxvnW)ML3kmAWOY~=YoLU#KU{Z2?u$zXIh^iRBzO;~p01qD* zCqFNjtPr1^uz;1Sq>Ym3>X`}43LJPjIfQw*+TCP!M2iY?b6F~hwWRwf$jjf@W-HFi zEh)&WBr2dGDa^*ft|cX`Ai{rflShcQn2U;tydXCR3rm2u_#_u$O>zESSBbblmta4) z4u9411n=45%K4e$Czji+n&`GDRJOA|(bGzShl_pR9D{~*?HD6TVCaRm?vV#l1tmd# z!T;$C7`7)ST>{$8S>O>_%)r3)8iW~}x_P4*7?_kiT^vI!{NGLu?3OYVIKEtu@$E|f zslMXRf0eQLy`Js(yI_O9*t($B%9U{uUEQa)Zn^(|>;II;mD+LZFYFU}w>@Xh%$AcW z>1si};VzeAStq7HS;6xtQt#xcTindc-o}&|*c~qFIJk3n$dM4Sqzel!N$h%+a`D@7 zpO1O0i8^yxRxTA$7dtt5lg{zPUk9EX(2)A) zt#?RszU#-`UMEz~uMdbw`8daDW?e?urQSOp>uxVOe(cv(Q?c5k%?heYQESvv|7=?2 z&X+TRF;6wFq*!qF`IkPMGLF~C7P~Ulgh-uqVzoK6$Ru!H@E4^!op*k|G@N#oZ{nGn z=RcOl6(5s$;~A;$n|*K6j31uLQgIeWSuIok3Y(psc2u=^No+}MxcBq3w_LqfaYx;p zJj>#E!ihg|SF21*7i~?Ea?SWEcF*-#@|4BudY0Zv(X~s{g1;I{IV@arx>SGnUzX(; z_Ago$Xl2H`*?;l_r>4zf@5PT-uZumA)m!a;a+N^1z@b$aDqgkzoiXv%;~<^YU-x0HVv&3aw#Y_=-d!ta;hg{bVeSRhe+N_ikDEs7G*6#@ z|1kgiRnOSBZ@YfFN}?Pum#<=O1CtPgr>mdK II;Vst0JszNk^lez -- Gitee From 8d496f5d1335c90ddc824ecbbd195f8493d884ff Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:20:23 +0000 Subject: [PATCH 089/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/dangerous.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/dangerous.png | Bin 1075 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/dangerous.png diff --git a/contribute/figures/dangerous.png b/contribute/figures/dangerous.png deleted file mode 100644 index 575bafbc1c7812a8a792ae3caca1ac38ec02d783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 -- Gitee From 9a6f42f6fb8625f327aa8ba9f14041643b3d4636 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:20:30 +0000 Subject: [PATCH 090/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/dangerous1.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/dangerous1.png | Bin 1075 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/dangerous1.png diff --git a/contribute/figures/dangerous1.png b/contribute/figures/dangerous1.png deleted file mode 100644 index 575bafbc1c7812a8a792ae3caca1ac38ec02d783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 -- Gitee From b3fd416f9224a43fbff0eca681733b157c27f5e0 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:20:36 +0000 Subject: [PATCH 091/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/note.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/note.png | Bin 1143 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/note.png diff --git a/contribute/figures/note.png b/contribute/figures/note.png deleted file mode 100644 index 0644ab8fb5b2d45425c6e0d62030c90888f2a037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 -- Gitee From 70b63871d2274f9c4913ddbc00e070ef36695d0e Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:20:47 +0000 Subject: [PATCH 092/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/note1.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/note1.png | Bin 1143 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/note1.png diff --git a/contribute/figures/note1.png b/contribute/figures/note1.png deleted file mode 100644 index 0644ab8fb5b2d45425c6e0d62030c90888f2a037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 -- Gitee From 754ce18a90667978da222ce539210181ae1b87f5 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 02:21:51 +0000 Subject: [PATCH 093/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/notice.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/notice.png | Bin 693 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/notice.png diff --git a/contribute/figures/notice.png b/contribute/figures/notice.png deleted file mode 100644 index cc2cc962c775ce22ef8dccc06d0d78815463229b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku Date: Fri, 5 Aug 2022 02:22:00 +0000 Subject: [PATCH 094/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/notice1.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/notice1.png | Bin 693 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/notice1.png diff --git a/contribute/figures/notice1.png b/contribute/figures/notice1.png deleted file mode 100644 index cc2cc962c775ce22ef8dccc06d0d78815463229b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku Date: Fri, 5 Aug 2022 07:09:49 +0000 Subject: [PATCH 095/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dangerous2 - \345\211\257\346\234\254.png" | Bin 0 -> 1075 bytes ...6\231\344\275\234\350\247\204\350\214\203.md" | 1 + 2 files changed, 1 insertion(+) create mode 100644 "contribute/figures/dangerous2 - \345\211\257\346\234\254.png" diff --git "a/contribute/figures/dangerous2 - \345\211\257\346\234\254.png" "b/contribute/figures/dangerous2 - \345\211\257\346\234\254.png" new file mode 100644 index 0000000000000000000000000000000000000000..575bafbc1c7812a8a792ae3caca1ac38ec02d783 GIT binary patch literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 literal 0 HcmV?d00001 diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index d82e2ea5f..1147e2835 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -32,6 +32,7 @@ docs文件夹中包含以下内容: | Virtualization | 虚拟化应用指南 | | userguide | openEuler工具集用户指南 | | StratoVirt | StratoVrit虚拟化用户指南 | +| ![输入图片说明](figures/dangerous2%20-%20%E5%89%AF%E6%9C%AC.png) | StratoVrit虚拟化用户指南 | ## 内容 -- Gitee From 05d639bd791d08a4981c1cc24ec609cec169b77f Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:13:35 +0000 Subject: [PATCH 096/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\345\206\231\344\275\234\350\247\204\350\214\203.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index 1147e2835..0aa78dbdd 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -32,7 +32,7 @@ docs文件夹中包含以下内容: | Virtualization | 虚拟化应用指南 | | userguide | openEuler工具集用户指南 | | StratoVirt | StratoVrit虚拟化用户指南 | -| ![输入图片说明](figures/dangerous2%20-%20%E5%89%AF%E6%9C%AC.png) | StratoVrit虚拟化用户指南 | + ## 内容 -- Gitee From 4894925493a9ef7456316031826795d1d5ccb4f3 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:22:12 +0000 Subject: [PATCH 097/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/note.png | Bin 0 -> 78117 bytes ...31\344\275\234\350\247\204\350\214\203.md" | 57 +----------------- 2 files changed, 1 insertion(+), 56 deletions(-) create mode 100644 contribute/figures/note.png diff --git a/contribute/figures/note.png b/contribute/figures/note.png new file mode 100644 index 0000000000000000000000000000000000000000..149f800b20ab71c7d9e17dfc983709fdc7007f66 GIT binary patch literal 78117 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

e^Qr>V`eFgV^(e@oa$lqM?OO}qNFdarEcaLe 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�E5LCz3*&= zjnf5a8ogZyB|U`8-=+$3L9X$dG6sV?Gvh@$j%| z|J;df2h+<=sv4CWhfUk_8C`Uj$CJaBv0KmBs8yepG(vn<@3akvY?!?F(Q)kzWUpF7 zsI)Z0Ko}H$|K5n($&h(I<}!XFVAxaGzi&Vj!5sKE>n+VUvf{f$8aoPK6&KLX2*@yB z$cO(5IOg<9!|^lxuz33JC0`?#^pM7hvuUy=R)xXo+PM% z`r2e|0wq|WSzWU=u8N&F7`maQ@Qy{GQRo)DRcvkUa5TCydzJ`cRR*s^jeG_z_xG3x zva@@)nCDxYQp{efPuJt3 znB)M`RbzsvtUc`(?gK~7v)|!v-bdigUi@WG=@W=PPOfBixW-is&Q)8Q2pPd_bPXkwpxDbkir9aik=WMLL zq)%C+X0{X;hCAQm4wG2ATcDstm?GIwt&+b}Z%Cv!pdxaMmZoYfHDBk`*HN!=V+=UQaQ)V!z@T#&l6)Qz9?qo`()pVl3EeJG`&`cn*FSxtJ}P z3L){9Xs&$cWR1CQ=#ZKu+j4oA*dRU0J)Yq_?erMu1im<;F&t0p|1_XfB)mOSF*2wW zVSMi1$MRQ+(MFkwBx|aIQ-@KSOoQyT_GF%8q&7VN*~Dt5qD*%1}<#o9B%4T-+ScuoDwbYP3DEdiUvO)|dG1{+s*QSz4#OKe% zqQ)MLH}SvQu(>`Q;&St(vs}Vu({%o6%L!FEqvrdw=femCs;RP$X)Dspda!hMY+flz z5wPC9U*B8BRu|y=&g`q@J&5-^jic3h5VgVW0XNn6+xNtk<*;MH!}%-2uT3VuTD&zs z>aLAYR*#;2&`Q&bF%@neAC2&zR_=sUVK78@{Ubwmm6P`{v zAV8dNy$0i%ZEgtvfYKYen+-odJ#oO}d<(XfmrC}~TizqbsB;~;tc#4mhD14y7j7@mvwd;}x1dulu;51SmHH&njFN-3RjRyKt=C>^C(AubL) zvAwO96^y4^EeMQ*%@|L}{_sDv@FAmr&5uLzkXeuVvP=soQMf|3yt6lfi+GkUFA0B9 zXO_lAJtFfUf!qk5xkrc}@fO*ySy{m_l;# zl)FM^)^-T&SNP1g4rePj#zAm7e(+Es7jy9mw7c1g^krp+{^NP_aK=M!D~ z!sR5rv(aEd4W*{bvgaWEC(p}gEz0ZXOGH+ZdOzIuFWLCO zla+@Xy@l{w$?J0;aYW&U9EvFOIyhw2`j1dUdb#OG`kJo2>@q2fhY)%0rV50-U|vFjpzHg zOdX=A05^*(&`rJbvUCFJL+fxt#>fs?1W;zcN4ro1e*=K4&53B69^Tu9q!znQ1#xF7 zt(93D!uh&aqV*(ove8Iy#ifjx%L;q5F+5W%#hr>`=I+BUlUw+i0g%+YvDgFs2vqUd z8(q{{3$Pkj0SaM|7T#6Q6UWR0>zEJ5m!nt+Tznkr`6+UAJjZa+ixv)wDCy&2KR5Lf z?ZKyVXKLHIG0hQ&#Rc`RJ06{{Y=fQileZesfm?mtzUa{F&6cnY3uPtl1*a`PSCt0{ zJDz@q8fcfi6~IydFG$J$bzv<>SooR_SO1<*R1LvLKC32p9cr;XiD2Sb`kWJNa4pm| zRsX;nVC(N=aO=!taT{m9Qu<6?>HZc#7)9K~Yn#rk#W+AvZ{SgEEG=P!Q&Sbr@aIn3 z#rRLF4BxZ!vTM@HR};A6<_hv)8}C8l`G=@X&2@d9}Fnb+iG-yGg9K9Y*V=%ztGiRg;k(CQAsi z9(b=ixc79s6dHPfKKhz+RJD*9xLD=6s~nD@70Yd6+#M-4D|w{` zAmn;LpB{8Gn$iwCEV>?W{uyfNs5@Boj>=vu#F0{VNLxWw-0o7oU2XS(+3X4iL9*{V zr^WkLDtpXpA$h6ot5=u8LXs=dE?b7>#;HMn{P)Vq_pH5ZmE;us<`>Kz?s-wQy;jN( z2x8gs?r^D%Lr`F%{$vLyFd;hT^rEMuej;f^R={z-N52>t#x0b}1=?D7OzoS<%O3DX z5r;u+oqQ??F7uT{Cwy7wp0&~-pFY?MiMOB1go+m5_j^?GlhcQt7P zhx^%Ln6hao;`-$8+nw4I#@68!O17#@vh-F(IG_8FfXd=s(Cg#KrObHX&Xcf64D1I;us4oTUtNagJan^dtvO6uABL!e78U9wX60=^%27pC~S~y*x)}u z#fGEpSH+@K-kg``I6T?DS1olBmMJsu zO15&srsvm2EVYzUL#?j$wv2pO*;I^?tY8&r^tI##(jH7KZ#m+NPeqN?x&GmO#!3E8 zm9ZIeWMGAfit)3GE=we~@Gn8jjzG=$WAI=}$iO%KokSn`$?EwMzirl48 zqgjwgatc`{9VpnIABjBNe0wrY+U2mM0L>TUvT#s$F%{%&0mZftOD9%#q4kkT%9CFwLmcDC}8P6vV3 zsk*;it0LY$6j^Jt(JjV z{AY;5(ZLo9bL^IX5ab_$a_mBiPZsAhV}Y?9{0_X$2!`0k4w~3!5~}89^m~`Qx_qFt z(FIk4Z_rtE*1cP7SG-E*;!Lx+s~7LvwF<{SjPx0u={=9$ZG07`rAF)NxbL=J$DG~e zJAYgM@fnsPC*K(!I}{vex2#HEg2<6Jeqg>BLCY`sXaH#z?MZvpy}1Nt{t3^Q-vIP)>`33or6OSIYA16ymi#)}Gkwmg2|DS1P*ZG^0@ z;xXb6tgO1vbA*d*Zjj4}bVXPzuDtl^(=L}ALRuM&bk1ar|B`fZ2e?F9y=Gzc;u7H% zr2nq=3sF6+Dr=jI+f1PMm+9u^Ae@5VG1_lhAWnc{s^d)ixN)!3526au^xextfCqB;FTB z^N1GdKYewVFYpl|>F7Cn>*Wu!{I{AigWVQrdN<*Zl$DO>_W@F73QHa}saCaePaw_? zEU4}ei@XIcaaRLQF1h^L^C#0EcpSBB0J7>VdNU8a-^nkS1t=ors{2vX#M9Z+Tl*kgisEYS`;sXp01B9@LLZ6KRnu$I*J~A zZj%h4>a?t5vzbxfPimh-Ii*8*07L~0Sifm^1+FJSiY z8LVygzVE%dWk2~RAp^G-rWLh*z#I*zh4w{<_mfK)+nzJq`h;#PwL~(xVV|^SMXjw8 z291Cb!53hfHR@N6c4t7WLJj0!xss0?*7R00zj^2fnX4v{$rr(MXG3ey#(X3d0izU@ zXi;*qm`Oaj#miatn8W$8Vo#B8vz_42i_nN$N^(T6MP?BobSmpt>0qnL($HVD{K@!sW)x zboi%Y{y{ku=@5O$)hH&;Wj`SPW>3)9JUR%6>pJ4T6{nAGS;kh~<2dcs!tdi?Vwd?P z5n?ak6{LAdHGI1uSVdfgWCyWF?jnX?#>4SNA0g%f0w08i?;Ol?%6_sfuAQHjvtyM@ z92IE_zx7jUprj7}nYXGAm~%`L4@AaKF7V!84M)pyuYkvu9hAmD!Y_^7mtzUDL9}}j z52l=y0cOEjfd4`*hX)w;>Ts(WvFG#Ayor=h*Bk~!E?T@?!Npzu64Q2|eGz=gBh=id zHI5=YGQVE2MQa$!+yESPG!P*MY{)bCOQh=2J{O-`%W3;(+FW*IB9`3dplkcj=~bzq zKV@`!HQKYaqv7pM7}LKwUaI79I-OJi47*yb@H2a8Ll5`iEU~`RGGsXqqH7U8ZQ zct~0WAIS~&>kqN^@lASeI$Y@a>PB8q*VrovwK%pp+p&AN0a-2&79E5^<(y#ecE-WB zE%x#Dg@{v_$X_P|X`1e()MQpu{oA_GORogIf+n!{uFO1ns{L%L6tm8$E`(XXtFOgQaBL-U;)p=|g?Y7EGN49l)M&;^qi!>b?xpQr2hx5InSQX^{&b8_NR5tPtB!7f8 z*^i&PZ8fDxT+^UV$ww!3s2IX(PKM2m%&wkUR1Y}bg;5)!NvlwT zzFdPcY_~3*Yr51fj^&%Ddhg>hI#SB zVf>wZ!_|MR?O%c^8GeP5Il6J>XuDPlxe>aw-Ta#_$@qyFb`^u%&LJa7a>J5CJg+R)e9qM_e9vxS5 z{;fT+`069ugcHpyxcV&vw)kZ^qm_ZPoNukdNF$i4jgl;pGpub=ZD@6LMC zD&o%H*CNI~P_HjQuny?(@mGi$q6?`}!&$2zo^ zEHq=g`4w+>N&;usoLqG^-ppBtMh!FADepog&T_s7w~F~@l7*$bbha2*Y5?8+Tj99_ z%8dnzgiIKH*{FkTI2H4>e3lbQK7CYi1@FD9cC@9oR2Yd^9cvXk$mc{dvi?bR_S%=y zLM30*-p@oR1(2r4-!uTpFncYVker$m7xlq8;akVr=xj3aRj(_*bxY1D zUx|0UTV4`UZD+EvQUb*O_w2T}*LEkBg$wxeQC2hcj9{zLUwE@hZqWAou#uC%M2bD@ zy4ML$DS*fv;|faF_Y`Rze)0AL?vlsD-!dQX=N6I<6b(E{doI=^+sdd(UuM%Uoen*h z3P{9yVz-EiAX+c?VcU42JkVaW#6=qc8MC8_bru`2oOnbhqcEVWJ%OwYuqlnJtS|}9 zdn~Z+hW-7CqeFcaWXp0bBgjGZ%ZXi-(QZ8Jh7`M1gNC#H-dwyBvVgDkrcmuTkalMZ z$D0-DSWRh-MQJL{#XjlnR3eX3G_3T1A>urDS!+b%-?>^1fWP28L8c#Nw5mL0cO%y) z^{DhN%f^QsXLakP(~i<+2MQ)DLZ{EnVT<)A7saoOoDjyG0T@JRTj-;tXFz5z;$hvfO354$(6&NuC%4`xNbRB>4G{~Mg32W1#7 z?S2)zA5W-bU2d992mZYwp?`$jktu?DHu?guSpWQYU#q4?G3$cMyDC4O5G$rj8erNZ zKntXNr&#+q^u&7(Bsm>_?!I;V6|8nJ^{0LCbC2{h2BNy>*s@_CAmv%dnh3UNAuw(5 zAEjM6bh~!|keyYodGACv&Geb=#-G^W)bu5?*0=@jt;=ZqdjLDn9g|R%c)_{S9s1|J?nA}U`Zqf(TL(%+?tT&=UJVI?JP{BGDqkO{`%`Omh?cHz-#su^l5Hm8M)H4Xo#a>BRGl~~ zx%+42{IQAc-?QK+$yMHq0sQ?!m_bvUWY?Y`Zpojm0YcqmklI1Y?0|HO_|NMuEqops zU{ZlbOqI#&R$=F|x0XcP)ZE;!Dht z@Cp*TpepQEvpy)1fn}_lG4i=|;N!e`_&H57< z_9Vm(CKYLU*j`=zt7q6pUHkM=z;$q9?|{BVOCrPyUPGsLIN49F1Zdk%?O@igi}`xD zzn9*?uuYei08^VjCROwAk?J17Am;MOyp_7Urv%pai298V6MkIrvz#^0GJPulaJD>z zZ@wPr@)c2;{sw|`=z^+_=zTHh^}q*lRTK0?i1s($&A=9A5&C{HIvGIc?#Q%?3*|rC zYZUE`uc2gOf&1SwI^@RgRFlWZ23c!5eD^7rDoYlI?GU!BvVV%#Om9N3g&@8CSZx>d-yv}}5?m`i_aas+Ho(ZbX&_+AN}U!e88x=^rYhuD1wvnOf58uDWrA0bbU zYH-H~>mUB2Odlf)hVBwopDKq&7O6DF@92{`49l-;tH%%dGZA+*${&w0d` zZrhBd^HU2b9T>mr-PW8xk!z1~LG^9W#5eDD)A4A2m2@!di(xp-1`#{Qf(;n!D=vYUL-*?L*kb07RgcpXw`;Al^>?h|UdJd^047>% zK=f)^9Rkc-u)*KQ!v&Qrx=uWcQLZUlM7$IO6PLAR5(sscz5?gaZ)^I-s*-L+@*VcZSDPXwK9jP_Q|;CkuEP~>6)a=6_#iVX5Oi4 z>Y&+#gL|#=?e2KSslV9@Fowu?Zk)eSGP@?O90=6CE-UsDsY7@hy~tz-pZc@4nvD7Z z#_mZw*ZbxRdL1uvQWJ^D@!VmwkmB~>p7FO@t12t5V2GM8{Zg@r${U_9fcGeJz$kFx z^Y$hgnYj}036-X7EfDP+J3XIr`QhlxJBH1pWi6-KCx3Kg{E*#~cxAzLfAG?Hlh&#i zZvYy?2%633gofvfz_gyK^7=*1jgm5Vd_SZ?>2a@AtG!>+ZXl^v1pX7B>p~Ia#Rl`{ z+5&ZVCsqF&(0A?ia&>n6oUHo8@4E>ONy4%&Q!+c+nvmx+!8sLr&>g<#VGWU*;)b@u zM&?o70IJR;K5a@pYu6@&I`#?4APRDa;Jq_5a+TR6@cX&$>=tkiXdN%NTBTAS}5$vs6! zg?m}CbgAda0w4D@9-pwb62v+zW#QBD+gY&{@p|x=(S&X%i9~Z4)&A&pqaLX$1Kyu; zwFj29qE%$UqN)YNc^j6U;P=hdHK#qTPe%n-NZnb^l$=`O6Jd7i!kG)f4eT+fcDr4m zi@ITRW=ChE@3ktlF%*}F`7XDdP^_AP^>O&b*o^gtTqVZWw(YCPIL3;Y#ZUC^X?f6D z0_Ez;6w>Q$RE$#tj|)(XphM5ZTiR)a@3Ho^HS9@I-Ka%*yOZwAxO0{I70I;5)7#EU zR#Ac}p0I5^ib{6v7+nMv)LLS|?ninwWs>AVe9j9}vk*7qC3-SZ@073<{(H^F>?aD( zRs8welq)7Rqjnh)JCL1wA*-pOIK2SGYs!S_v4|ccAkkIM9cKFr#;aoP3{|XV4*xfXXRj^ zZE#B%{8|AFW;-LsaZ?<`ovY0p;EO~-KDajaWPE)pGOF4lPRhKL`V@Q7gJ>udft;(8 zl3QwXMq%CUs(dZa*lON>ptMw1mZ79!I)c6UV=xqkHlK%Fa!HEy}sMue5Oo zwQ=Fu%HO*KtEk@eoxBI6?JdyF!BSm4>LC5O9q7h_yyukks&SL%15$c~C%MYPC)N9R zkq5Mo9Kj2R>)PT*eHgDwqzCGXe5-@Xj!HZBga)Ii{dHYS608j2A=)(?=#u}09Yf|$ zQy9V`-u@I6-;NU+b;u`_ht7p|QOh~3%s7q(exjaz;BkZ(i&Y>9pR2IR3B^}7m;yU? z8Rav2*Gik**>L2&H|2S)nFrQN(!|jyL^V1g;xt&&bqNJ9=23Fv9(~2IHZ&zq84nm} zPkHG`dvJaO{Zk|C&dQ+_z;@-%+}?fUNe5DQ#XAFiE6xtdjTv?-FO{QT32X)_sb!G$ zsvZUGr-k398A3vb_FEC@fUFvE8Hjv1yuAKGvo_Yo6Va8)ju1Z^!X(FZkxCsa;eG{o zxM3=MOBPvb4v0ssY~vn#MPd`9m?tC`8r&F|za$@tmqEsE-cEUM)q~|NhuKeJeaRFUHaq< zj7>wvqh@?ClP8?XKWI^XDf{}QJaTc+I?%7LXU!@aes@qPI`@Jkzy(qtrhODb64ecKcTek(3+jrEhnHoJ>rVmDWAwW z$L!F{LlT>?mlb@Eg*wp3FSO-w3r<{gtC~@x)ji6M_92J0R+1_OCXW`x#}#gq>?}D> z%kp!Hz*qb>&&M5MdxdKdh{{w*BUv(68FtO-s{Z|*P{at;i>r%JxCRN$4M z0z(TiJw}BC&prh8n#jA4?TS-`d7{%XevbY5kC~^#-t3_{ODdY zbn&HK#CJ#wXLp%DM@4mgwe-+Nbic9Rh6|7l%c+$Y%HX3eA1WDtF;)}aChPJfF$O8y zXfw(V#V4=tu603+s?w&&a#V$}ZR*Z?oZf8qYJ>k%T&tSy;ryuh84<3vqv%f+io&;; zEv!;IR&)4?mUy@yhu*f=T#8Qw2!arwu|XVq4Y>ZvEojD)qqVqt1bK2X#?x79omz0GU1<4MZOMns zTX*Ni52-`D+75Of1GF} zhBDScoFh+`JAu8=H?un4Z65b77~@Lz8yt^})1R6WaT!@Ls-94b@V!p&)pRkev%oU& zZ`dI4mjwVQQ0YFT{|$6cgjSR=f`TX{$VfdlCZu$0svANK&PtbE6lA*!`#gNxQu6v5 z7C)9k3b4#|0Kc}Wa5q@tTLkvw&)ue`&CkknXOHq?2XjcKtp`||;9@OlW;j}_mO86N}f^+f`AIU-`FJ7 zWS?r?2E?TuB!KL}W`|55dvM)3fiweTVqz55K?J01zM^_m|NgCh`=f>R8f3CI@fK8= zj=d0P*!!%Kr14F+o<7-iPl!2@%I8z)aq}YW6Qh~<=?`NskrI#ly?$KntLZOUVOm9- z@sTxmSY5`irqs>jl&KevJ~Y9FvO_IwAxSfj1@2w4FgPur?R4cJ1Z}%x( z(yj{OyVcj9R@?U4US~^+bc?mYH3AKg`!&*O44g}dVTGqAZ@)wz%{pj#%ec*<_D33l zVToyVZjG18lS)fxn8M8f4`BY)vDZA~Rva0ng(~o!JnXs+qBk0KTw==1il!%-$;1 zlvuorVMaK%}u*GUkQ4=>ft>r5=a--=KzxQJ_{#b|En7Mkd`_>8^+u2O4 ziOTC>yzEGh*Fp;RSg+)mHK~!5ygCoJ)!=8<`-*qc__W+xrtT3N(9TbKA6;*?igtsl zKdFYfvKUNfBak_^s7_t78ZC8+m;Z!o9ETi5CGTaV;$1oM6y$S+nPQT7@{cu{#~^rD+&U{q0fq1UFtB`Flt1Xaf~{?0dU8t6&(3<^0;@r7-HJv!Rv ze>ImS&z}6f-9}znIuvhXCH@pn-0aZGd;zB&?CaK0&p`_=c?EqW;4%>-FuHa~s+Vxu zEBs6anfRDcNrA(^%v9{nP@ZYPFT%hed)myVtL*mx=ftw}yJ z9AjI1V5J$!<#z*OdQ-h15yh<4%Q)i+KFjMSUnMoQ+Jfli{qn>1ZG9l?3*Q>A+fOyT)(}SN%gdtf#h^-PJA<)NC{!-cQ*`0t(5D7jHbqKd#VG1mDh5Djo zs>*VPctdmbiJuMlS#JztPkES+fAqyB4W{_`mDRk>VNI7}<7YGoQz_OabWBUUXq@B& z{W*Kfo9;~2B7R;b$wYC8x~1K(TzxL%0v(eZ2{anMjG!{&4@xGlq3EgDvH8oArtI{n z#MTNbt!!Bt_&VQD+fOvtOl3ri2oWpvvBQh!G#l7pUPuoL>3{^lk&;3ue3KWGN}OKt zp0>K#iMhH~`{(Xhq>iLf%7sl#eJJSEhVi!+3f%OQaG~&fpABzxef^Z1MEZ0Ywbh~ED<72VlZ`k|M^^NoAuwTK4f zFl0UHI9o2?v+ea}eg**&MS#dtAQM+k_x7KSfU6NCLdwzw{cJIT8T&P34IpPp)iDeH z9PxIkz2mTMi5pVRSNF|M+XO_pMa<Qmd0& zM#j$waQ4iW&S=lDOXp7!hu(Fc5i_KXpk$pfL}$Dn3X{Ft1pime*FVS(iR}YrCh3Y?%ievsaUT84DZgvMBfhVM7Cs+sddC z2+vVnYwkV~%m~uqd#GS~ivSAdp4Y`F^UyN+dW2cV(ca>d`Pq$;7|=phdp%2UXEY zWq+dL3w2ifuGy`Wz}Gq}FcS`N@i!1Rf3#J9k#dRcUMA?Xj9x+COuMrT-X z<9%?v2PwVi4ShS`tR?w_QaaZ;3?M7H{+02KU?TTFg|4{2qUsyTYZ3fUp!@%( zuJBmE2>m;rwT?dhlkolti>UcOa9HDvM6B1^WoKvjMqbYN+i&S*VCr+t^2USV&Z~FQ zN$>G*{+wNZ@;lhMS!=L$2r}E_+n?`_Eb}A%^{2-ambNR(R!+ZAlqF9~;HRJTtG(YZ z4iIe+UBA4sEdXPaU{h3!dth?izm0mh_)*^JsjBajv(^?ntDL;guYZBGvGaKV-SjL% zL&)cHrQjNS21ITBUR^@32|xX7!I3~IEm){Pc1|H2_N&S6$8M~b<2ToB3u6jVNE`sJ zfb5sfhHm?dyoM@+&dlCOSgqr9fCk=(E&jC81A5XMOyZ{v{~Nl!ejh;48Y!AY#ywec^G_szx7L0;eAi34uZ8wBs+go50Q2k#lJJ?kBR+<(ufb&B$YP&l-# zH+YE?Q*?R$aLP|Th&5LL{`J!j*T=Ipr&s)C(rfp0qN2fBlxuI+KW$Sf{AJreFCE_d jYfE$efrdMY9X}xbp 文档中会出现以下注释符号,代表不同的使用场景和提示程度。如果需要提示用户注意的信息,可以根据重要程度选择对应的注释符号。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

符号

-

说明

-

引用方法

-

-

表示如不避免则将会导致死亡或严重伤害的具有高等级风险的危害。

-
>![](public_sys-resources/icon-danger.gif) **危险:**      
->正文内容
-

-

表示如不避免则可能导致死亡或严重伤害的具有中等级风险的危害。

-
>![](public_sys-resources/icon-warning.gif) **警告:**      
->正文内容
-

-

表示如不避免则可能导致轻微或中度伤害的具有低等级风险的危害。

-
>![](public_sys-resources/icon-caution.gif) **注意:**      
->正文内容
-

-

用于传递设备或环境安全警示信息。如不避免则可能会导致设备损坏、数据丢失、设备性能降低或其它不可预知的结果。

-

“须知”不涉及人身伤害。

-
>![](public_sys-resources/icon-notice.gif) **须知:**      
->正文内容
-

-

对正文中重点信息的补充说明。

-

“说明”不是安全警示信息,不涉及人身、设备及环境伤害信息。

-
>![](public_sys-resources/icon-note.gif) **说明:**      
->正文内容
-
- +![](figures/note.png) ## 链接 -- Gitee From 6ed190ff89db9a7867e2bb8c05d39680889d250f Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:28:20 +0000 Subject: [PATCH 098/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Description2.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Description2.png | Bin 1722 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Description2.png diff --git a/contribute/figures/Description2.png b/contribute/figures/Description2.png deleted file mode 100644 index 3aa7f168714924cf9f87a47191bbc1b7339458f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1722 zcmeAS@N?(olHy`uVBq!ia0vp^en2e4!OXzG*l+6T3gj>r2e~^jtUD+363Agmcl32+ zVA$Bt{U?!?fq`jdfKLcW5dk0|z|X+IM?eusnjMJP*?HN4GzhSHz3p5<=RFK2K&VU;TWI!B-EP}>{=z=%{*)b4ha7%#1iTp1*kAX0D=E{m)Y zO%|vIXk*CPYF(hjgOVV>UAF>wh=DQOu6MI}{LHFYg5Ep1%` zBO?=2Gjj_|D{EUjdj|&>S2uSLPcLuZfWW|@py1H(@QBFRxcG$3tn8fJ-28&V!lL4m z($cc>ipr|$n%cVh`i6$)=9c!3uI|462@|JGnL2&O>^XDiE?Br|$KIVxoh|Cz5DjWe*MPHTeoiCzJ2H3 z{re9dK6?E4$&;tgo;`o@^3|)?Z{ECp`|kbw_a8of`uyeV_a8rh{`&pr@4tUrO)Ehe zjoo{7Hg)qx0dws-PZ!4!3;(xMeun!bN*v!Gd?-Szn!|Nrt4UhQ$$4vA zW=u)xx^rThu2AbH*C`$=awewSH(Ka+DM>_inabn6pQl&6e>CIel{qqf@^kFI&v{;X z@BQC-&-c8y{a$-v(ureEN+Ess$||i}H;GnF^H|_)8t%22(P@5}B5SF2+0@9R4vSBU zy0#@svK1Vxys;oc-|q!+@8LG=lJ#HMFlthPm)W@n_Q6aVD9e24U#2^ zzA9GHTiLIPnEEWbA6W3=3CraNmW^!7g{1a~UA$h^Qkg9(ec^zli%;$Rj{7DTyceue zDk`1TSI#lxmrjTL+vSgc{d`kw`dqtzv$jOS%2Vozp4`%v?GAoNH-B$m=70C|yPwRj zHY=U}8mpDO=i0fV1?>iQ$7R|Q56Ra@xL&Twi&Z{)QP@O%SHHgB!xp}Orp5YqPy5)1 z2JTALU|YNU>(56oi~HmBgySOb_q}cTVO6cLux3;10>;1MENm<~U%v}XUnY|rULf3P z^!rrO!iLEY-OBa6+rrJyf39`h_H5#k191&rv*)`viL8G#H9jS}fAyyK@e+w??rPsF6Qrc)sHDcfzGHc^%-r+c l^QC$ Date: Fri, 5 Aug 2022 07:28:27 +0000 Subject: [PATCH 099/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/Warnings2.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/Warnings2.png | Bin 1125 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/Warnings2.png diff --git a/contribute/figures/Warnings2.png b/contribute/figures/Warnings2.png deleted file mode 100644 index 5daec9520108da4e48c154838015df05d2557070..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1125 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAud@ma}qQuVo1yDbNHen~>ubALN=86EL+iSx#2=Os?#? zIQE5JLS^QnLfl+t3SvrPLK_14oirpxd3ja^iyJA3P4$(HFqD=OC~tqWs!6&i{1 za@(m(>dT9%iVFo8$jAxvnW)ML3kmAWOY~=YoLU#KU{Z2?u$zXIh^iRBzO;~p01qD* zCqFNjtPr1^uz;1Sq>Ym3>X`}43LJPjIfQw*+TCP!M2iY?b6F~hwWRwf$jjf@W-HFi zEh)&WBr2dGDa^*ft|cX`Ai{rflShcQn2U;tydXCR3rm2u_#_u$O>zESSBbblmta4) z4u9411n=45%K4e$Czji+n&`GDRJOA|(bGzShl_pR9D{~*?HD6TVCaRm?vV#l1tmd# z!T;$C7`7)ST>{$8S>O>_%)r3)8iW~}x_P4*7?_kiT^vI!{NGLu?3OYVIKEtu@$E|f zslMXRf0eQLy`Js(yI_O9*t($B%9U{uUEQa)Zn^(|>;II;mD+LZFYFU}w>@Xh%$AcW z>1si};VzeAStq7HS;6xtQt#xcTindc-o}&|*c~qFIJk3n$dM4Sqzel!N$h%+a`D@7 zpO1O0i8^yxRxTA$7dtt5lg{zPUk9EX(2)A) zt#?RszU#-`UMEz~uMdbw`8daDW?e?urQSOp>uxVOe(cv(Q?c5k%?heYQESvv|7=?2 z&X+TRF;6wFq*!qF`IkPMGLF~C7P~Ulgh-uqVzoK6$Ru!H@E4^!op*k|G@N#oZ{nGn z=RcOl6(5s$;~A;$n|*K6j31uLQgIeWSuIok3Y(psc2u=^No+}MxcBq3w_LqfaYx;p zJj>#E!ihg|SF21*7i~?Ea?SWEcF*-#@|4BudY0Zv(X~s{g1;I{IV@arx>SGnUzX(; z_Ago$Xl2H`*?;l_r>4zf@5PT-uZumA)m!a;a+N^1z@b$aDqgkzoiXv%;~<^YU-x0HVv&3aw#Y_=-d!ta;hg{bVeSRhe+N_ikDEs7G*6#@ z|1kgiRnOSBZ@YfFN}?Pum#<=O1CtPgr>mdK II;Vst0JszNk^lez -- Gitee From 1c567814f20af0c239b8898abcccb10150711ffd Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:28:35 +0000 Subject: [PATCH 100/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/dangerous2=20-=20=E5=89=AF=E6=9C=AC.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dangerous2 - \345\211\257\346\234\254.png" | Bin 1075 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 "contribute/figures/dangerous2 - \345\211\257\346\234\254.png" diff --git "a/contribute/figures/dangerous2 - \345\211\257\346\234\254.png" "b/contribute/figures/dangerous2 - \345\211\257\346\234\254.png" deleted file mode 100644 index 575bafbc1c7812a8a792ae3caca1ac38ec02d783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 -- Gitee From 7f1b408b3838a4b055ea3a64fd7c339518a98e0d Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:28:41 +0000 Subject: [PATCH 101/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/dangerous2.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/dangerous2.png | Bin 1075 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/dangerous2.png diff --git a/contribute/figures/dangerous2.png b/contribute/figures/dangerous2.png deleted file mode 100644 index 575bafbc1c7812a8a792ae3caca1ac38ec02d783..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1075 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu;j{`39IuMcky z*%+USay#a2vtLvD`|}4sUOwsxcD=aC!)u`sQmWi_V3T{Plmfx zhkLJ{nc!q=ksjpn^Zl!@k8YmNkGwmx`R}ivC)NgTT^Rdl^^Cv2e_e0MeShiLVQZrc zc@e+Aetdm&TT)CwjIZmTZ=e7F`?r62`1^}T{`~m%<^DB4XSau>)MM>O7sN1eabNP<9e8D`MMFmQ!X#JKTmSz5 zzj%G)$`g74Rcmg!dl@D7=cMoR$xjTrdOd29``@6G&v!JhOyu~aJkjV@f827_gx3ZW zzwN%Td285(X*Z&de_N*N9CZ5@)5R+=J_0Toyynj%*DS|-l#{OoaM8#@%p>(!fi!O2l8ds z)Mi+z78Q5(beh@}9jXYMsB$j8UVo8b%W9S8ya^u0yBm}pSNW{Hn0vc*`V=p27N%=U zU%A)4IdP~f@pgBihwR$O?5|g~8<&b|OE+ch*yCPwIBWj()l7|1QMVn z|F9lQG7)+7GBQL~X+lxUDT|;a!^4uRXS`6gDm!6pGVzJFqT34})8m=VLaPgAU7XqF zy}7UFXVd+?4$gNJD_bQV+_la1&NDPgoig)s!TJ?Cr;^NS&)qp-IcZ(=>3#clZJ*n| ziLLreh+E=o-}?nU(d>3Qm7CoDvUQj1JiDs&?Kl7b*fweIb@z5I`nEvmZm;;3RVU{t ozT~_Ap;Bzwz0_0oJQw}BcUh}UTC{UFFflQBy85}Sb4q9e0KkGn1^@s6 -- Gitee From 786e98bbc6782d8d97790842a7252925da29416a Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:28:47 +0000 Subject: [PATCH 102/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/note.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/note.png | Bin 78117 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/note.png diff --git a/contribute/figures/note.png b/contribute/figures/note.png deleted file mode 100644 index 149f800b20ab71c7d9e17dfc983709fdc7007f66..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 78117 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

e^Qr>V`eFgV^(e@oa$lqM?OO}qNFdarEcaLe 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�E5LCz3*&= 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 jYfE$efrdMY9X}xbp Date: Fri, 5 Aug 2022 07:28:53 +0000 Subject: [PATCH 103/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/note2.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/note2.png | Bin 1143 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/note2.png diff --git a/contribute/figures/note2.png b/contribute/figures/note2.png deleted file mode 100644 index 0644ab8fb5b2d45425c6e0d62030c90888f2a037..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1143 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAu`j$s^(WofW_xjy$BLOrx+)TK;-U}tC@4vZC`yO~xoCLUstfaRt4d2e zJnXPwQu2eH`cpfTtqm2WMEEom#Q3;4MFn{GFS0V$lrhy&6zAm@;^vYP;FS{OSCbLd zSCiR0N2Mq`+{xDB#M;2E3uAkm6TEDd#Y9E=tE`vx*+>fWDM<@Cn=A42a5v_eZJVL5 zATH!?rL3(aE-fm+$IG1@7mySaAR{4ubBDgBy!ig*;j4Sq)5CO}?JR3bVnY1gWJUO= z)mub(=^1OuX(>w8m&fd!?|ovq&GF@WW;(J0{9Kw!A|iY|^ID8o&rCSK+CWKGIM!dU zy~sGqTfH(>pP!pkRz%3tN+H=_O-ET$RaRVBNKj5(@W7hrl0<{q{Yk)J6!4q_iiv`f zAiv=M^aTvt6O%3h?dB}-h%9Dc;Cc9u)A;wl{esQ%eQPJ|X#Ey+qFCbWz9_fd z)|-`I7;JuaaOaQCvv+ppD;?n3nzp=uf~MErD!Dlu6ax%=h1N3|*sThe#a?Zj zni9j?up~{_b3$4TDv>O_#asBVU8;O5BJk%Xcfj*!X+Yz`u zdU46A)7B4*nv**3&$VZ>?)A@`w=DBU!*X*+m3v(qm{+}Cwo?4?#7Zg2d37nzCKNs6 zdsF}P(A!VjMXqlL}UsqcQ^Z(u}&OasSf%x;l z(+k&5R`oP1y~J&)$2#p^yo8Ziq*?ee@5TtFX&rhT1t#Cke4nphR+#yYXVI3OS>L`+ zxXks;a@OnFXZ#C7rtY;={Hm+5^{!S$mymCao_o^E2Y1*XHYapxBU+z2Isz<9uUN03P6>9-R*w6{lh%WCC$1a)w&_M3mX#k5>5t8HsE=fz&-#m3x|U3)6@bENl) zg$hXeCcit`|Jr?PX+5*}n^SDBzwG6keJ8d>{`<9KN4=N6|6?cGdT!RtX$nhsKh#+I zJ*qC!O>ahB8UGpchpb;4`%hlDH7}4&*R^-y>da%|vHOL6p9QV^^EY`-_>TXt*<%^% a7|*ihn7`lE{tB3=7(8A5T-G@yGywoAWd2D2 -- Gitee From 7318ee07fa469bbdd370d2c63a81efcae9628f16 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 5 Aug 2022 07:28:59 +0000 Subject: [PATCH 104/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?contribute/figures/notice2.png?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/notice2.png | Bin 693 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 contribute/figures/notice2.png diff --git a/contribute/figures/notice2.png b/contribute/figures/notice2.png deleted file mode 100644 index cc2cc962c775ce22ef8dccc06d0d78815463229b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 693 zcmeAS@N?(olHy`uVBq!ia0vp^K0qwP!OXzG*nMDT1(3s79OUlAuD{LvSMI&J_2~WDL${}Gx*%S# z^y%x*KY#!I{`1eP_um%oyt@DVqtD-d{r>asV_ zhi~3bYNV#W@V<5J$L15RmQ8akCLY};cp!GxcU}F8Wfx{_ZY`X5`>D?7Q;Dxs|D`rf z6?E1-us|sM{yeLVaUnW7r`v3*U1uNB)Up(v)lj|vXg!;7bA@2G{@ss)SC$qpy`i`z zEbqo#wZ)BnUp2O$I?&8-ylT(7X;(v5s~xWjyC2le8Z@D6m5P6yF!$1li<55zygwKp zyx?Xk*RJ;;CjVPx;CkEku Date: Fri, 5 Aug 2022 07:29:56 +0000 Subject: [PATCH 105/130] =?UTF-8?q?update=20contribute/=E5=86=99=E4=BD=9C?= =?UTF-8?q?=E8=A7=84=E8=8C=83.md.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- contribute/figures/SafetyAlert.png | Bin 0 -> 67456 bytes ...\231\344\275\234\350\247\204\350\214\203.md" | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 contribute/figures/SafetyAlert.png diff --git a/contribute/figures/SafetyAlert.png b/contribute/figures/SafetyAlert.png new file mode 100644 index 0000000000000000000000000000000000000000..0f672abbd6d2bba5621632e953d423f06db72789 GIT binary patch literal 67456 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 LjdTic*@XTNA)fuh literal 0 HcmV?d00001 diff --git "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" index 99957fdf3..7fd09dbfb 100644 --- "a/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" +++ "b/contribute/\345\206\231\344\275\234\350\247\204\350\214\203.md" @@ -104,7 +104,7 @@ docs文件夹中包含以下内容: ## 注释符号 文档中会出现以下注释符号,代表不同的使用场景和提示程度。如果需要提示用户注意的信息,可以根据重要程度选择对应的注释符号。 -![](figures/note.png) +![](figures/SafetyAlert.png) ## 链接 -- Gitee From 72f18d7b1cc4110437c03df4f15f2ab3b8c4b11e Mon Sep 17 00:00:00 2001 From: Jiajie Li Date: Mon, 8 Aug 2022 10:09:08 +0800 Subject: [PATCH 106/130] StratoVirt: update bootindex usage Signed-off-by: Jiajie Li --- docs/en/docs/StratoVirt/VM_configuration.md | 7 ++++--- ...232\346\213\237\346\234\272\351\205\215\347\275\256.md" | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/en/docs/StratoVirt/VM_configuration.md b/docs/en/docs/StratoVirt/VM_configuration.md index d565a4aa1..bd7c236c4 100644 --- a/docs/en/docs/StratoVirt/VM_configuration.md +++ b/docs/en/docs/StratoVirt/VM_configuration.md @@ -106,7 +106,8 @@ VM disk configuration includes the following configuration items: - **if** (optional): driver type. The default value is **none**. The block device is **none**. - **bus**: bus to which the device is to be mounted. - **addr**: IDs of the slot and function to which the device is to be mounted. -- **multifunction** (optional): whether to enable PCI multi-function. +- **multifunction** (optional): whether to enable PCI multi-function. +- **bootindex** (optional, only for standard machine): set the boot order of block device. If not set, the priority is lowest. The number ranges from 0 to 255, the smaller the number, the higher the priority. #### Disk Configuration Modes @@ -123,7 +124,7 @@ The standard VM configuration format is as follows: ``` -drive id=drive_id,file=path_on_host[,readonly=off][,direct=off][,throttling.iops-total=200][,if=none] --device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,][serial=serial_num][,multifunction=on] +-device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,][serial=serial_num][,multifunction=on][,bootindex=1] ``` The following describes the **throttling.iops-total** and **iothread** configuration items: @@ -249,7 +250,7 @@ A serial port is a VM device used to transmit data between hosts and VMs. To use Or: ``` --chardev backend[,path=path,server,nowait] +-chardev backend[,path=path,server,nowait] ``` ### Console Device Configuration diff --git "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" index fd98b1fd1..9ca583e37 100644 --- "a/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/StratoVirt/\350\231\232\346\213\237\346\234\272\351\205\215\347\275\256.md" @@ -108,6 +108,7 @@ StratoVirt 能够运行的最小配置为: - bus:设备要挂载的bus。 - addr:设备要挂载的slot和function号。 - multifunction:是否开启pci多功能。(可选配置) +- bootindex:配置启动优先级属性,如果没有设置,默认最低优先级。配置范围从0到255,数字越小,优先级越高。(可选配置,只支持标准机型) #### 磁盘配置方式 @@ -124,7 +125,7 @@ StratoVirt 能够运行的最小配置为: ``` -drive id=drive_id,file=path_on_host[,readonly=off][,direct=off][,throttling.iops-total=200][,if=none] --device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,][serial=serial_num][,multifunction=on] +-device virtio-blk-pci,drive=drive_id,bus=pcie.0,addr=0x3.0x0[,iothread=iothread1,][serial=serial_num][,multifunction=on][,bootindex=1] ``` 下面对throttling.iops-total和iothread两个配置项进行详细说明: @@ -250,7 +251,7 @@ iothread配置细节见[iothread配置](#iothread配置) 或者: ``` --chardev backend[,path=path,server,nowait] +-chardev backend[,path=path,server,nowait] ``` ### console 设备配置 -- Gitee From 775cdd31ed6e98a1f3cfd9dedb946073f8c4ce5f Mon Sep 17 00:00:00 2001 From: z30023234 Date: Wed, 10 Aug 2022 09:38:55 +0800 Subject: [PATCH 107/130] Fix 404's link --- docs/en/docs/secGear/secGear-development-guide.md | 2 +- ...1secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/docs/secGear/secGear-development-guide.md b/docs/en/docs/secGear/secGear-development-guide.md index 442e4136f..d43662b51 100644 --- a/docs/en/docs/secGear/secGear-development-guide.md +++ b/docs/en/docs/secGear/secGear-development-guide.md @@ -412,7 +412,7 @@ Applications developed using secGear comply with the following unified directory Copy the device public key file rsa_public_key_cloud.pem to the enclave directory. The device public key is used to encrypt the dynamic library in the security zone by using the temporarily generated AES key. - Note: The rsa_public_key_cloud.pem file is downloaded from . + Note: The rsa_public_key_cloud.pem file is downloaded from . 7. Compile the program. diff --git "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" index f74da9fee..25436626d 100644 --- "a/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" +++ "b/docs/zh/docs/secGear/\345\274\200\345\217\221secGear\345\272\224\347\224\250\347\250\213\345\272\217.md" @@ -419,7 +419,7 @@ 将设备公钥文件 rsa_public_key_cloud.pem 复制到 enclave 目录。此处的设备公钥用于使用临时生成的 aes 密钥对安全区动态库进行加密。 - 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/itrustee_sdk/blob/master/build/signtools/cloud/rsa_public_key_cloud.pem + 说明:rsa_public_key_cloud.pem 文件下载路径:https://gitee.com/openeuler/itrustee_sdk/blob/master/build/signtools/rsa_public_key_cloud.pem -- Gitee From ef6c4e42a5fc78b69f4b87f96be87676cce0a4b5 Mon Sep 17 00:00:00 2001 From: Zhang Yang Date: Wed, 10 Aug 2022 16:06:43 +0800 Subject: [PATCH 108/130] StratoVirt: introduce free page reporting of balloon Signed-off-by: Zhang Yang --- docs/en/docs/StratoVirt/VM_configuration.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/en/docs/StratoVirt/VM_configuration.md b/docs/en/docs/StratoVirt/VM_configuration.md index bd7c236c4..3b14ec577 100644 --- a/docs/en/docs/StratoVirt/VM_configuration.md +++ b/docs/en/docs/StratoVirt/VM_configuration.md @@ -458,20 +458,21 @@ During running of a VM, the balloon driver in it occupies or releases memory to Lightweight VMs: ``` --device virtio-balloon-device,deflate-on-oom=true +-device virtio-balloon-device[,deflate-on-oom=true|false][,free-page-reporting=true|false] ``` Standard VMs: ``` --device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0,deflate-on-oom=true[,multifunction=on] +-device virtio-balloon-pci,bus=pcie.0,addr=0x4.0x0[,deflate-on-oom=true|false][,free-page-reporting=true|false][,multifunction=on|off] ``` ![](./public_sys-resources/icon-note.gif)**NOTE** 1. The value of **deflate-on-oom** is of the Boolean type, indicating whether to enable the auto deflate feature. When this feature is enabled, if the balloon device has reclaimed some memory, it automatically releases the memory to the guest when the guest requires the memory. If this feature is disabled, the memory is not automatically returned. -2. When running the QMP command to reclaim the VM memory, ensure that the VM has sufficient memory to keep basic running. Otherwise, some operations may time out and the VM cannot apply for idle memory. -3. If the huge page feature is enabled in the VM, the balloon device cannot reclaim the memory occupied by the huge pages. +2. The value of **free-page-reporting** is of the Boolean type, indicating whether to release free pages from kernel reporting. This feature can be used to reuse memory. +3. When running the QMP command to reclaim the VM memory, ensure that the VM has sufficient memory to keep basic running. Otherwise, some operations may time out and the VM cannot apply for idle memory. +4. If the huge page feature is enabled in the VM, the balloon device cannot reclaim the memory occupied by the huge pages. > If **deflate-on-oom** is set to **false**, when the guest memory is insufficient, the balloon device does not automatically release the memory. As a result, the guest OOM may occur, the processes may be killed, and even the VM cannot run properly. -- Gitee From 190f0b9cfff7142325ab35392570023143c9e334 Mon Sep 17 00:00:00 2001 From: wu-changsheng Date: Tue, 9 Aug 2022 19:46:48 +0800 Subject: [PATCH 109/130] fix doc describe err --- docs/zh/docs/Gazelle/Gazelle.md | 115 +++++++++++++++++--------------- 1 file changed, 62 insertions(+), 53 deletions(-) diff --git a/docs/zh/docs/Gazelle/Gazelle.md b/docs/zh/docs/Gazelle/Gazelle.md index 3c1487c69..d65ef9bf6 100644 --- a/docs/zh/docs/Gazelle/Gazelle.md +++ b/docs/zh/docs/Gazelle/Gazelle.md @@ -13,7 +13,6 @@ Gazelle是一款高性能用户态协议栈。它基于DPDK在用户态直接读 ## 安装 配置openEuler的yum源,直接使用yum命令安装 ```sh -#dpdk >= 21.11-2 yum install dpdk yum install libconfig yum install numactl @@ -21,17 +20,19 @@ yum install libboundscheck yum install libpcap yum install gazelle ``` +>说明: +dpdk >= 21.11-2 ## 使用方法 配置运行环境,使用Gazelle加速应用程序步骤如下: ### 1. 使用root权限安装ko 根据实际情况选择使用ko,提供虚拟网口、绑定网卡到用户态功能。 若使用虚拟网口功能,则使用rte_kni.ko -``` sh +```sh modprobe rte_kni carrier="on" ``` -网卡从内核驱动绑为用户态驱动的ko,根据实际情况选择一种 -``` sh +网卡从内核驱动绑为用户态驱动的ko,根据实际情况选择一种。 +```sh #若IOMMU能使用 modprobe vfio-pci @@ -42,11 +43,13 @@ modprobe vfio-pci #其它情况 modprobe igb_uio ``` +>说明: +可根据机器BIOS配置,查看是否使能IOMMU。 ### 2. dpdk绑定网卡 将网卡绑定到步骤1选择的驱动。为用户态网卡驱动提供网卡资源访问接口。 -``` sh +```sh #使用vfio-pci dpdk-devbind -b vfio-pci enp3s0 @@ -57,33 +60,34 @@ dpdk-devbind -b igb_uio enp3s0 ### 3. 大页内存配置 Gazelle使用大页内存提高效率。使用root权限配置系统预留大页内存,可选用任意页大小。因每页内存都需要一个fd,使用内存较大时,建议使用1G的大页,避免占用过多fd。 根据实际情况,选择一种页大小,配置足够的大页内存即可。配置大页操作如下: -``` sh +```sh #配置2M大页内存:在node0上配置 2M * 1024 = 2G echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages #配置1G大页内存:在node0上配置1G * 5 = 5G echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages - -#查看配置结果 -grep Huge /proc/meminfo ``` +>说明: +cat查询实际预留页个数,连续内存不足时可能比预期少 ### 4. 挂载大页内存 创建两个目录,分别给lstack的进程、ltran进程访问大页内存使用。操作步骤如下: -``` sh -mkdir -p /mnt/hugepages -mkdir -p /mnt/hugepages-2M -chmod -R 700 /mnt/hugepages -chmod -R 700 /mnt/hugepages-2M -mount -t hugetlbfs nodev /mnt/hugepages -o pagesize=2M -mount -t hugetlbfs nodev /mnt/hugepages-2M -o pagesize=2M +```sh +mkdir -p /mnt/hugepages-ltran +mkdir -p /mnt/hugepages-lstack +chmod -R 700 /mnt/hugepages-ltran +chmod -R 700 /mnt/hugepages-lstack + +mount -t hugetlbfs nodev /mnt/hugepages-ltran -o pagesize=2M +mount -t hugetlbfs nodev /mnt/hugepages-lstack -o pagesize=2M ``` +>说明: +/mnt/hugepages-ltran和/mnt/hugepages-lstack必须挂载同样pagesize大页 ### 5. 应用程序使用Gazelle 有两种使用Gazelle方法,根据需要选择其一 -- 重新编译应用程序,链接Gazelle的库 -修改应用makefile文件链接liblstack.so,示例如下: -``` +- 重新编译应用程序,替换sockets接口 +```sh #makefile中添加Gazelle的Makefile -include /etc/gazelle/lstack.Makefile @@ -91,9 +95,9 @@ mount -t hugetlbfs nodev /mnt/hugepages-2M -o pagesize=2M gcc test.c -o test ${LSTACK_LIBS} ``` -- 使用LD_PRELOAD加载Gazelle的库 +- 使用LD_PRELOAD加载Gazelle库 GAZELLE_BIND_PROCNAME环境变量指定进程名,LD_PRELOAD指定Gazelle库路径 -``` +```sh GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test ``` @@ -102,21 +106,22 @@ GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test |选项|参数格式|说明| |:---|:---|:---| -|dpdk_args|--socket-mem(必需)
--huge-dir(必需)
--proc-type(必需)
--legacy-mem
--map-perfect
等|dpdk初始化参数,参考dpdk说明| +|dpdk_args|--socket-mem(必需)
--huge-dir(必需)
--proc-type(必需)
--legacy-mem
--map-perfect
-d|dpdk初始化参数,参考dpdk说明
--map-perfect为扩展特性,用于防止dpdk占用多余的地址空间,保证ltran有额外的地址空间分配给lstack。
-d参数加载指定so库文件| +|listen_shadow| 0/1 | 是否使用影子fd监听。单listen线程,多协议栈线程时是能| |use_ltran| 0/1 | 是否使用ltran | |num_cpus|"0,2,4 ..."|lstack线程绑定的cpu编号,编号的数量为lstack线程个数(小于等于网卡多队列数量)。可按NUMA选择cpu| |num_wakeup|"1,3,5 ..."|wakeup线程绑定的cpu编号,编号的数量为wakeup线程个数,与lstack线程的数量保持一致。与numcpus选择对应NUMA的cpu。不配置则为不使用唤醒线程| |low_power_mode|0/1|是否开启低功耗模式,暂不支持| |kni_swith|0/1|rte_kni开关,默认为0。只有不使用ltran时才能开启| -|host_addr|"192.168.xx.xx"|协议栈的IP地址,必须和redis-server配置
文件里的“bind”字段保存一致。| +|host_addr|"192.168.xx.xx"|协议栈的IP地址,也是应用程序的IP地址| |mask_addr|"255.255.xx.xx"|掩码地址| |gateway_addr|"192.168.xx.1"|网关地址| |devices|"aa:bb:cc:dd:ee:ff"|网卡通信的mac地址,需要与ltran.conf的bond_macs配置一致| lstack.conf示例: -``` conf -dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-2M", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] +```sh +dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] use_ltran=1 kni_switch=0 @@ -134,23 +139,23 @@ devices="aa:bb:cc:dd:ee:ff" - ltran.conf用于指定ltran启动的参数,默认路径为/etc/gazelle/ltran.conf。使用ltran时,lstack.conf内配置use_ltran=1,配置参数如下: -|功能分类|选项|参数格式|说明| -|:---|:---|:---|:---| -|kit|forward_kit|"dpdk"|指定网卡收发模块。
保留字段,目前未使用。| -||forward_kit_args|-l
--socket-mem(必需)
--huge-dir(必需)
--proc-TYPE(必需)
--legacy-mem(必需)
--map-perfect(必需)
等|dpdk初始化参数,参考dpdk说明。
注:--map-perfect为扩展特性,用于防止dpdk占用多余的地址空间,保证ltran有额外的地址空间分配给lstack。| -|kni|kni_switch|0/1|rte_kni开关,默认为0| -|dispatcher|dispatch_max_clients|n|ltran支持的最大client数。
1、多进程单线程场景,支持的lstack实例数不大于32,每lstack实例有1个网络线程
2、单进程多线程场景,支持的1个lstack实例,lstack实例的网络线程数不大于32| -||dispatch_subnet|192.168.xx.xx|子网掩码,表示ltran能识别的IP所在子网网段。参数为样例,子网按实际值配置。| -||dispatch_subnet_length|n|子网长度,表示ltran能识别的子网长度,例如length为4时,192.168.1.1-192.168.1.16| -|bond|bond_mode|n|bond模式,目前只支持Active Backup(Mode1),取值为1| -||bond_miimon|n|bond链路监控时间,单位为ms,取值范围为1到2^64 - 1 - (1000 * 1000)| -||bond_ports|"0xaa"|使用的dpdk网卡,0x1表示第一块| -||bond_macs|"aa:bb:cc:dd:ee:ff"|绑定的网卡mac地址,需要跟kni的mac地址保持一致| -||bond_mtu|n|最大传输单元,默认是1500,不能超过1500,最小值为68,不能低于68| +|选项|参数格式|说明| +|:---|:---|:---| +|forward_kit|"dpdk"|指定网卡收发模块。
保留字段,目前未使用。| +|forward_kit_args|-l
--socket-mem(必需)
--huge-dir(必需)
--proc-TYPE(必需)
--legacy-mem(必需)
--map-perfect(必需)
-d|dpdk初始化参数,参考dpdk说明。
--map-perfect为扩展特性,用于防止dpdk占用多余的地址空间,保证ltran有额外的地址空间分配给lstack。
-d参数加载指定so库文件| +|kni_switch|0/1|rte_kni开关,默认为0| +|dispatch_max_clients|n|ltran支持的最大client数。
lstack的协议栈线程总数不大于32| +|dispatch_subnet|192.168.xx.xx|子网掩码,表示ltran能识别的IP所在子网网段。参数为样例,子网按实际值配置。| +|dispatch_subnet_length|n|子网长度,表示ltran能识别的子网长度,例如length为4时,192.168.1.1-192.168.1.16| +|bond_mode|n|bond模式,目前只支持Active Backup(Mode1),取值为1| +|bond_miimon|n|bond链路监控时间,单位为ms,取值范围为1到2^64 - 1 - (1000 * 1000)| +|bond_ports|"0x01"|使用的dpdk网卡,0x1表示第一块| +|bond_macs|"aa:bb:cc:dd:ee:ff"|绑定的网卡mac地址,需要跟kni的mac地址保持一致| +|bond_mtu|n|最大传输单元,默认是1500,不能超过1500,最小值为68,不能低于68| ltran.conf示例: -``` conf -forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages --proc-type primary --legacy-mem --map-perfect --syslog daemon" +```sh +forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages-ltran --proc-type primary --legacy-mem --map-perfect --syslog daemon" forward_kit="dpdk" kni_switch=0 @@ -171,12 +176,12 @@ tcp_conn_scan_interval=10 - 启动ltran进程 单进程且网卡支持多队列,则直接使用网卡多队列分发报文到各线程,不启动ltran进程,lstack.conf的use_ltran配置为0. 启动ltran时不使用-config-file指定配置文件,则使用默认路径/etc/gazelle/ltran.conf -``` sh +```sh ltran --config-file ./ltran.conf ``` - 启动应用程序 启动应用程序前不使用环境变量LSTACK_CONF_PATH指定配置文件,则使用默认路径/etc/gazelle/lstack.conf -``` sh +```sh export LSTACK_CONF_PATH=./lstack.conf LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf ``` @@ -185,11 +190,11 @@ LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-ser Gazelle wrap应用程序POSIX接口,应用程序无需修改代码。 ### 9. 调测命令 -- 不使用ltran模式时不支持gazellectl ltran xxx命令,以及lstack -r命令 -``` +- 不使用ltran模式时不支持gazellectl ltran xxx命令,以及gazellectl lstack show {ip | pid} -r命令 +```sh Usage: gazellectl [-h | help] - or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] - or: gazellectl lstack show {ip} [LSTACK_OPTIONS] [time] + or: gazellectl ltran {quit | show | set} [LTRAN_OPTIONS] [time] + or: gazellectl lstack {show | set} {ip | pid} [LSTACK_OPTIONS] [time] quit ltran process exit @@ -199,6 +204,8 @@ Usage: gazellectl [-h | help] -i, instance show ltran instance register info -b, burst show ltran NIC packet len per second -l, latency show ltran latency + set: + loglevel {error | info | debug} set ltran loglevel where LSTACK_OPTIONS := show lstack all statistics @@ -206,7 +213,9 @@ Usage: gazellectl [-h | help] -s, snmp show lstack snmp -c, connetct show lstack connect -l, latency show lstack latency - + set: + loglevel {error | info | debug} set lstack loglevel + lowpower {0 | 1} set lowpower enable [time] measure latency time default 1S ``` @@ -243,17 +252,17 @@ Usage: gazellectl [-h | help] - 不使用ltran模式,KNI网口不可配置只支持本地通讯使用,且需要启动前配置NetworkManager不管理KNI网卡。 - 虚拟KNI网口的IP及mac地址,需要与lstack.conf配置文件保持一致 。 -## 风险提示 -Gazelle可能存在如下安全风险,用户需要根据使用场景评估风险。 +## 注意事项 +用户根据使用场景评估使用Gazelle **共享内存** - 现状 - 大页内存 mount 至 /mnt/hugepages-2M 目录,链接 liblstack.so 的进程初始化时在 /mnt/hugepages-2M 目录下创建文件,每个文件对应 2M 大页内存,并 mmap 这些文件。ltran 在收到 lstask 的注册信息后,根据大页内存配置信息也 mmap 目录下文件,实现大页内存共享。 - ltran 在 /mnt/hugepages 目录的大页内存同理。 -- 当前消减措施 + 大页内存 mount 至 /mnt/hugepages-lstack 目录,进程初始化时在 /mnt/hugepages-lstack 目录下创建文件,每个文件对应一个大页,并 mmap 这些文件。ltran 在收到 lstask 的注册信息后,根据大页内存配置信息也 mmap 目录下文件,实现大页内存共享。 + ltran 在 /mnt/hugepages-ltran 目录的大页内存同理。 +- 当前消减措施 大页文件权限 600,只有 OWNER 用户才能访问文件,默认 root 用户,支持配置成其它用户; 大页文件有 DPDK 文件锁,不能直接写或者映射。 -- 风险点 +- 注意 属于同一用户的恶意进程模仿DPDK实现逻辑,通过大页文件共享大页内存,写破坏大页内存,导致Gazelle程序crash。建议用户下的进程属于同一信任域。 **流量限制** -- Gitee From 940750e6fbb41a0a6df61f1140d9fef46d97a678 Mon Sep 17 00:00:00 2001 From: liupengroc Date: Thu, 11 Aug 2022 14:24:30 +0800 Subject: [PATCH 110/130] update English translation for index.md --- docs/en/menu/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/en/menu/index.md b/docs/en/menu/index.md index 169899888..43140e2fa 100644 --- a/docs/en/menu/index.md +++ b/docs/en/menu/index.md @@ -57,7 +57,7 @@ headless: true - [Appendix]({{< relref "./docs/SecHarden/appendix.md" >}}) - [Virtualization User Guide]({{< relref "./docs/Virtualization/virtualization.md" >}}) - [Introduction to Virtualization]({{< relref "./docs/Virtualization/introduction-to-virtualization.md" >}}) - - [Installing Virtualization]({{< relref "./docs/Virtualization/virtualization-installation.md" >}}) + - [Installing Virtualization Components]({{< relref "./docs/Virtualization/virtualization-installation.md" >}}) - [Environment Preparation]({{< relref "./docs/Virtualization/environment-preparation.md" >}}) - [VM Configuration]({{< relref "./docs/Virtualization/vm-configuration.md" >}}) - [Managing VMs]({{< relref "./docs/Virtualization/managing-vms.md" >}}) -- Gitee From 8effc087389deee758bd267c2a8970f2ed49ea0f Mon Sep 17 00:00:00 2001 From: zhangqiumiao Date: Thu, 11 Aug 2022 14:01:43 +0000 Subject: [PATCH 111/130] =?UTF-8?q?update=20docs/zh/docs/Administration/?= =?UTF-8?q?=E5=9F=BA=E7=A1=80=E9=85=8D=E7=BD=AE.md.=20=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E4=B8=8D=E5=90=8C=E5=BC=95=E5=AF=BC=E6=A8=A1=E5=BC=8F=E4=B8=8B?= =?UTF-8?q?=E7=9A=84grub.cfg=E6=96=87=E4=BB=B6=E6=89=80=E5=9C=A8=E8=B7=AF?= =?UTF-8?q?=E5=BE=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhangqiumiao --- .../\345\237\272\347\241\200\351\205\215\347\275\256.md" | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git "a/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" "b/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" index ff5e779e2..f863f5c20 100644 --- "a/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" +++ "b/docs/zh/docs/Administration/\345\237\272\347\241\200\351\205\215\347\275\256.md" @@ -448,7 +448,7 @@ Linux 将时钟分为: ### 设置kdump预留内存 #### 预留内存参数格式 -kdump预留内存参数必须添加到内核启动参数中,配置文件为/boot/efi/EFI/openEuler/grub.cfg,openEuler发布版本中默认已经添加,可以根据实际使用情况调整。添加和修改启动参数后,重启系统生效。kdump预留内存参数格式如下: +kdump预留内存参数必须添加到内核启动参数中,配置文件为/boot/efi/EFI/openEuler/grub.cfg(UEFI引导模式)或/boot/grub2/grub.cfg(legacy引导模式),openEuler发布版本中默认已经添加,可以根据实际使用情况调整。添加和修改启动参数后,重启系统生效。kdump预留内存参数格式如下: | 内核启动参数 | 描述 | 默认值 | 备注 | |--------------------|-------------------------------------------|---------------|------------------------------------------------------------| -- Gitee From a8a0f9a6a342c189458d4967b5f10e9f4f916c7b Mon Sep 17 00:00:00 2001 From: gaoxingwang Date: Thu, 11 Aug 2022 22:33:29 +0800 Subject: [PATCH 112/130] =?UTF-8?q?=E6=B7=BB=E5=8A=A0ifcfg=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E6=96=87=E4=BB=B6=E7=94=9F=E6=95=88=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../\351\205\215\347\275\256\347\275\221\347\273\234.md" | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git "a/docs/zh/docs/Administration/\351\205\215\347\275\256\347\275\221\347\273\234.md" "b/docs/zh/docs/Administration/\351\205\215\347\275\256\347\275\221\347\273\234.md" index 0bc0efb4b..a6ee14ea6 100644 --- "a/docs/zh/docs/Administration/\351\205\215\347\275\256\347\275\221\347\273\234.md" +++ "b/docs/zh/docs/Administration/\351\205\215\347\275\256\347\275\221\347\273\234.md" @@ -353,6 +353,10 @@ $ nmcli connection show id 'Wifi ' | grep mtu nmcli> quit ``` +- 使用如下命令激活连接以生效配置: + ``` + $ nmcli con up enp3s0 + ``` ### 使用ip命令 @@ -449,7 +453,7 @@ ip route add 192.168.2.0/24 via 10.0.0.1 [dev interface-name] ### 通过ifcfg文件配置网络 >![](./public_sys-resources/icon-note.gif) **说明:** ->通过ifcfg文件配置的网络配置不会立即生效,需要在root权限下执行**systemctl reload NetworkManager**命令以重启网络服务后才生效。 +>通过ifcfg文件配置的网络配置不会立即生效,修改文件后(以ifcfg-enp3s0为例),需要在root权限下执行**nmcli con reload;nmcli con up enp3s0**命令以重新加载配置文件并激活连接才生效。 #### 配置静态网络 -- Gitee From faaa9f2bc2873078c4d305ff43b25dca8289e3c8 Mon Sep 17 00:00:00 2001 From: zhangxiaoyu Date: Fri, 12 Aug 2022 15:02:26 +0800 Subject: [PATCH 113/130] fix kubernetes docs Signed-off-by: zhangxiaoyu --- .../\345\207\206\345\244\207\350\257\201\344\271\246.md" | 2 +- ...50\243\205Kubernetes\350\275\257\344\273\266\345\214\205.md" | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git "a/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" "b/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" index 1ff573239..ccd0824fc 100644 --- "a/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" +++ "b/docs/zh/docs/Kubernetes/\345\207\206\345\244\207\350\257\201\344\271\246.md" @@ -167,7 +167,7 @@ service-account.csr service-account-key.pem service-account.pem 生成证书: ```bash -$ cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json-profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager +$ cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager ``` 结果如下: diff --git "a/docs/zh/docs/Kubernetes/\345\256\211\350\243\205Kubernetes\350\275\257\344\273\266\345\214\205.md" "b/docs/zh/docs/Kubernetes/\345\256\211\350\243\205Kubernetes\350\275\257\344\273\266\345\214\205.md" index c91a576bc..98fc9552e 100644 --- "a/docs/zh/docs/Kubernetes/\345\256\211\350\243\205Kubernetes\350\275\257\344\273\266\345\214\205.md" +++ "b/docs/zh/docs/Kubernetes/\345\256\211\350\243\205Kubernetes\350\275\257\344\273\266\345\214\205.md" @@ -5,7 +5,7 @@ $ dnf install -y docker conntrack-tools socat ``` -EPOL 之后,可以直接通过 dnf 安装 K8S +配置EPOL源之后,可以直接通过 dnf 安装 K8S ```bash $ rpm -ivh kubernetes*.rpm -- Gitee From 7d7f6e22c4cd723cf2727c7acb5a12449ac553ec Mon Sep 17 00:00:00 2001 From: wangxiyuan Date: Mon, 15 Aug 2022 10:14:28 +0800 Subject: [PATCH 114/130] Update opentack doc --- .../thirdparty_migration/OpenStack-train.md | 2959 --------------- .../thirdparty_migration/OpenStack-wallaby.md | 3214 ----------------- .../zh/docs/thirdparty_migration/openstack.md | 1 + .../docs/thirdparty_migration/thidrparty.md | 3 - docs/zh/menu/index.md | 2 +- 5 files changed, 2 insertions(+), 6177 deletions(-) delete mode 100644 docs/zh/docs/thirdparty_migration/OpenStack-train.md delete mode 100644 docs/zh/docs/thirdparty_migration/OpenStack-wallaby.md create mode 100644 docs/zh/docs/thirdparty_migration/openstack.md diff --git a/docs/zh/docs/thirdparty_migration/OpenStack-train.md b/docs/zh/docs/thirdparty_migration/OpenStack-train.md deleted file mode 100644 index a8d3f4409..000000000 --- a/docs/zh/docs/thirdparty_migration/OpenStack-train.md +++ /dev/null @@ -1,2959 +0,0 @@ -# OpenStack-Train 部署指南 - - - -- [OpenStack-Train 部署指南](#openstack-train-部署指南) - - [OpenStack 简介](#openstack-简介) - - [约定](#约定) - - [准备环境](#准备环境) - - [环境配置](#环境配置) - - [安装 SQL DataBase](#安装-sql-database) - - [安装 RabbitMQ](#安装-rabbitmq) - - [安装 Memcached](#安装-memcached) - - [安装 OpenStack](#安装-openstack) - - [Keystone 安装](#keystone-安装) - - [Glance 安装](#glance-安装) - - [Placement安装](#placement安装) - - [Nova 安装](#nova-安装) - - [Neutron 安装](#neutron-安装) - - [Cinder 安装](#cinder-安装) - - [horizon 安装](#horizon-安装) - - [Tempest 安装](#tempest-安装) - - [Ironic 安装](#ironic-安装) - - [Kolla 安装](#kolla-安装) - - [Trove 安装](#trove-安装) - - [Swift 安装](#swift-安装) - - [Cyborg 安装](#cyborg-安装) - - [Aodh 安装](#aodh-安装) - - [Gnocchi 安装](#gnocchi-安装) - - [Ceilometer 安装](#ceilometer-安装) - - [Heat 安装](#heat-安装) - - [快速安装 OpenStack](#快速安装-openstack) - - -## OpenStack 简介 - -OpenStack 是一个社区,也是一个项目。它提供了一个部署云的操作平台或工具集,为组织提供可扩展的、灵活的云计算。 - -作为一个开源的云计算管理平台,OpenStack 由nova、cinder、neutron、glance、keystone、horizon等几个主要的组件组合起来完成具体工作。OpenStack 支持几乎所有类型的云环境,项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenStack 通过各种互补的服务提供了基础设施即服务(IaaS)的解决方案,每个服务提供 API 进行集成。 - -openEuler 22.03-LTS版本官方源已经支持 OpenStack-Train 版本,用户可以配置好 yum 源后根据此文档进行 OpenStack 部署。 - -## 约定 - -OpenStack 支持多种形态部署,此文档支持`ALL in One`以及`Distributed`两种部署方式,按照如下方式约定: - -`ALL in One`模式: - -```text -忽略所有可能的后缀 -``` - -`Distributed`模式: - -```text -以 `(CTL)` 为后缀表示此条配置或者命令仅适用`控制节点` -以 `(CPT)` 为后缀表示此条配置或者命令仅适用`计算节点` -以 `(STG)` 为后缀表示此条配置或者命令仅适用`存储节点` -除此之外表示此条配置或者命令同时适用`控制节点`和`计算节点` -``` - -***注意*** - -涉及到以上约定的服务如下: - -- Cinder -- Nova -- Neutron - -## 准备环境 - -### 环境配置 - -1. 启动OpenStack Train yum源 - - ```shell - yum update - yum install openstack-release-train - yum clean all && yum makecache - ``` - - **注意**:如果你的环境的YUM源没有启用EPOL,需要同时配置EPOL - - ```shell - vi /etc/yum.repos.d/openEuler.repo - - [EPOL] - name=EPOL - baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler - EOF - ``` - -2. 修改主机名以及映射 - - 设置各个节点的主机名 - - ```shell - hostnamectl set-hostname controller (CTL) - hostnamectl set-hostname compute (CPT) - ``` - - 假设controller节点的IP是`10.0.0.11`,compute节点的IP是`10.0.0.12`(如果存在的话),则于`/etc/hosts`新增如下: - - ```shell - 10.0.0.11 controller - 10.0.0.12 compute - ``` - -### 安装 SQL DataBase - -1. 执行如下命令,安装软件包。 - - ```shell - yum install mariadb mariadb-server python3-PyMySQL - ``` - -2. 执行如下命令,创建并编辑 `/etc/my.cnf.d/openstack.cnf` 文件。 - - ```shell - vim /etc/my.cnf.d/openstack.cnf - - [mysqld] - bind-address = 10.0.0.11 - default-storage-engine = innodb - innodb_file_per_table = on - max_connections = 4096 - collation-server = utf8_general_ci - character-set-server = utf8 - ``` - - ***注意*** - - **其中 `bind-address` 设置为控制节点的管理IP地址。** - -3. 启动 DataBase 服务,并为其配置开机自启动: - - ```shell - systemctl enable mariadb.service - systemctl start mariadb.service - ``` - -4. 配置DataBase的默认密码(可选) - - ```shell - mysql_secure_installation - ``` - - ***注意*** - - **根据提示进行即可** - -### 安装 RabbitMQ - -1. 执行如下命令,安装软件包。 - - ```shell - yum install rabbitmq-server - ``` - -2. 启动 RabbitMQ 服务,并为其配置开机自启动。 - - ```shell - systemctl enable rabbitmq-server.service - systemctl start rabbitmq-server.service - ``` - -3. 添加 OpenStack用户。 - - ```shell - rabbitmqctl add_user openstack RABBIT_PASS - ``` - - ***注意*** - - **替换 `RABBIT_PASS`,为 OpenStack 用户设置密码** - -4. 设置openstack用户权限,允许进行配置、写、读: - - ```shell - rabbitmqctl set_permissions openstack ".*" ".*" ".*" - ``` - -### 安装 Memcached - -1. 执行如下命令,安装依赖软件包。 - - ```shell - yum install memcached python3-memcached - ``` - -2. 编辑 `/etc/sysconfig/memcached` 文件。 - - ```shell - vim /etc/sysconfig/memcached - - OPTIONS="-l 127.0.0.1,::1,controller" - ``` - -3. 执行如下命令,启动 Memcached 服务,并为其配置开机启动。 - - ```shell - systemctl enable memcached.service - systemctl start memcached.service - ``` - - ***注意*** - - **服务启动后,可以通过命令`memcached-tool controller stats`确保启动正常,服务可用,其中可以将`controller`替换为控制节点的管理IP地址。** - -## 安装 OpenStack - -### Keystone 安装 - -1. 创建 keystone 数据库并授权。 - - ``` sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE keystone; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `KEYSTONE_DBPASS`,为 Keystone 数据库设置密码** - -2. 安装软件包。 - - ```shell - yum install openstack-keystone httpd mod_wsgi - ``` - -3. 配置keystone相关配置 - - ```shell - vim /etc/keystone/keystone.conf - - [database] - connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone - - [token] - provider = fernet - ``` - - ***解释*** - - [database]部分,配置数据库入口 - - [token]部分,配置token provider - - ***注意:*** - - **替换 `KEYSTONE_DBPASS` 为 Keystone 数据库的密码** - -4. 同步数据库。 - - ```shell - su -s /bin/sh -c "keystone-manage db_sync" keystone - ``` - -5. 初始化Fernet密钥仓库。 - - ```shell - keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone - keystone-manage credential_setup --keystone-user keystone --keystone-group keystone - ``` - -6. 启动服务。 - - ```shell - keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ - --bootstrap-admin-url http://controller:5000/v3/ \ - --bootstrap-internal-url http://controller:5000/v3/ \ - --bootstrap-public-url http://controller:5000/v3/ \ - --bootstrap-region-id RegionOne - ``` - - ***注意*** - - **替换 `ADMIN_PASS`,为 admin 用户设置密码** - -7. 配置Apache HTTP server - - ```shell - vim /etc/httpd/conf/httpd.conf - - ServerName controller - ``` - - ```shell - ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ - ``` - - ***解释*** - - 配置 `ServerName` 项引用控制节点 - - ***注意*** - **如果 `ServerName` 项不存在则需要创建** - -8. 启动Apache HTTP服务。 - - ```shell - systemctl enable httpd.service - systemctl start httpd.service - ``` - -9. 创建环境变量配置。 - - ```shell - cat << EOF >> ~/.admin-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=admin - export OS_USERNAME=admin - export OS_PASSWORD=ADMIN_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - EOF - ``` - - ***注意*** - - **替换 `ADMIN_PASS` 为 admin 用户的密码** - -10. 依次创建domain, projects, users, roles,需要先安装好python3-openstackclient: - - ```shell - yum install python3-openstackclient - ``` - - 导入环境变量 - - ```shell - source ~/.admin-openrc - ``` - - 创建project `service`,其中 domain `default` 在 keystone-manage bootstrap 时已创建 - - ```shell - openstack domain create --description "An Example Domain" example - ``` - - ```shell - openstack project create --domain default --description "Service Project" service - ``` - - 创建(non-admin)project `myproject`,user `myuser` 和 role `myrole`,为 `myproject` 和 `myuser` 添加角色`myrole` - - ```shell - openstack project create --domain default --description "Demo Project" myproject - openstack user create --domain default --password-prompt myuser - openstack role create myrole - openstack role add --project myproject --user myuser myrole - ``` - -11. 验证 - - 取消临时环境变量OS_AUTH_URL和OS_PASSWORD: - - ```shell - source ~/.admin-openrc - unset OS_AUTH_URL OS_PASSWORD - ``` - - 为admin用户请求token: - - ```shell - openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name admin --os-username admin token issue - ``` - - 为myuser用户请求token: - - ```shell - openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name myproject --os-username myuser token issue - ``` - -### Glance 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE glance; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意:*** - - **替换 `GLANCE_DBPASS`,为 glance 数据库设置密码** - - 创建服务凭证 - - ```shell - source ~/.admin-openrc - - openstack user create --domain default --password-prompt glance - openstack role add --project service --user glance admin - openstack service create --name glance --description "OpenStack Image" image - ``` - - 创建镜像服务API端点: - - ```shell - openstack endpoint create --region RegionOne image public http://controller:9292 - openstack endpoint create --region RegionOne image internal http://controller:9292 - openstack endpoint create --region RegionOne image admin http://controller:9292 - ``` - -2. 安装软件包 - - ```shell - yum install openstack-glance - ``` - -3. 配置glance相关配置: - - ```shell - vim /etc/glance/glance-api.conf - - [database] - connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = glance - password = GLANCE_PASS - - [paste_deploy] - flavor = keystone - - [glance_store] - stores = file,http - default_store = file - filesystem_store_datadir = /var/lib/glance/images/ - ``` - - ***解释:*** - - [database]部分,配置数据库入口 - - [keystone_authtoken] [paste_deploy]部分,配置身份认证服务入口 - - [glance_store]部分,配置本地文件系统存储和镜像文件的位置 - - ***注意*** - - **替换 `GLANCE_DBPASS` 为 glance 数据库的密码** - - **替换 `GLANCE_PASS` 为 glance 用户的密码** - -4. 同步数据库: - - ```shell - su -s /bin/sh -c "glance-manage db_sync" glance - ``` - -5. 启动服务: - - ```shell - systemctl enable openstack-glance-api.service - systemctl start openstack-glance-api.service - ``` - -6. 验证 - - 下载镜像 - - ```shell - source ~/.admin-openrc - - wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img - ``` - - ***注意*** - - **如果您使用的环境是鲲鹏架构,请下载aarch64版本的镜像;已对镜像cirros-0.5.2-aarch64-disk.img进行测试。** - - 向Image服务上传镜像: - - ```shell - openstack image create --disk-format qcow2 --container-format bare \ - --file cirros-0.4.0-x86_64-disk.img --public cirros - ``` - - 确认镜像上传并验证属性: - - ```shell - openstack image list - ``` - -### Placement安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - 作为 root 用户访问数据库,创建 placement 数据库并授权。 - - ```shell - mysql -u root -p - MariaDB [(none)]> CREATE DATABASE placement; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `PLACEMENT_DBPASS` 为 placement 数据库设置密码** - - ```shell - source admin-openrc - ``` - - 执行如下命令,创建 placement 服务凭证、创建 placement 用户以及添加‘admin’角色到用户‘placement’。 - - 创建Placement API服务 - - ```shell - openstack user create --domain default --password-prompt placement - openstack role add --project service --user placement admin - openstack service create --name placement --description "Placement API" placement - ``` - - 创建placement服务API端点: - - ```shell - openstack endpoint create --region RegionOne placement public http://controller:8778 - openstack endpoint create --region RegionOne placement internal http://controller:8778 - openstack endpoint create --region RegionOne placement admin http://controller:8778 - ``` - -2. 安装和配置 - - 安装软件包: - - ```shell - yum install openstack-placement-api - ``` - - 配置placement: - - 编辑 /etc/placement/placement.conf 文件: - - 在[placement_database]部分,配置数据库入口 - - 在[api] [keystone_authtoken]部分,配置身份认证服务入口 - - ```shell - # vim /etc/placement/placement.conf - [placement_database] - # ... - connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - auth_url = http://controller:5000/v3 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = placement - password = PLACEMENT_PASS - ``` - - 其中,替换 PLACEMENT_DBPASS 为 placement 数据库的密码,替换 PLACEMENT_PASS 为 placement 用户的密码。 - - 同步数据库: - - ```shell - su -s /bin/sh -c "placement-manage db sync" placement - ``` - - 启动httpd服务: - - ```shell - systemctl restart httpd - ``` - -3. 验证 - - 执行如下命令,执行状态检查: - - ```shell - . admin-openrc - placement-status upgrade check - ``` - - 安装osc-placement,列出可用的资源类别及特性: - - ```shell - yum install python3-osc-placement - openstack --os-placement-api-version 1.2 resource class list --sort-column name - openstack --os-placement-api-version 1.6 trait list --sort-column name - ``` - -### Nova 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p (CTL) - - MariaDB [(none)]> CREATE DATABASE nova_api; - MariaDB [(none)]> CREATE DATABASE nova; - MariaDB [(none)]> CREATE DATABASE nova_cell0; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换NOVA_DBPASS,为nova数据库设置密码** - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 创建nova服务凭证: - - ```shell - openstack user create --domain default --password-prompt nova (CTL) - openstack role add --project service --user nova admin (CTL) - openstack service create --name nova --description "OpenStack Compute" compute (CTL) - ``` - - 创建nova API端点: - - ```shell - openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 (CTL) - openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 (CTL) - openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 (CTL) - ``` - -2. 安装软件包 - - ```shell - yum install openstack-nova-api openstack-nova-conductor \ (CTL) - openstack-nova-novncproxy openstack-nova-scheduler - - yum install openstack-nova-compute (CPT) - ``` - - ***注意*** - - **如果为arm64结构,还需要执行以下命令** - - ```shell - yum install edk2-aarch64 (CPT) - ``` - -3. 配置nova相关配置 - - ```shell - vim /etc/nova/nova.conf - - [DEFAULT] - enabled_apis = osapi_compute,metadata - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - my_ip = 10.0.0.1 - use_neutron = true - firewall_driver = nova.virt.firewall.NoopFirewallDriver - compute_driver=libvirt.LibvirtDriver (CPT) - instances_path = /var/lib/nova/instances/ (CPT) - lock_path = /var/lib/nova/tmp (CPT) - - [api_database] - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api (CTL) - - [database] - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova (CTL) - - [api] - auth_strategy = keystone - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000/ - auth_url = http://controller:5000/ - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = nova - password = NOVA_PASS - - [vnc] - enabled = true - server_listen = $my_ip - server_proxyclient_address = $my_ip - novncproxy_base_url = http://controller:6080/vnc_auto.html (CPT) - - [glance] - api_servers = http://controller:9292 - - [oslo_concurrency] - lock_path = /var/lib/nova/tmp (CTL) - - [placement] - region_name = RegionOne - project_domain_name = Default - project_name = service - auth_type = password - user_domain_name = Default - auth_url = http://controller:5000/v3 - username = placement - password = PLACEMENT_PASS - - [neutron] - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true (CTL) - metadata_proxy_shared_secret = METADATA_SECRET (CTL) - ``` - - ***解释*** - - [default]部分,启用计算和元数据的API,配置RabbitMQ消息队列入口,配置my_ip,启用网络服务neutron; - - [api_database] [database]部分,配置数据库入口; - - [api] [keystone_authtoken]部分,配置身份认证服务入口; - - [vnc]部分,启用并配置远程控制台入口; - - [glance]部分,配置镜像服务API的地址; - - [oslo_concurrency]部分,配置lock path; - - [placement]部分,配置placement服务的入口。 - - ***注意*** - - **替换 `RABBIT_PASS` 为 RabbitMQ 中 openstack 账户的密码;** - - **配置 `my_ip` 为控制节点的管理IP地址;** - - **替换 `NOVA_DBPASS` 为nova数据库的密码;** - - **替换 `NOVA_PASS` 为nova用户的密码;** - - **替换 `PLACEMENT_PASS` 为placement用户的密码;** - - **替换 `NEUTRON_PASS` 为neutron用户的密码;** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - - **额外** - - 确定是否支持虚拟机硬件加速(x86架构): - - ```shell - egrep -c '(vmx|svm)' /proc/cpuinfo (CPT) - ``` - - 如果返回值为0则不支持硬件加速,需要配置libvirt使用QEMU而不是KVM: - - ```shell - vim /etc/nova/nova.conf (CPT) - - [libvirt] - virt_type = qemu - ``` - - 如果返回值为1或更大的值,则支持硬件加速,则`virt_type`可以配置为`kvm` - - ***注意*** - - **如果为arm64结构,还需要在计算节点执行以下命令** - - ```shell - - mkdir -p /usr/share/AAVMF - chown nova:nova /usr/share/AAVMF - - ln -s /usr/share/edk2/aarch64/QEMU_EFI-pflash.raw \ - /usr/share/AAVMF/AAVMF_CODE.fd - ln -s /usr/share/edk2/aarch64/vars-template-pflash.raw \ - /usr/share/AAVMF/AAVMF_VARS.fd - - vim /etc/libvirt/qemu.conf - - nvram = ["/usr/share/AAVMF/AAVMF_CODE.fd: \ - /usr/share/AAVMF/AAVMF_VARS.fd", \ - "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw: \ - /usr/share/edk2/aarch64/vars-template-pflash.raw"] - ``` - - 并且当ARM架构下的部署环境为嵌套虚拟化时,`libvirt`配置如下: - - ```shell - [libvirt] - virt_type = qemu - cpu_mode = custom - cpu_model = cortex-a72 - ``` - -4. 同步数据库 - - 同步nova-api数据库: - - ```shell - su -s /bin/sh -c "nova-manage api_db sync" nova (CTL) - ``` - - 注册cell0数据库: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova (CTL) - ``` - - 创建cell1 cell: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova (CTL) - ``` - - 同步nova数据库: - - ```shell - su -s /bin/sh -c "nova-manage db sync" nova (CTL) - ``` - - 验证cell0和cell1注册正确: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova (CTL) - ``` - - 添加计算节点到openstack集群 - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova (CTL) - ``` - -5. 启动服务 - - ```shell - systemctl enable \ (CTL) - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - - systemctl start \ (CTL) - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - ``` - - ```shell - systemctl enable libvirtd.service openstack-nova-compute.service (CPT) - systemctl start libvirtd.service openstack-nova-compute.service (CPT) - ``` - -6. 验证 - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 列出服务组件,验证每个流程都成功启动和注册: - - ```shell - openstack compute service list (CTL) - ``` - - 列出身份服务中的API端点,验证与身份服务的连接: - - ```shell - openstack catalog list (CTL) - ``` - - 列出镜像服务中的镜像,验证与镜像服务的连接: - - ```shell - openstack image list (CTL) - ``` - - 检查cells是否运作成功,以及其他必要条件是否已具备。 - - ```shell - nova-status upgrade check (CTL) - ``` - -### Neutron 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p (CTL) - - MariaDB [(none)]> CREATE DATABASE neutron; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `NEUTRON_DBPASS` 为 neutron 数据库设置密码。** - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 创建neutron服务凭证 - - ```shell - openstack user create --domain default --password-prompt neutron (CTL) - openstack role add --project service --user neutron admin (CTL) - openstack service create --name neutron --description "OpenStack Networking" network (CTL) - ``` - - 创建Neutron服务API端点: - - ```shell - openstack endpoint create --region RegionOne network public http://controller:9696 (CTL) - openstack endpoint create --region RegionOne network internal http://controller:9696 (CTL) - openstack endpoint create --region RegionOne network admin http://controller:9696 (CTL) - ``` - -2. 安装软件包: - - ```shell - yum install openstack-neutron openstack-neutron-linuxbridge ebtables ipset \ (CTL) - openstack-neutron-ml2 - ``` - - ```shell - yum install openstack-neutron-linuxbridge ebtables ipset (CPT) - ``` - -3. 配置neutron相关配置: - - 配置主体配置 - - ```shell - vim /etc/neutron/neutron.conf - - [database] - connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron (CTL) - - [DEFAULT] - core_plugin = ml2 (CTL) - service_plugins = router (CTL) - allow_overlapping_ips = true (CTL) - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - notify_nova_on_port_status_changes = true (CTL) - notify_nova_on_port_data_changes = true (CTL) - api_workers = 3 (CTL) - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = neutron - password = NEUTRON_PASS - - [nova] - auth_url = http://controller:5000 (CTL) - auth_type = password (CTL) - project_domain_name = Default (CTL) - user_domain_name = Default (CTL) - region_name = RegionOne (CTL) - project_name = service (CTL) - username = nova (CTL) - password = NOVA_PASS (CTL) - - [oslo_concurrency] - lock_path = /var/lib/neutron/tmp - ``` - - ***解释*** - - [database]部分,配置数据库入口; - - [default]部分,启用ml2插件和router插件,允许ip地址重叠,配置RabbitMQ消息队列入口; - - [default] [keystone]部分,配置身份认证服务入口; - - [default] [nova]部分,配置网络来通知计算网络拓扑的变化; - - [oslo_concurrency]部分,配置lock path。 - - ***注意*** - - **替换`NEUTRON_DBPASS`为 neutron 数据库的密码;** - - **替换`RABBIT_PASS`为 RabbitMQ中openstack 账户的密码;** - - **替换`NEUTRON_PASS`为 neutron 用户的密码;** - - **替换`NOVA_PASS`为 nova 用户的密码。** - - 配置ML2插件: - - ```shell - vim /etc/neutron/plugins/ml2/ml2_conf.ini - - [ml2] - type_drivers = flat,vlan,vxlan - tenant_network_types = vxlan - mechanism_drivers = linuxbridge,l2population - extension_drivers = port_security - - [ml2_type_flat] - flat_networks = provider - - [ml2_type_vxlan] - vni_ranges = 1:1000 - - [securitygroup] - enable_ipset = true - ``` - - 创建/etc/neutron/plugin.ini的符号链接 - - ```shell - ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini - ``` - - **注意** - - **[ml2]部分,启用 flat、vlan、vxlan 网络,启用 linuxbridge 及 l2population 机制,启用端口安全扩展驱动;** - - **[ml2_type_flat]部分,配置 flat 网络为 provider 虚拟网络;** - - **[ml2_type_vxlan]部分,配置 VXLAN 网络标识符范围;** - - **[securitygroup]部分,配置允许 ipset。** - - **补充** - - **l2 的具体配置可以根据用户需求自行修改,本文使用的是provider network + linuxbridge** - - 配置 Linux bridge 代理: - - ```shell - vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini - - [linux_bridge] - physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME - - [vxlan] - enable_vxlan = true - local_ip = OVERLAY_INTERFACE_IP_ADDRESS - l2_population = true - - [securitygroup] - enable_security_group = true - firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver - ``` - - ***解释*** - - [linux_bridge]部分,映射 provider 虚拟网络到物理网络接口; - - [vxlan]部分,启用 vxlan 覆盖网络,配置处理覆盖网络的物理网络接口 IP 地址,启用 layer-2 population; - - [securitygroup]部分,允许安全组,配置 linux bridge iptables 防火墙驱动。 - - ***注意*** - - **替换`PROVIDER_INTERFACE_NAME`为物理网络接口;** - - **替换`OVERLAY_INTERFACE_IP_ADDRESS`为控制节点的管理IP地址。** - - 配置Layer-3代理: - - ```shell - vim /etc/neutron/l3_agent.ini (CTL) - - [DEFAULT] - interface_driver = linuxbridge - ``` - - ***解释*** - - 在[default]部分,配置接口驱动为linuxbridge - - 配置DHCP代理: - - ```shell - vim /etc/neutron/dhcp_agent.ini (CTL) - - [DEFAULT] - interface_driver = linuxbridge - dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq - enable_isolated_metadata = true - ``` - - ***解释*** - - [default]部分,配置linuxbridge接口驱动、Dnsmasq DHCP驱动,启用隔离的元数据。 - - 配置metadata代理: - - ```shell - vim /etc/neutron/metadata_agent.ini (CTL) - - [DEFAULT] - nova_metadata_host = controller - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - ***解释*** - - [default]部分,配置元数据主机和shared secret。 - - ***注意*** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - -4. 配置nova相关配置 - - ```shell - vim /etc/nova/nova.conf - - [neutron] - auth_url = http://controller:5000 - auth_type = password - project_domain_name = Default - user_domain_name = Default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true (CTL) - metadata_proxy_shared_secret = METADATA_SECRET (CTL) - ``` - - ***解释*** - - [neutron]部分,配置访问参数,启用元数据代理,配置secret。 - - ***注意*** - - **替换`NEUTRON_PASS`为 neutron 用户的密码;** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - -5. 同步数据库: - - ```shell - su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ - --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron - ``` - -6. 重启计算API服务: - - ```shell - systemctl restart openstack-nova-api.service - ``` - -7. 启动网络服务 - - ```shell - systemctl enable neutron-server.service neutron-linuxbridge-agent.service \ (CTL) - neutron-dhcp-agent.service neutron-metadata-agent.service \ - neutron-l3-agent.service - - systemctl restart neutron-server.service neutron-linuxbridge-agent.service \ (CTL) - neutron-dhcp-agent.service neutron-metadata-agent.service \ - neutron-l3-agent.service - - systemctl enable neutron-linuxbridge-agent.service (CPT) - systemctl restart neutron-linuxbridge-agent.service openstack-nova-compute.service (CPT) - ``` - -8. 验证 - - 验证 neutron 代理启动成功: - - ```shell - openstack network agent list - ``` - -### Cinder 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE cinder; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `CINDER_DBPASS` 为cinder数据库设置密码。** - - ```shell - source ~/.admin-openrc - ``` - - 创建cinder服务凭证: - - ```shell - openstack user create --domain default --password-prompt cinder - openstack role add --project service --user cinder admin - openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 - openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 - ``` - - 创建块存储服务API端点: - - ```shell - openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%\(project_id\)s - ``` - -2. 安装软件包: - - ```shell - yum install openstack-cinder-api openstack-cinder-scheduler (CTL) - ``` - - ```shell - yum install lvm2 device-mapper-persistent-data scsi-target-utils rpcbind nfs-utils \ (STG) - openstack-cinder-volume openstack-cinder-backup - ``` - -3. 准备存储设备,以下仅为示例: - - ```shell - pvcreate /dev/vdb - vgcreate cinder-volumes /dev/vdb - - vim /etc/lvm/lvm.conf - - - devices { - ... - filter = [ "a/vdb/", "r/.*/"] - ``` - - ***解释*** - - 在devices部分,添加过滤以接受/dev/vdb设备拒绝其他设备。 - -4. 准备NFS - - ```shell - mkdir -p /root/cinder/backup - - cat << EOF >> /etc/export - /root/cinder/backup 192.168.1.0/24(rw,sync,no_root_squash,no_all_squash) - EOF - - ``` - -5. 配置cinder相关配置: - - ```shell - vim /etc/cinder/cinder.conf - - [DEFAULT] - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - my_ip = 10.0.0.11 - enabled_backends = lvm (STG) - backup_driver=cinder.backup.drivers.nfs.NFSBackupDriver (STG) - backup_share=HOST:PATH (STG) - - [database] - connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = cinder - password = CINDER_PASS - - [oslo_concurrency] - lock_path = /var/lib/cinder/tmp - - [lvm] - volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver (STG) - volume_group = cinder-volumes (STG) - iscsi_protocol = iscsi (STG) - iscsi_helper = tgtadm (STG) - ``` - - ***解释*** - - [database]部分,配置数据库入口; - - [DEFAULT]部分,配置RabbitMQ消息队列入口,配置my_ip; - - [DEFAULT] [keystone_authtoken]部分,配置身份认证服务入口; - - [oslo_concurrency]部分,配置lock path。 - - ***注意*** - - **替换`CINDER_DBPASS`为 cinder 数据库的密码;** - - **替换`RABBIT_PASS`为 RabbitMQ 中 openstack 账户的密码;** - - **配置`my_ip`为控制节点的管理 IP 地址;** - - **替换`CINDER_PASS`为 cinder 用户的密码;** - - **替换`HOST:PATH`为 NFS 的HOSTIP和共享路径的密码;** - -6. 同步数据库: - - ```shell - su -s /bin/sh -c "cinder-manage db sync" cinder (CTL) - ``` - -7. 配置nova: - - ```shell - vim /etc/nova/nova.conf (CTL) - - [cinder] - os_region_name = RegionOne - ``` - -8. 重启计算API服务 - - ```shell - systemctl restart openstack-nova-api.service - ``` - -9. 启动cinder服务 - - ```shell - systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) - systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) - ``` - - ```shell - systemctl enable rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) - openstack-cinder-volume.service \ - openstack-cinder-backup.service - systemctl start rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) - openstack-cinder-volume.service \ - openstack-cinder-backup.service - ``` - - ***注意*** - - 当cinder使用tgtadm的方式挂卷的时候,要修改/etc/tgt/tgtd.conf,内容如下,保证tgtd可以发现cinder-volume的iscsi target。 - - ```shell - include /var/lib/cinder/volumes/* - ``` - -10. 验证 - - ```shell - source ~/.admin-openrc - openstack volume service list - ``` - -### horizon 安装 - -1. 安装软件包 - - ```shell - yum install openstack-dashboard - ``` - -2. 修改文件 - - 修改变量 - - ```text - vim /etc/openstack-dashboard/local_settings - - OPENSTACK_HOST = "controller" - ALLOWED_HOSTS = ['*', ] - - SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - - CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', - 'LOCATION': 'controller:11211', - } - } - - OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST - OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True - OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default" - OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user" - - OPENSTACK_API_VERSIONS = { - "identity": 3, - "image": 2, - "volume": 3, - } - ``` - -3. 重启 httpd 服务 - - ```shell - systemctl restart httpd.service memcached.service - ``` - -4. 验证 - 打开浏览器,输入网址,登录 horizon。 - - ***注意*** - - **替换HOSTIP为控制节点管理平面IP地址** - -### Tempest 安装 - -Tempest是OpenStack的集成测试服务,如果用户需要全面自动化测试已安装的OpenStack环境的功能,则推荐使用该组件。否则,可以不用安装。 - -1. 安装Tempest - - ```shell - yum install openstack-tempest - ``` - -2. 初始化目录 - - ```shell - tempest init mytest - ``` - -3. 修改配置文件。 - - ```shell - cd mytest - vi etc/tempest.conf - ``` - - tempest.conf中需要配置当前OpenStack环境的信息,具体内容可以参考[官方示例](https://docs.openstack.org/tempest/latest/sampleconf.html) - -4. 执行测试 - - ```shell - tempest run - ``` - -5. 安装tempest扩展(可选) - OpenStack各个服务本身也提供了一些tempest测试包,用户可以安装这些包来丰富tempest的测试内容。在Train中,我们提供了Cinder、Glance、Keystone、Ironic、Trove的扩展测试,用户可以执行如下命令进行安装使用: - ``` - yum install python3-cinder-tempest-plugin python3-glance-tempest-plugin python3-ironic-tempest-plugin python3-keystone-tempest-plugin python3-trove-tempest-plugin - ``` - -### Ironic 安装 - -Ironic是OpenStack的裸金属服务,如果用户需要进行裸机部署则推荐使用该组件。否则,可以不用安装。 - -1. 设置数据库 - - 裸金属服务在数据库中存储信息,创建一个**ironic**用户可以访问的**ironic**数据库,替换**IRONIC_DBPASSWORD**为合适的密码 - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - ``` -2. 安装软件包 - - ```shell - yum install openstack-ironic-api openstack-ironic-conductor python3-ironicclient - ``` - - 启动服务 - - ```shell - systemctl enable openstack-ironic-api openstack-ironic-conductor - systemctl start openstack-ironic-api openstack-ironic-conductor - ``` - -3. 创建服务用户认证 - - 1、创建Bare Metal服务用户 - - ```shell - openstack user create --password IRONIC_PASSWORD \ - --email ironic@example.com ironic - openstack role add --project service --user ironic admin - openstack service create --name ironic \ - --description "Ironic baremetal provisioning service" baremetal - ``` - - 2、创建Bare Metal服务访问入口 - - ```shell - openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 - openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 - openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 - ``` - -4. 配置ironic-api服务 - - 配置文件路径/etc/ironic/ironic.conf - - 1、通过**connection**选项配置数据库的位置,如下所示,替换**IRONIC_DBPASSWORD**为**ironic**用户的密码,替换**DB_IP**为DB服务器所在的IP地址: - - ```shell - [database] - - # The SQLAlchemy connection string used to connect to the - # database (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 2、通过以下选项配置ironic-api服务使用RabbitMQ消息代理,替换**RPC_\***为RabbitMQ的详细地址和凭证 - - ```shell - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 用户也可自行使用json-rpc方式替换rabbitmq - - 3、配置ironic-api服务使用身份认证服务的凭证,替换**PUBLIC_IDENTITY_IP**为身份认证服务器的公共IP,替换**PRIVATE_IDENTITY_IP**为身份认证服务器的私有IP,替换**IRONIC_PASSWORD**为身份认证服务中**ironic**用户的密码: - - ```shell - [DEFAULT] - - # Authentication strategy used by ironic-api: one of - # "keystone" or "noauth". "noauth" should not be used in a - # production environment because all authentication will be - # disabled. (string value) - - auth_strategy=keystone - - [keystone_authtoken] - # Authentication type to load (string value) - auth_type=password - # Complete public Identity API endpoint (string value) - www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 - # Complete admin Identity API endpoint. (string value) - auth_url=http://PRIVATE_IDENTITY_IP:5000 - # Service username. (string value) - username=ironic - # Service account password. (string value) - password=IRONIC_PASSWORD - # Service tenant name. (string value) - project_name=service - # Domain name containing project (string value) - project_domain_name=Default - # User's domain name (string value) - user_domain_name=Default - - ``` - - 4、创建裸金属服务数据库表 - - ```shell - ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema - ``` - - 5、重启ironic-api服务 - - ```shell - sudo systemctl restart openstack-ironic-api - ``` - -5. 配置ironic-conductor服务 - - 1、替换**HOST_IP**为conductor host的IP - - ```shell - [DEFAULT] - - # IP address of this host. If unset, will determine the IP - # programmatically. If unable to do so, will use "127.0.0.1". - # (string value) - - my_ip=HOST_IP - ``` - - 2、配置数据库的位置,ironic-conductor应该使用和ironic-api相同的配置。替换**IRONIC_DBPASSWORD**为**ironic**用户的密码,替换DB_IP为DB服务器所在的IP地址: - - ```shell - [database] - - # The SQLAlchemy connection string to use to connect to the - # database. (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 3、通过以下选项配置ironic-api服务使用RabbitMQ消息代理,ironic-conductor应该使用和ironic-api相同的配置,替换**RPC_\***为RabbitMQ的详细地址和凭证 - - ```shell - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 用户也可自行使用json-rpc方式替换rabbitmq - - 4、配置凭证访问其他OpenStack服务 - - 为了与其他OpenStack服务进行通信,裸金属服务在请求其他服务时需要使用服务用户与OpenStack Identity服务进行认证。这些用户的凭据必须在与相应服务相关的每个配置文件中进行配置。 - - ```shell - [neutron] - 访问OpenStack网络服务 - [glance] - 访问OpenStack镜像服务 - [swift] - 访问OpenStack对象存储服务 - [cinder] - 访问OpenStack块存储服务 - [inspector] - 访问OpenStack裸金属introspection服务 - [service_catalog] - 一个特殊项用于保存裸金属服务使用的凭证,该凭证用于发现注册在OpenStack身份认证服务目录中的自己的API URL端点 - ``` - - 简单起见,可以对所有服务使用同一个服务用户。为了向后兼容,该用户应该和ironic-api服务的[keystone_authtoken]所配置的为同一个用户。但这不是必须的,也可以为每个服务创建并配置不同的服务用户。 - - 在下面的示例中,用户访问OpenStack网络服务的身份验证信息配置为: - - ```shell - 网络服务部署在名为RegionOne的身份认证服务域中,仅在服务目录中注册公共端点接口 - - 请求时使用特定的CA SSL证书进行HTTPS连接 - - 与ironic-api服务配置相同的服务用户 - - 动态密码认证插件基于其他选项发现合适的身份认证服务API版本 - ``` - - ```shell - [neutron] - - # Authentication type to load (string value) - auth_type = password - # Authentication URL (string value) - auth_url=https://IDENTITY_IP:5000/ - # Username (string value) - username=ironic - # User's password (string value) - password=IRONIC_PASSWORD - # Project name to scope to (string value) - project_name=service - # Domain ID containing project (string value) - project_domain_id=default - # User's domain id (string value) - user_domain_id=default - # PEM encoded Certificate Authority to use when verifying - # HTTPs connections. (string value) - cafile=/opt/stack/data/ca-bundle.pem - # The default region_name for endpoint URL discovery. (string - # value) - region_name = RegionOne - # List of interfaces, in order of preference, for endpoint - # URL. (list value) - valid_interfaces=public - ``` - - 默认情况下,为了与其他服务进行通信,裸金属服务会尝试通过身份认证服务的服务目录发现该服务合适的端点。如果希望对一个特定服务使用一个不同的端点,则在裸金属服务的配置文件中通过endpoint_override选项进行指定: - - ```shell - [neutron] ... endpoint_override = - ``` - - 5、配置允许的驱动程序和硬件类型 - - 通过设置enabled_hardware_types设置ironic-conductor服务允许使用的硬件类型: - - ```shell - [DEFAULT] enabled_hardware_types = ipmi - ``` - - 配置硬件接口: - - ```shell - enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool - ``` - - 配置接口默认值: - - ```shell - [DEFAULT] default_deploy_interface = direct default_network_interface = neutron - ``` - - 如果启用了任何使用Direct deploy的驱动,必须安装和配置镜像服务的Swift后端。Ceph对象网关(RADOS网关)也支持作为镜像服务的后端。 - - 6、重启ironic-conductor服务 - - ```shell - sudo systemctl restart openstack-ironic-conductor - ``` - -6. 配置httpd服务 - - 1. 创建ironic要使用的httpd的root目录并设置属主属组,目录路径要和/etc/ironic/ironic.conf中[deploy]组中http_root 配置项指定的路径要一致。 - - ``` - mkdir -p /var/lib/ironic/httproot ``chown ironic.ironic /var/lib/ironic/httproot - ``` - - 2. 安装和配置httpd服务 - - 1. 安装httpd服务,已有请忽略 - - ``` - yum install httpd -y - ``` - 2. 创建/etc/httpd/conf.d/openstack-ironic-httpd.conf文件,内容如下: - - ``` - Listen 8080 - - - ServerName ironic.openeuler.com - - ErrorLog "/var/log/httpd/openstack-ironic-httpd-error_log" - CustomLog "/var/log/httpd/openstack-ironic-httpd-access_log" "%h %l %u %t \"%r\" %>s %b" - - DocumentRoot "/var/lib/ironic/httproot" - - Options Indexes FollowSymLinks - Require all granted - - LogLevel warn - AddDefaultCharset UTF-8 - EnableSendfile on - - - ``` - - 注意监听的端口要和/etc/ironic/ironic.conf里[deploy]选项中http_url配置项中指定的端口一致。 - - 3. 重启httpd服务。 - - ``` - systemctl restart httpd - ``` -7. deploy ramdisk镜像制作 - - T版的ramdisk镜像支持通过ironic-python-agent服务或disk-image-builder工具制作,也可以使用社区最新的ironic-python-agent-builder。用户也可以自行选择其他工具制作。 - 若使用T版原生工具,则需要安装对应的软件包。 - - ```shell - yum install openstack-ironic-python-agent - 或者 - yum install diskimage-builder - ``` - - 具体的使用方法可以参考[官方文档](https://docs.openstack.org/ironic/queens/install/deploy-ramdisk.html) - - 这里介绍下使用ironic-python-agent-builder构建ironic使用的deploy镜像的完整过程。 - - 1. 安装 ironic-python-agent-builder - - 1. 安装工具: - - ```shell - pip install ironic-python-agent-builder - ``` - - 2. 修改以下文件中的python解释器: - - ```shell - /usr/bin/yum /usr/libexec/urlgrabber-ext-down - ``` - - 3. 安装其它必须的工具: - - ```shell - yum install git - ``` - - 由于`DIB`依赖`semanage`命令,所以在制作镜像之前确定该命令是否可用:`semanage --help`,如果提示无此命令,安装即可: - - ```shell - # 先查询需要安装哪个包 - [root@localhost ~]# yum provides /usr/sbin/semanage - 已加载插件:fastestmirror - Loading mirror speeds from cached hostfile - * base: mirror.vcu.edu - * extras: mirror.vcu.edu - * updates: mirror.math.princeton.edu - policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities - 源 :base - 匹配来源: - 文件名 :/usr/sbin/semanage - # 安装 - [root@localhost ~]# yum install policycoreutils-python - ``` - - 2. 制作镜像 - - 如果是`arm`架构,需要添加: - ```shell - export ARCH=aarch64 - ``` - - 基本用法: - - ```shell - usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] - [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] - distribution - - positional arguments: - distribution Distribution to use - - optional arguments: - -h, --help show this help message and exit - -r RELEASE, --release RELEASE - Distribution release to use - -o OUTPUT, --output OUTPUT - Output base file name - -e ELEMENT, --element ELEMENT - Additional DIB element to use - -b BRANCH, --branch BRANCH - If set, override the branch that is used for ironic- - python-agent and requirements - -v, --verbose Enable verbose logging in diskimage-builder - --extra-args EXTRA_ARGS - Extra arguments to pass to diskimage-builder - ``` - - 举例说明: - - ```shell - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky - ``` - - 3. 允许ssh登陆 - - 初始化环境变量,然后制作镜像: - - ```shell - export DIB_DEV_USER_USERNAME=ipa \ - export DIB_DEV_USER_PWDLESS_SUDO=yes \ - export DIB_DEV_USER_PASSWORD='123' - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser - ``` - - 4. 指定代码仓库 - - 初始化对应的环境变量,然后制作镜像: - - ```shell - # 指定仓库地址以及版本 - DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git - DIB_REPOREF_ironic_python_agent=origin/develop - - # 直接从gerrit上clone代码 - DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent - DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 - ``` - - 参考:[source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html)。 - - 指定仓库地址及版本验证成功。 - - 5. 注意 - 原生的openstack里的pxe配置文件的模版不支持arm64架构,需要自己对原生openstack代码进行修改: - - 在T版中,社区的ironic仍然不支持arm64位的uefi pxe启动,表现为生成的grub.cfg文件(一般位于/tftpboot/下)格式不对而导致pxe启动失败 - - 需要用户对生成grub.cfg的代码逻辑自行修改。 - - ironic向ipa发送查询命令执行状态请求的tls报错: - - T版的ipa和ironic默认都会开启tls认证的方式向对方发送请求,跟据官网的说明进行关闭即可。 - - 1. 修改ironic配置文件(/etc/ironic/ironic.conf)下面的配置中添加ipa-insecure=1: - - ``` - [agent] - verify_ca = False - - [pxe] - pxe_append_params = nofb nomodeset vga=normal coreos.autologin ipa-insecure=1 - ``` - - 2. ramdisk镜像中添加ipa配置文件/etc/ironic_python_agent/ironic_python_agent.conf并配置tls的配置如下: - - /etc/ironic_python_agent/ironic_python_agent.conf (需要提前创建/etc/ironic_python_agent目录) - - ``` - [DEFAULT] - enable_auto_tls = False - ``` - - 设置权限: - - ``` - chown -R ipa.ipa /etc/ironic_python_agent/ - ``` - - 3. 修改ipa服务的服务启动文件,添加配置文件选项 - - vim usr/lib/systemd/system/ironic-python-agent.service - - ``` - [Unit] - Description=Ironic Python Agent - After=network-online.target - - [Service] - ExecStartPre=/sbin/modprobe vfat - ExecStart=/usr/local/bin/ironic-python-agent --config-file /etc/ironic_python_agent/ironic_python_agent.conf - Restart=always - RestartSec=30s - - [Install] - WantedBy=multi-user.target - ``` - - -在Train中,我们还提供了ironic-inspector等服务,用户可根据自身需求安装。 - -### Kolla 安装 - -Kolla为OpenStack服务提供生产环境可用的容器化部署的功能。 - -Kolla的安装十分简单,只需要安装对应的RPM包即可 - -``` -yum install openstack-kolla openstack-kolla-ansible -``` - -安装完后,就可以使用`kolla-ansible`, `kolla-build`, `kolla-genpwd`, `kolla-mergepwd`等命令进行相关的镜像制作和容器环境部署了。 - -### Trove 安装 -Trove是OpenStack的数据库服务,如果用户使用OpenStack提供的数据库服务则推荐使用该组件。否则,可以不用安装。 - -1. 设置数据库 - - 数据库服务在数据库中存储信息,创建一个**trove**用户可以访问的**trove**数据库,替换**TROVE_DBPASSWORD**为合适的密码 - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE trove CHARACTER SET utf8; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'localhost' \ - IDENTIFIED BY 'TROVE_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'%' \ - IDENTIFIED BY 'TROVE_DBPASSWORD'; - ``` - -2. 创建服务用户认证 - - 1、创建**Trove**服务用户 - - ```shell - openstack user create --domain default --password-prompt trove - openstack role add --project service --user trove admin - openstack service create --name trove --description "Database" database - ``` - **解释:** `TROVE_PASSWORD` 替换为`trove`用户的密码 - - 2、创建**Database**服务访问入口 - - ```shell - openstack endpoint create --region RegionOne database public http://controller:8779/v1.0/%\(tenant_id\)s - openstack endpoint create --region RegionOne database internal http://controller:8779/v1.0/%\(tenant_id\)s - openstack endpoint create --region RegionOne database admin http://controller:8779/v1.0/%\(tenant_id\)s - ``` - -3. 安装和配置**Trove**各组件 - - 1、安装**Trove**包 - ```shell script - yum install openstack-trove python3-troveclient - ``` - - 2. 配置`trove.conf` - ```shell script - vim /etc/trove/trove.conf - - [DEFAULT] - log_dir = /var/log/trove - trove_auth_url = http://controller:5000/ - nova_compute_url = http://controller:8774/v2 - cinder_url = http://controller:8776/v1 - swift_url = http://controller:8080/v1/AUTH_ - rpc_backend = rabbit - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672 - auth_strategy = keystone - add_addresses = True - api_paste_config = /etc/trove/api-paste.ini - nova_proxy_admin_user = admin - nova_proxy_admin_pass = ADMIN_PASSWORD - nova_proxy_admin_tenant_name = service - taskmanager_manager = trove.taskmanager.manager.Manager - use_nova_server_config_drive = True - # Set these if using Neutron Networking - network_driver = trove.network.neutron.NeutronDriver - network_label_regex = .* - - [database] - connection = mysql+pymysql://trove:TROVE_DBPASSWORD@controller/trove - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000/ - auth_url = http://controller:5000/ - auth_type = password - project_domain_name = default - user_domain_name = default - project_name = service - username = trove - password = TROVE_PASSWORD - ``` - **解释:** - - `[Default]`分组中`nova_compute_url` 和 `cinder_url` 为Nova和Cinder在Keystone中创建的endpoint - - `nova_proxy_XXX` 为一个能访问Nova服务的用户信息,上例中使用`admin`用户为例 - - `transport_url` 为`RabbitMQ`连接信息,`RABBIT_PASS`替换为RabbitMQ的密码 - - `[database]`分组中的`connection` 为前面在mysql中为Trove创建的数据库信息 - - Trove的用户信息中`TROVE_PASSWORD`替换为实际trove用户的密码 - - 3. 配置`trove-guestagent.conf` - ```shell script - vim /etc/trove/trove-guestagent.conf - - rabbit_host = controller - rabbit_password = RABBIT_PASS - trove_auth_url = http://controller:5000/ - ``` - **解释:** `guestagent`是trove中一个独立组件,需要预先内置到Trove通过Nova创建的虚拟 - 机镜像中,在创建好数据库实例后,会起guestagent进程,负责通过消息队列(RabbitMQ)向Trove上 - 报心跳,因此需要配置RabbitMQ的用户和密码信息。 - **从Victoria版开始,Trove使用一个统一的镜像来跑不同类型的数据库,数据库服务运行在Guest虚拟机的Docker容器中。** - - `RABBIT_PASS`替换为RabbitMQ的密码 - - 4. 生成数据`Trove`数据库表 - ```shell script - su -s /bin/sh -c "trove-manage db_sync" trove - ``` - -4. 完成安装配置 - 1. 配置**Trove**服务自启动 - ```shell script - systemctl enable openstack-trove-api.service \ - openstack-trove-taskmanager.service \ - openstack-trove-conductor.service - ``` - 2. 启动服务 - ```shell script - systemctl start openstack-trove-api.service \ - openstack-trove-taskmanager.service \ - openstack-trove-conductor.service - ``` -### Swift 安装 - -Swift 提供了弹性可伸缩、高可用的分布式对象存储服务,适合存储大规模非结构化数据。 - -1. 创建服务凭证、API端点。 - - 创建服务凭证 - - ``` shell - #创建swift用户: - openstack user create --domain default --password-prompt swift - #为swift用户添加admin角色: - openstack role add --project service --user swift admin - #创建swift服务实体: - openstack service create --name swift --description "OpenStack Object Storage" object-store - ``` - - 创建swift API 端点: - - ```shell - openstack endpoint create --region RegionOne object-store public http://controller:8080/v1/AUTH_%\(project_id\)s - openstack endpoint create --region RegionOne object-store internal http://controller:8080/v1/AUTH_%\(project_id\)s - openstack endpoint create --region RegionOne object-store admin http://controller:8080/v1 - ``` - - -2. 安装软件包: - - ```shell - yum install openstack-swift-proxy python3-swiftclient python3-keystoneclient python3-keystonemiddleware memcached (CTL) - ``` - -3. 配置proxy-server相关配置 - - Swift RPM包里已经包含了一个基本可用的proxy-server.conf,只需要手动修改其中的ip和swift password即可。 - - ***注意*** - - **注意替换password为您在身份服务中为swift用户选择的密码** - -4. 安装和配置存储节点 (STG) - - 安装支持的程序包: - ```shell - yum install xfsprogs rsync - ``` - - 将/dev/vdb和/dev/vdc设备格式化为 XFS - - ```shell - mkfs.xfs /dev/vdb - mkfs.xfs /dev/vdc - ``` - - 创建挂载点目录结构: - - ```shell - mkdir -p /srv/node/vdb - mkdir -p /srv/node/vdc - ``` - - 找到新分区的 UUID: - - ```shell - blkid - ``` - - 编辑/etc/fstab文件并将以下内容添加到其中: - - ```shell - UUID="" /srv/node/vdb xfs noatime 0 2 - UUID="" /srv/node/vdc xfs noatime 0 2 - ``` - - 挂载设备: - - ```shell - mount /srv/node/vdb - mount /srv/node/vdc - ``` - ***注意*** - - **如果用户不需要容灾功能,以上步骤只需要创建一个设备即可,同时可以跳过下面的rsync配置** - - (可选)创建或编辑/etc/rsyncd.conf文件以包含以下内容: - - ```shell - [DEFAULT] - uid = swift - gid = swift - log file = /var/log/rsyncd.log - pid file = /var/run/rsyncd.pid - address = MANAGEMENT_INTERFACE_IP_ADDRESS - - [account] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/account.lock - - [container] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/container.lock - - [object] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/object.lock - ``` - **替换MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址** - - 启动rsyncd服务并配置它在系统启动时启动: - - ```shell - systemctl enable rsyncd.service - systemctl start rsyncd.service - ``` - -5. 在存储节点安装和配置组件 (STG) - - 安装软件包: - - ```shell - yum install openstack-swift-account openstack-swift-container openstack-swift-object - ``` - - 编辑/etc/swift目录的account-server.conf、container-server.conf和object-server.conf文件,替换bind_ip为存储节点上管理网络的IP地址。 - - 确保挂载点目录结构的正确所有权: - - ```shell - chown -R swift:swift /srv/node - ``` - - 创建recon目录并确保其拥有正确的所有权: - - ```shell - mkdir -p /var/cache/swift - chown -R root:swift /var/cache/swift - chmod -R 775 /var/cache/swift - ``` - -6. 创建账号环 (CTL) - - 切换到/etc/swift目录。 - - ```shell - cd /etc/swift - ``` - - 创建基础account.builder文件: - - ```shell - swift-ring-builder account.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中: - - ```shell - swift-ring-builder account.builder add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6202 --device DEVICE_NAME --weight DEVICE_WEIGHT - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意 *** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder account.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder account.builder rebalance - ``` - -7. 创建容器环 (CTL) - - 切换到`/etc/swift`目录。 - - 创建基础`container.builder`文件: - - ```shell - swift-ring-builder container.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中: - - ```shell - swift-ring-builder container.builder \ - add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6201 \ - --device DEVICE_NAME --weight 100 - - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意*** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder container.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder container.builder rebalance - ``` - -8. 创建对象环 (CTL) - - 切换到`/etc/swift`目录。 - - 创建基础`object.builder`文件: - - ```shell - swift-ring-builder object.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中 - - ```shell - swift-ring-builder object.builder \ - add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6200 \ - --device DEVICE_NAME --weight 100 - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意 *** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder object.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder object.builder rebalance - ``` - - 分发环配置文件: - - 将`account.ring.gz`,`container.ring.gz`以及 `object.ring.gz`文件复制到每个存储节点和运行代理服务的任何其他节点上的`/etc/swift`目录。 - - - -9. 完成安装 - - 编辑`/etc/swift/swift.conf`文件 - - ``` shell - [swift-hash] - swift_hash_path_suffix = test-hash - swift_hash_path_prefix = test-hash - - [storage-policy:0] - name = Policy-0 - default = yes - ``` - - **用唯一值替换 test-hash** - - 将swift.conf文件复制到/etc/swift每个存储节点和运行代理服务的任何其他节点上的目录。 - - 在所有节点上,确保配置目录的正确所有权: - - ```shell - chown -R root:swift /etc/swift - ``` - - 在控制器节点和运行代理服务的任何其他节点上,启动对象存储代理服务及其依赖项,并将它们配置为在系统启动时启动: - - ```shell - systemctl enable openstack-swift-proxy.service memcached.service - systemctl start openstack-swift-proxy.service memcached.service - ``` - - 在存储节点上,启动对象存储服务并将它们配置为在系统启动时启动: - - ```shell - systemctl enable openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service - - systemctl start openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service - - systemctl enable openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service - - systemctl start openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service - - systemctl enable openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service - - systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service - ``` - -### Cyborg 安装 - -Cyborg为OpenStack提供加速器设备的支持,包括 GPU, FPGA, ASIC, NP, SoCs, NVMe/NOF SSDs, ODP, DPDK/SPDK等等。 - -1. 初始化对应数据库 - -``` -CREATE DATABASE cyborg; -GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; -GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -$ openstack user create --domain default --password-prompt cyborg -$ openstack role add --project service --user cyborg admin -$ openstack service create --name cyborg --description "Acceleration Service" accelerator - -$ openstack endpoint create --region RegionOne \ - accelerator public http://:6666/v1 -$ openstack endpoint create --region RegionOne \ - accelerator internal http://:6666/v1 -$ openstack endpoint create --region RegionOne \ - accelerator admin http://:6666/v1 -``` - -3. 安装Cyborg - -``` -yum install openstack-cyborg -``` - -4. 配置Cyborg - -修改`/etc/cyborg/cyborg.conf` - -``` -[DEFAULT] -transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ -use_syslog = False -state_path = /var/lib/cyborg -debug = True - -[database] -connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg - -[service_catalog] -project_domain_id = default -user_domain_id = default -project_name = service -password = PASSWORD -username = cyborg -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password - -[placement] -project_domain_name = Default -project_name = service -user_domain_name = Default -password = PASSWORD -username = placement -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password - -[keystone_authtoken] -memcached_servers = localhost:11211 -project_domain_name = Default -project_name = service -user_domain_name = Default -password = PASSWORD -username = cyborg -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password -``` - -自行修改对应的用户名、密码、IP等信息 - -5. 同步数据库表格 - -``` -cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade -``` - -6. 启动Cyborg服务 - -``` -systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent -systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent -``` - -### Aodh 安装 - -1. 创建数据库 - -``` -CREATE DATABASE aodh; - -GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; - -GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt aodh - -openstack role add --project service --user aodh admin - -openstack service create --name aodh --description "Telemetry" alarming - -openstack endpoint create --region RegionOne alarming public http://controller:8042 - -openstack endpoint create --region RegionOne alarming internal http://controller:8042 - -openstack endpoint create --region RegionOne alarming admin http://controller:8042 -``` - -3. 安装Aodh - -``` -yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient -``` - -4. 修改配置文件 - -``` -[database] -connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh - -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller -auth_strategy = keystone - -[keystone_authtoken] -www_authenticate_uri = http://controller:5000 -auth_url = http://controller:5000 -memcached_servers = controller:11211 -auth_type = password -project_domain_id = default -user_domain_id = default -project_name = service -username = aodh -password = AODH_PASS - -[service_credentials] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_id = default -user_domain_id = default -project_name = service -username = aodh -password = AODH_PASS -interface = internalURL -region_name = RegionOne -``` - -5. 初始化数据库 - -``` -aodh-dbsync -``` - -6. 启动Aodh服务 - -``` -systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service - -systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service -``` - -### Gnocchi 安装 - -1. 创建数据库 - -``` -CREATE DATABASE gnocchi; - -GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; - -GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt gnocchi - -openstack role add --project service --user gnocchi admin - -openstack service create --name gnocchi --description "Metric Service" metric - -openstack endpoint create --region RegionOne metric public http://controller:8041 - -openstack endpoint create --region RegionOne metric internal http://controller:8041 - -openstack endpoint create --region RegionOne metric admin http://controller:8041 -``` - -3. 安装Gnocchi - -``` -yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient -``` - -4. 修改配置文件`/etc/gnocchi/gnocchi.conf` - -``` -[api] -auth_mode = keystone -port = 8041 -uwsgi_mode = http-socket - -[keystone_authtoken] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_name = Default -user_domain_name = Default -project_name = service -username = gnocchi -password = GNOCCHI_PASS -interface = internalURL -region_name = RegionOne - -[indexer] -url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi - -[storage] -# coordination_url is not required but specifying one will improve -# performance with better workload division across workers. -coordination_url = redis://controller:6379 -file_basepath = /var/lib/gnocchi -driver = file -``` - -5. 初始化数据库 - -``` -gnocchi-upgrade -``` - -6. 启动Gnocchi服务 - -``` -systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service - -systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service -``` - -### Ceilometer 安装 - -1. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt ceilometer - -openstack role add --project service --user ceilometer admin - -openstack service create --name ceilometer --description "Telemetry" metering -``` - -2. 安装Ceilometer - -``` -yum install openstack-ceilometer-notification openstack-ceilometer-central -``` - -3. 修改配置文件`/etc/ceilometer/pipeline.yaml` - -``` -publishers: - # set address of Gnocchi - # + filter out Gnocchi-related activity meters (Swift driver) - # + set default archive policy - - gnocchi://?filter_project=service&archive_policy=low -``` - -4. 修改配置文件`/etc/ceilometer/ceilometer.conf` - -``` -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller - -[service_credentials] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_id = default -user_domain_id = default -project_name = service -username = ceilometer -password = CEILOMETER_PASS -interface = internalURL -region_name = RegionOne -``` - -5. 初始化数据库 - -``` -ceilometer-upgrade -``` - -6. 启动Ceilometer服务 - -``` -systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service - -systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service -``` - -### Heat 安装 - -1. 创建**heat**数据库,并授予**heat**数据库正确的访问权限,替换**HEAT_DBPASS**为合适的密码 - -``` -CREATE DATABASE heat; -GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; -GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; -``` - -2. 创建服务凭证,创建**heat**用户,并为其增加**admin**角色 - -``` -openstack user create --domain default --password-prompt heat -openstack role add --project service --user heat admin -``` - -3. 创建**heat**和**heat-cfn**服务及其对应的API端点 - -``` -openstack service create --name heat --description "Orchestration" orchestration -openstack service create --name heat-cfn --description "Orchestration" cloudformation -openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 -openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 -openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 -``` - -4. 创建stack管理的额外信息,包括**heat**domain及其对应domain的admin用户**heat_domain_admin**, -**heat_stack_owner**角色,**heat_stack_user**角色 - -``` -openstack user create --domain heat --password-prompt heat_domain_admin -openstack role add --domain heat --user-domain heat --user heat_domain_admin admin -openstack role create heat_stack_owner -openstack role create heat_stack_user -``` - -5. 安装软件包 - -``` -yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine -``` - -6. 修改配置文件`/etc/heat/heat.conf` - -``` -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller -heat_metadata_server_url = http://controller:8000 -heat_waitcondition_server_url = http://controller:8000/v1/waitcondition -stack_domain_admin = heat_domain_admin -stack_domain_admin_password = HEAT_DOMAIN_PASS -stack_user_domain_name = heat - -[database] -connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat - -[keystone_authtoken] -www_authenticate_uri = http://controller:5000 -auth_url = http://controller:5000 -memcached_servers = controller:11211 -auth_type = password -project_domain_name = default -user_domain_name = default -project_name = service -username = heat -password = HEAT_PASS - -[trustee] -auth_type = password -auth_url = http://controller:5000 -username = heat -password = HEAT_PASS -user_domain_name = default - -[clients_keystone] -auth_uri = http://controller:5000 -``` - -7. 初始化**heat**数据库表 - -``` -su -s /bin/sh -c "heat-manage db_sync" heat -``` - -8. 启动服务 - -``` -systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service -systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service -``` - -## 快速安装 OpenStack - -OpenStack SIG还提供了一键部署OpenStack all in one或三节点的ansible脚本,用户可以使用该脚本快速部署一套基于openEuler RPM的OpenStack环境。下面以all in one举例说明使用方法 - -1. 安装OpenStack SIG工具 - - ```shell - pip install openstack-sig-tool - ``` - -2. 配置openstack yum 源 - - ```shell - yum install openstack-release-train - ``` - - **注意**:如果你的环境的YUM源没有启用EPOL,需要同时配置EPOL - - ```shell - vi /etc/yum.repos.d/openEuler.repo - - [EPOL] - name=EPOL - baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler - EOF - -3. 刷新ansible配置 - - 打开`/usr/local/etc/inventory/all_in_one.yaml`,根据当前机器环境和需求修改对应配置。内容如下 - - ```shell - all: - hosts: - controller: - ansible_host: - ansible_ssh_private_key_file: - ansible_ssh_user: root - vars: - mysql_root_password: root - mysql_project_password: root - rabbitmq_password: root - project_identity_password: root - enabled_service: - - keystone - - neutron - - cinder - - placement - - nova - - glance - - horizon - - aodh - - ceilometer - - cyborg - - gnocchi - - kolla - - heat - - swift - - trove - - tempest - neutron_provider_interface_name: br-ex - default_ext_subnet_range: 10.100.100.0/24 - default_ext_subnet_gateway: 10.100.100.1 - neutron_dataplane_interface_name: eth1 - cinder_block_device: vdb - swift_storage_devices: - - vdc - swift_hash_path_suffix: ash - swift_hash_path_prefix: has - children: - compute: - hosts: controller - storage: - hosts: controller - network: - hosts: controller - vars: - test-key: test-value - dashboard: - hosts: controller - vars: - allowed_host: '*' - kolla: - hosts: controller - vars: - # We add openEuler OS support for kolla in OpenStack Queens/Rocky release - # Set this var to true if you want to use it in Q/R - openeuler_plugin: false - ``` - - **关键配置** - - | 配置项 | 解释 | - |---|---| - | ansible_host | all in one节点IP | - | ansible_ssh_private_key_file | ansible脚本登录all in one节点时使用的登录秘钥 | - | ansible_ssh_user | ansible脚本登录all in one节点时使用的登录用户 | - | enabled_service | 安装服务列表,根据用户需求自行删减 | - | neutron_provider_interface_name | neutron L3网桥名称 | - | default_ext_subnet_range | neutron私网IP段 | - | default_ext_subnet_gateway | neutron私网gateway | - | neutron_dataplane_interface_name | neutron使用的网卡,推荐使用一张新的网卡,以免和现有网卡冲突,发现all in one主机断连的情况 | - | cinder_block_device | cinder使用的卷设备名 | - | swift_storage_devices | swift使用的卷设备名 | - -4. 执行安装命令 - - ```shell - oos env setup all_in_one - ``` - - 该命令执行后,OpenStack all in one环境就部署成功了 - - 环境变量文件在当前用户的根目录下,名叫`.admin-openrc` - -5. 初始化tempest环境 - - 如果用户想使用该环境运行tempest测试的话,可以执行命令`oos env init all_in_one`,会自动把tempest需要的OpenStack资源自动创建好。 - - 命令执行成功后,在用户的根目录下会生成`mytest`目录,进入其中就可以执行`tempest run`命令了。 diff --git a/docs/zh/docs/thirdparty_migration/OpenStack-wallaby.md b/docs/zh/docs/thirdparty_migration/OpenStack-wallaby.md deleted file mode 100644 index fce1caf20..000000000 --- a/docs/zh/docs/thirdparty_migration/OpenStack-wallaby.md +++ /dev/null @@ -1,3214 +0,0 @@ -# OpenStack-Wallaby 部署指南 - - - -- [OpenStack-Wallaby 部署指南](#openstack-wallaby-部署指南) - - [OpenStack 简介](#openstack-简介) - - [约定](#约定) - - [准备环境](#准备环境) - - [环境配置](#环境配置) - - [安装 SQL DataBase](#安装-sql-database) - - [安装 RabbitMQ](#安装-rabbitmq) - - [安装 Memcached](#安装-memcached) - - [安装 OpenStack](#安装-openstack) - - [Keystone 安装](#keystone-安装) - - [Glance 安装](#glance-安装) - - [Placement安装](#placement安装) - - [Nova 安装](#nova-安装) - - [Neutron 安装](#neutron-安装) - - [Cinder 安装](#cinder-安装) - - [horizon 安装](#horizon-安装) - - [Tempest 安装](#tempest-安装) - - [Ironic 安装](#ironic-安装) - - [Kolla 安装](#kolla-安装) - - [Trove 安装](#trove-安装) - - [Swift 安装](#swift-安装) - - [Cyborg 安装](#cyborg-安装) - - [Aodh 安装](#aodh-安装) - - [Gnocchi 安装](#gnocchi-安装) - - [Ceilometer 安装](#ceilometer-安装) - - [Heat 安装](#heat-安装) - - [快速安装 OpenStack](#快速安装-openstack) - - -## OpenStack 简介 - -OpenStack 是一个社区,也是一个项目。它提供了一个部署云的操作平台或工具集,为组织提供可扩展的、灵活的云计算。 - -作为一个开源的云计算管理平台,OpenStack 由nova、cinder、neutron、glance、keystone、horizon等几个主要的组件组合起来完成具体工作。OpenStack 支持几乎所有类型的云环境,项目目标是提供实施简单、可大规模扩展、丰富、标准统一的云计算管理平台。OpenStack 通过各种互补的服务提供了基础设施即服务(IaaS)的解决方案,每个服务提供 API 进行集成。 - -openEuler 22.03 LTS 版本官方源已经支持 OpenStack-Wallaby 版本,用户可以配置好 yum 源后根据此文档进行 OpenStack 部署。 - -## 约定 - -OpenStack 支持多种形态部署,此文档支持`ALL in One`以及`Distributed`两种部署方式,按照如下方式约定: - -`ALL in One`模式: - -```text -忽略所有可能的后缀 -``` - -`Distributed`模式: - -```text -以 `(CTL)` 为后缀表示此条配置或者命令仅适用`控制节点` -以 `(CPT)` 为后缀表示此条配置或者命令仅适用`计算节点` -以 `(STG)` 为后缀表示此条配置或者命令仅适用`存储节点` -除此之外表示此条配置或者命令同时适用`控制节点`和`计算节点` -``` - -***注意*** - -涉及到以上约定的服务如下: - -- Cinder -- Nova -- Neutron - -## 准备环境 - -### 环境配置 - -1. 配置 22.03 LTS 官方yum源,需要启用EPOL软件仓以支持OpenStack - - ```shell - yum update - yum install openstack-release-wallaby - yum clean all && yum makecache - ``` - - **注意**:如果你的环境的YUM源没有启用EPOL,需要同时配置EPOL - - ```shell - vi /etc/yum.repos.d/openEuler.repo - - [EPOL] - name=EPOL - baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler - EOF - -2. 修改主机名以及映射 - - 设置各个节点的主机名 - - ```shell - hostnamectl set-hostname controller (CTL) - hostnamectl set-hostname compute (CPT) - ``` - - 假设controller节点的IP是`10.0.0.11`,compute节点的IP是`10.0.0.12`(如果存在的话),则于`/etc/hosts`新增如下: - - ```shell - 10.0.0.11 controller - 10.0.0.12 compute - ``` - -### 安装 SQL DataBase - -1. 执行如下命令,安装软件包。 - - ```shell - yum install mariadb mariadb-server python3-PyMySQL - ``` - -2. 执行如下命令,创建并编辑 `/etc/my.cnf.d/openstack.cnf` 文件。 - - ```shell - vim /etc/my.cnf.d/openstack.cnf - - [mysqld] - bind-address = 10.0.0.11 - default-storage-engine = innodb - innodb_file_per_table = on - max_connections = 4096 - collation-server = utf8_general_ci - character-set-server = utf8 - ``` - - ***注意*** - - **其中 `bind-address` 设置为控制节点的管理IP地址。** - -3. 启动 DataBase 服务,并为其配置开机自启动: - - ```shell - systemctl enable mariadb.service - systemctl start mariadb.service - ``` - -4. 配置DataBase的默认密码(可选) - - ```shell - mysql_secure_installation - ``` - - ***注意*** - - **根据提示进行即可** - -### 安装 RabbitMQ - -1. 执行如下命令,安装软件包。 - - ```shell - yum install rabbitmq-server - ``` - -2. 启动 RabbitMQ 服务,并为其配置开机自启动。 - - ```shell - systemctl enable rabbitmq-server.service - systemctl start rabbitmq-server.service - ``` - -3. 添加 OpenStack用户。 - - ```shell - rabbitmqctl add_user openstack RABBIT_PASS - ``` - - ***注意*** - - **替换 `RABBIT_PASS`,为 OpenStack 用户设置密码** - -4. 设置openstack用户权限,允许进行配置、写、读: - - ```shell - rabbitmqctl set_permissions openstack ".*" ".*" ".*" - ``` - -### 安装 Memcached - -1. 执行如下命令,安装依赖软件包。 - - ```shell - yum install memcached python3-memcached - ``` - -2. 编辑 `/etc/sysconfig/memcached` 文件。 - - ```shell - vim /etc/sysconfig/memcached - - OPTIONS="-l 127.0.0.1,::1,controller" - ``` - -3. 执行如下命令,启动 Memcached 服务,并为其配置开机启动。 - - ```shell - systemctl enable memcached.service - systemctl start memcached.service - ``` - - ***注意*** - - **服务启动后,可以通过命令`memcached-tool controller stats`确保启动正常,服务可用,其中可以将`controller`替换为控制节点的管理IP地址。** - -## 安装 OpenStack - -### Keystone 安装 - -1. 创建 keystone 数据库并授权。 - - ``` sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE keystone; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'localhost' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON keystone.* TO 'keystone'@'%' \ - IDENTIFIED BY 'KEYSTONE_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `KEYSTONE_DBPASS`,为 Keystone 数据库设置密码** - -2. 安装软件包。 - - ```shell - yum install openstack-keystone httpd mod_wsgi - ``` - -3. 配置keystone相关配置 - - ```shell - vim /etc/keystone/keystone.conf - - [database] - connection = mysql+pymysql://keystone:KEYSTONE_DBPASS@controller/keystone - - [token] - provider = fernet - ``` - - ***解释*** - - [database]部分,配置数据库入口 - - [token]部分,配置token provider - - ***注意:*** - - **替换 `KEYSTONE_DBPASS` 为 Keystone 数据库的密码** - -4. 同步数据库。 - - ```shell - su -s /bin/sh -c "keystone-manage db_sync" keystone - ``` - -5. 初始化Fernet密钥仓库。 - - ```shell - keystone-manage fernet_setup --keystone-user keystone --keystone-group keystone - keystone-manage credential_setup --keystone-user keystone --keystone-group keystone - ``` - -6. 启动服务。 - - ```shell - keystone-manage bootstrap --bootstrap-password ADMIN_PASS \ - --bootstrap-admin-url http://controller:5000/v3/ \ - --bootstrap-internal-url http://controller:5000/v3/ \ - --bootstrap-public-url http://controller:5000/v3/ \ - --bootstrap-region-id RegionOne - ``` - - ***注意*** - - **替换 `ADMIN_PASS`,为 admin 用户设置密码** - -7. 配置Apache HTTP server - - ```shell - vim /etc/httpd/conf/httpd.conf - - ServerName controller - ``` - - ```shell - ln -s /usr/share/keystone/wsgi-keystone.conf /etc/httpd/conf.d/ - ``` - - ***解释*** - - 配置 `ServerName` 项引用控制节点 - - ***注意*** - **如果 `ServerName` 项不存在则需要创建** - -8. 启动Apache HTTP服务。 - - ```shell - systemctl enable httpd.service - systemctl start httpd.service - ``` - -9. 创建环境变量配置。 - - ```shell - cat << EOF >> ~/.admin-openrc - export OS_PROJECT_DOMAIN_NAME=Default - export OS_USER_DOMAIN_NAME=Default - export OS_PROJECT_NAME=admin - export OS_USERNAME=admin - export OS_PASSWORD=ADMIN_PASS - export OS_AUTH_URL=http://controller:5000/v3 - export OS_IDENTITY_API_VERSION=3 - export OS_IMAGE_API_VERSION=2 - EOF - ``` - - ***注意*** - - **替换 `ADMIN_PASS` 为 admin 用户的密码** - -10. 依次创建domain, projects, users, roles,需要先安装好python3-openstackclient: - - ```shell - yum install python3-openstackclient - ``` - - 导入环境变量 - - ```shell - source ~/.admin-openrc - ``` - - 创建project `service`,其中 domain `default` 在 keystone-manage bootstrap 时已创建 - - ```shell - openstack domain create --description "An Example Domain" example - ``` - - ```shell - openstack project create --domain default --description "Service Project" service - ``` - - 创建(non-admin)project `myproject`,user `myuser` 和 role `myrole`,为 `myproject` 和 `myuser` 添加角色`myrole` - - ```shell - openstack project create --domain default --description "Demo Project" myproject - openstack user create --domain default --password-prompt myuser - openstack role create myrole - openstack role add --project myproject --user myuser myrole - ``` - -11. 验证 - - 取消临时环境变量OS_AUTH_URL和OS_PASSWORD: - - ```shell - source ~/.admin-openrc - unset OS_AUTH_URL OS_PASSWORD - ``` - - 为admin用户请求token: - - ```shell - openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name admin --os-username admin token issue - ``` - - 为myuser用户请求token: - - ```shell - openstack --os-auth-url http://controller:5000/v3 \ - --os-project-domain-name Default --os-user-domain-name Default \ - --os-project-name myproject --os-username myuser token issue - ``` - -### Glance 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE glance; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'localhost' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON glance.* TO 'glance'@'%' \ - IDENTIFIED BY 'GLANCE_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意:*** - - **替换 `GLANCE_DBPASS`,为 glance 数据库设置密码** - - 创建服务凭证 - - ```shell - source ~/.admin-openrc - - openstack user create --domain default --password-prompt glance - openstack role add --project service --user glance admin - openstack service create --name glance --description "OpenStack Image" image - ``` - - 创建镜像服务API端点: - - ```shell - openstack endpoint create --region RegionOne image public http://controller:9292 - openstack endpoint create --region RegionOne image internal http://controller:9292 - openstack endpoint create --region RegionOne image admin http://controller:9292 - ``` - -2. 安装软件包 - - ```shell - yum install openstack-glance - ``` - -3. 配置glance相关配置: - - ```shell - vim /etc/glance/glance-api.conf - - [database] - connection = mysql+pymysql://glance:GLANCE_DBPASS@controller/glance - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = glance - password = GLANCE_PASS - - [paste_deploy] - flavor = keystone - - [glance_store] - stores = file,http - default_store = file - filesystem_store_datadir = /var/lib/glance/images/ - ``` - - ***解释:*** - - [database]部分,配置数据库入口 - - [keystone_authtoken] [paste_deploy]部分,配置身份认证服务入口 - - [glance_store]部分,配置本地文件系统存储和镜像文件的位置 - - ***注意*** - - **替换 `GLANCE_DBPASS` 为 glance 数据库的密码** - - **替换 `GLANCE_PASS` 为 glance 用户的密码** - -4. 同步数据库: - - ```shell - su -s /bin/sh -c "glance-manage db_sync" glance - ``` - -5. 启动服务: - - ```shell - systemctl enable openstack-glance-api.service - systemctl start openstack-glance-api.service - ``` - -6. 验证 - - 下载镜像 - - ```shell - source ~/.admin-openrc - - wget http://download.cirros-cloud.net/0.4.0/cirros-0.4.0-x86_64-disk.img - ``` - - ***注意*** - - **如果您使用的环境是鲲鹏架构,请下载aarch64版本的镜像;已对镜像cirros-0.5.2-aarch64-disk.img进行测试。** - - 向Image服务上传镜像: - - ```shell - openstack image create --disk-format qcow2 --container-format bare \ - --file cirros-0.4.0-x86_64-disk.img --public cirros - ``` - - 确认镜像上传并验证属性: - - ```shell - openstack image list - ``` - -### Placement安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - 作为 root 用户访问数据库,创建 placement 数据库并授权。 - - ```shell - mysql -u root -p - MariaDB [(none)]> CREATE DATABASE placement; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'localhost' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON placement.* TO 'placement'@'%' \ - IDENTIFIED BY 'PLACEMENT_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `PLACEMENT_DBPASS` 为 placement 数据库设置密码** - - ```shell - source admin-openrc - ``` - - 执行如下命令,创建 placement 服务凭证、创建 placement 用户以及添加‘admin’角色到用户‘placement’。 - - 创建Placement API服务 - - ```shell - openstack user create --domain default --password-prompt placement - openstack role add --project service --user placement admin - openstack service create --name placement --description "Placement API" placement - ``` - - 创建placement服务API端点: - - ```shell - openstack endpoint create --region RegionOne placement public http://controller:8778 - openstack endpoint create --region RegionOne placement internal http://controller:8778 - openstack endpoint create --region RegionOne placement admin http://controller:8778 - ``` - -2. 安装和配置 - - 安装软件包: - - ```shell - yum install openstack-placement-api - ``` - - 配置placement: - - 编辑 /etc/placement/placement.conf 文件: - - 在[placement_database]部分,配置数据库入口 - - 在[api] [keystone_authtoken]部分,配置身份认证服务入口 - - ```shell - # vim /etc/placement/placement.conf - [placement_database] - # ... - connection = mysql+pymysql://placement:PLACEMENT_DBPASS@controller/placement - [api] - # ... - auth_strategy = keystone - [keystone_authtoken] - # ... - auth_url = http://controller:5000/v3 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = placement - password = PLACEMENT_PASS - ``` - - 其中,替换 PLACEMENT_DBPASS 为 placement 数据库的密码,替换 PLACEMENT_PASS 为 placement 用户的密码。 - - 同步数据库: - - ```shell - su -s /bin/sh -c "placement-manage db sync" placement - ``` - - 启动httpd服务: - - ```shell - systemctl restart httpd - ``` - -3. 验证 - - 执行如下命令,执行状态检查: - - ```shell - . admin-openrc - placement-status upgrade check - ``` - - 安装osc-placement,列出可用的资源类别及特性: - - ```shell - yum install python3-osc-placement - openstack --os-placement-api-version 1.2 resource class list --sort-column name - openstack --os-placement-api-version 1.6 trait list --sort-column name - ``` - -### Nova 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p (CTL) - - MariaDB [(none)]> CREATE DATABASE nova_api; - MariaDB [(none)]> CREATE DATABASE nova; - MariaDB [(none)]> CREATE DATABASE nova_cell0; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_api.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'localhost' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON nova_cell0.* TO 'nova'@'%' \ - IDENTIFIED BY 'NOVA_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换NOVA_DBPASS,为nova数据库设置密码** - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 创建nova服务凭证: - - ```shell - openstack user create --domain default --password-prompt nova (CTL) - openstack role add --project service --user nova admin (CTL) - openstack service create --name nova --description "OpenStack Compute" compute (CTL) - ``` - - 创建nova API端点: - - ```shell - openstack endpoint create --region RegionOne compute public http://controller:8774/v2.1 (CTL) - openstack endpoint create --region RegionOne compute internal http://controller:8774/v2.1 (CTL) - openstack endpoint create --region RegionOne compute admin http://controller:8774/v2.1 (CTL) - ``` - -2. 安装软件包 - - ```shell - yum install openstack-nova-api openstack-nova-conductor \ (CTL) - openstack-nova-novncproxy openstack-nova-scheduler - - yum install openstack-nova-compute (CPT) - ``` - - ***注意*** - - **如果为arm64结构,还需要执行以下命令** - - ```shell - yum install edk2-aarch64 (CPT) - ``` - -3. 配置nova相关配置 - - ```shell - vim /etc/nova/nova.conf - - [DEFAULT] - enabled_apis = osapi_compute,metadata - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - my_ip = 10.0.0.1 - use_neutron = true - firewall_driver = nova.virt.firewall.NoopFirewallDriver - compute_driver=libvirt.LibvirtDriver (CPT) - instances_path = /var/lib/nova/instances/ (CPT) - lock_path = /var/lib/nova/tmp (CPT) - - [api_database] - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova_api (CTL) - - [database] - connection = mysql+pymysql://nova:NOVA_DBPASS@controller/nova (CTL) - - [api] - auth_strategy = keystone - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000/ - auth_url = http://controller:5000/ - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = nova - password = NOVA_PASS - - [vnc] - enabled = true - server_listen = $my_ip - server_proxyclient_address = $my_ip - novncproxy_base_url = http://controller:6080/vnc_auto.html (CPT) - - [libvirt] - virt_type = qemu (CPT) - cpu_mode = custom (CPT) - cpu_model = cortex-a72 (CPT) - - [glance] - api_servers = http://controller:9292 - - [oslo_concurrency] - lock_path = /var/lib/nova/tmp (CTL) - - [placement] - region_name = RegionOne - project_domain_name = Default - project_name = service - auth_type = password - user_domain_name = Default - auth_url = http://controller:5000/v3 - username = placement - password = PLACEMENT_PASS - - [neutron] - auth_url = http://controller:5000 - auth_type = password - project_domain_name = default - user_domain_name = default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true (CTL) - metadata_proxy_shared_secret = METADATA_SECRET (CTL) - ``` - - ***解释*** - - [default]部分,启用计算和元数据的API,配置RabbitMQ消息队列入口,配置my_ip,启用网络服务neutron; - - [api_database] [database]部分,配置数据库入口; - - [api] [keystone_authtoken]部分,配置身份认证服务入口; - - [vnc]部分,启用并配置远程控制台入口; - - [glance]部分,配置镜像服务API的地址; - - [oslo_concurrency]部分,配置lock path; - - [placement]部分,配置placement服务的入口。 - - ***注意*** - - **替换 `RABBIT_PASS` 为 RabbitMQ 中 openstack 账户的密码;** - - **配置 `my_ip` 为控制节点的管理IP地址;** - - **替换 `NOVA_DBPASS` 为nova数据库的密码;** - - **替换 `NOVA_PASS` 为nova用户的密码;** - - **替换 `PLACEMENT_PASS` 为placement用户的密码;** - - **替换 `NEUTRON_PASS` 为neutron用户的密码;** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - - **额外** - - 确定是否支持虚拟机硬件加速(x86架构): - - ```shell - egrep -c '(vmx|svm)' /proc/cpuinfo (CPT) - ``` - - 如果返回值为0则不支持硬件加速,需要配置libvirt使用QEMU而不是KVM: - - ```shell - vim /etc/nova/nova.conf (CPT) - - [libvirt] - virt_type = qemu - ``` - - 如果返回值为1或更大的值,则支持硬件加速,不需要进行额外的配置 - - ***注意*** - - **如果为arm64结构,还需要执行以下命令** - - ```shell - vim /etc/libvirt/qemu.conf - - nvram = ["/usr/share/AAVMF/AAVMF_CODE.fd: \ - /usr/share/AAVMF/AAVMF_VARS.fd", \ - "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw: \ - /usr/share/edk2/aarch64/vars-template-pflash.raw"] - - vim /etc/qemu/firmware/edk2-aarch64.json - - { - "description": "UEFI firmware for ARM64 virtual machines", - "interface-types": [ - "uefi" - ], - "mapping": { - "device": "flash", - "executable": { - "filename": "/usr/share/edk2/aarch64/QEMU_EFI-pflash.raw", - "format": "raw" - }, - "nvram-template": { - "filename": "/usr/share/edk2/aarch64/vars-template-pflash.raw", - "format": "raw" - } - }, - "targets": [ - { - "architecture": "aarch64", - "machines": [ - "virt-*" - ] - } - ], - "features": [ - - ], - "tags": [ - - ] - } - - (CPT) - ``` - -4. 同步数据库 - - 同步nova-api数据库: - - ```shell - su -s /bin/sh -c "nova-manage api_db sync" nova (CTL) - ``` - - 注册cell0数据库: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova (CTL) - ``` - - 创建cell1 cell: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 create_cell --name=cell1 --verbose" nova (CTL) - ``` - - 同步nova数据库: - - ```shell - su -s /bin/sh -c "nova-manage db sync" nova (CTL) - ``` - - 验证cell0和cell1注册正确: - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 list_cells" nova (CTL) - ``` - - 添加计算节点到openstack集群 - - ```shell - su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova (CPT) - ``` - -5. 启动服务 - - ```shell - systemctl enable \ (CTL) - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - - systemctl start \ (CTL) - openstack-nova-api.service \ - openstack-nova-scheduler.service \ - openstack-nova-conductor.service \ - openstack-nova-novncproxy.service - ``` - - ```shell - systemctl enable libvirtd.service openstack-nova-compute.service (CPT) - systemctl start libvirtd.service openstack-nova-compute.service (CPT) - ``` - -6. 验证 - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 列出服务组件,验证每个流程都成功启动和注册: - - ```shell - openstack compute service list (CTL) - ``` - - 列出身份服务中的API端点,验证与身份服务的连接: - - ```shell - openstack catalog list (CTL) - ``` - - 列出镜像服务中的镜像,验证与镜像服务的连接: - - ```shell - openstack image list (CTL) - ``` - - 检查cells是否运作成功,以及其他必要条件是否已具备。 - - ```shell - nova-status upgrade check (CTL) - ``` - -### Neutron 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p (CTL) - - MariaDB [(none)]> CREATE DATABASE neutron; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'localhost' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON neutron.* TO 'neutron'@'%' \ - IDENTIFIED BY 'NEUTRON_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `NEUTRON_DBPASS` 为 neutron 数据库设置密码。** - - ```shell - source ~/.admin-openrc (CTL) - ``` - - 创建neutron服务凭证 - - ```shell - openstack user create --domain default --password-prompt neutron (CTL) - openstack role add --project service --user neutron admin (CTL) - openstack service create --name neutron --description "OpenStack Networking" network (CTL) - ``` - - 创建Neutron服务API端点: - - ```shell - openstack endpoint create --region RegionOne network public http://controller:9696 (CTL) - openstack endpoint create --region RegionOne network internal http://controller:9696 (CTL) - openstack endpoint create --region RegionOne network admin http://controller:9696 (CTL) - ``` - -2. 安装软件包: - - ```shell - yum install openstack-neutron openstack-neutron-linuxbridge ebtables ipset \ (CTL) - openstack-neutron-ml2 - ``` - - ```shell - yum install openstack-neutron-linuxbridge ebtables ipset (CPT) - ``` - -3. 配置neutron相关配置: - - 配置主体配置 - - ```shell - vim /etc/neutron/neutron.conf - - [database] - connection = mysql+pymysql://neutron:NEUTRON_DBPASS@controller/neutron (CTL) - - [DEFAULT] - core_plugin = ml2 (CTL) - service_plugins = router (CTL) - allow_overlapping_ips = true (CTL) - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - notify_nova_on_port_status_changes = true (CTL) - notify_nova_on_port_data_changes = true (CTL) - api_workers = 3 (CTL) - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = neutron - password = NEUTRON_PASS - - [nova] - auth_url = http://controller:5000 (CTL) - auth_type = password (CTL) - project_domain_name = Default (CTL) - user_domain_name = Default (CTL) - region_name = RegionOne (CTL) - project_name = service (CTL) - username = nova (CTL) - password = NOVA_PASS (CTL) - - [oslo_concurrency] - lock_path = /var/lib/neutron/tmp - ``` - - ***解释*** - - [database]部分,配置数据库入口; - - [default]部分,启用ml2插件和router插件,允许ip地址重叠,配置RabbitMQ消息队列入口; - - [default] [keystone]部分,配置身份认证服务入口; - - [default] [nova]部分,配置网络来通知计算网络拓扑的变化; - - [oslo_concurrency]部分,配置lock path。 - - ***注意*** - - **替换`NEUTRON_DBPASS`为 neutron 数据库的密码;** - - **替换`RABBIT_PASS`为 RabbitMQ中openstack 账户的密码;** - - **替换`NEUTRON_PASS`为 neutron 用户的密码;** - - **替换`NOVA_PASS`为 nova 用户的密码。** - - 配置ML2插件: - - ```shell - vim /etc/neutron/plugins/ml2/ml2_conf.ini - - [ml2] - type_drivers = flat,vlan,vxlan - tenant_network_types = vxlan - mechanism_drivers = linuxbridge,l2population - extension_drivers = port_security - - [ml2_type_flat] - flat_networks = provider - - [ml2_type_vxlan] - vni_ranges = 1:1000 - - [securitygroup] - enable_ipset = true - ``` - - 创建/etc/neutron/plugin.ini的符号链接 - - ```shell - ln -s /etc/neutron/plugins/ml2/ml2_conf.ini /etc/neutron/plugin.ini - ``` - - **注意** - - **[ml2]部分,启用 flat、vlan、vxlan 网络,启用 linuxbridge 及 l2population 机制,启用端口安全扩展驱动;** - - **[ml2_type_flat]部分,配置 flat 网络为 provider 虚拟网络;** - - **[ml2_type_vxlan]部分,配置 VXLAN 网络标识符范围;** - - **[securitygroup]部分,配置允许 ipset。** - - **补充** - - **l2 的具体配置可以根据用户需求自行修改,本文使用的是provider network + linuxbridge** - - 配置 Linux bridge 代理: - - ```shell - vim /etc/neutron/plugins/ml2/linuxbridge_agent.ini - - [linux_bridge] - physical_interface_mappings = provider:PROVIDER_INTERFACE_NAME - - [vxlan] - enable_vxlan = true - local_ip = OVERLAY_INTERFACE_IP_ADDRESS - l2_population = true - - [securitygroup] - enable_security_group = true - firewall_driver = neutron.agent.linux.iptables_firewall.IptablesFirewallDriver - ``` - - ***解释*** - - [linux_bridge]部分,映射 provider 虚拟网络到物理网络接口; - - [vxlan]部分,启用 vxlan 覆盖网络,配置处理覆盖网络的物理网络接口 IP 地址,启用 layer-2 population; - - [securitygroup]部分,允许安全组,配置 linux bridge iptables 防火墙驱动。 - - ***注意*** - - **替换`PROVIDER_INTERFACE_NAME`为物理网络接口;** - - **替换`OVERLAY_INTERFACE_IP_ADDRESS`为控制节点的管理IP地址。** - - 配置Layer-3代理: - - ```shell - vim /etc/neutron/l3_agent.ini (CTL) - - [DEFAULT] - interface_driver = linuxbridge - ``` - - ***解释*** - - 在[default]部分,配置接口驱动为linuxbridge - - 配置DHCP代理: - - ```shell - vim /etc/neutron/dhcp_agent.ini (CTL) - - [DEFAULT] - interface_driver = linuxbridge - dhcp_driver = neutron.agent.linux.dhcp.Dnsmasq - enable_isolated_metadata = true - ``` - - ***解释*** - - [default]部分,配置linuxbridge接口驱动、Dnsmasq DHCP驱动,启用隔离的元数据。 - - 配置metadata代理: - - ```shell - vim /etc/neutron/metadata_agent.ini (CTL) - - [DEFAULT] - nova_metadata_host = controller - metadata_proxy_shared_secret = METADATA_SECRET - ``` - - ***解释*** - - [default]部分,配置元数据主机和shared secret。 - - ***注意*** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - -4. 配置nova相关配置 - - ```shell - vim /etc/nova/nova.conf - - [neutron] - auth_url = http://controller:5000 - auth_type = password - project_domain_name = Default - user_domain_name = Default - region_name = RegionOne - project_name = service - username = neutron - password = NEUTRON_PASS - service_metadata_proxy = true (CTL) - metadata_proxy_shared_secret = METADATA_SECRET (CTL) - ``` - - ***解释*** - - [neutron]部分,配置访问参数,启用元数据代理,配置secret。 - - ***注意*** - - **替换`NEUTRON_PASS`为 neutron 用户的密码;** - - **替换`METADATA_SECRET`为合适的元数据代理secret。** - -5. 同步数据库: - - ```shell - su -s /bin/sh -c "neutron-db-manage --config-file /etc/neutron/neutron.conf \ - --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron - ``` - -6. 重启计算API服务: - - ```shell - systemctl restart openstack-nova-api.service - ``` - -7. 启动网络服务 - - ```shell - systemctl enable neutron-server.service neutron-linuxbridge-agent.service \ (CTL) - neutron-dhcp-agent.service neutron-metadata-agent.service \ - systemctl enable neutron-l3-agent.service - systemctl restart openstack-nova-api.service neutron-server.service (CTL) - neutron-linuxbridge-agent.service neutron-dhcp-agent.service \ - neutron-metadata-agent.service neutron-l3-agent.service - - systemctl enable neutron-linuxbridge-agent.service (CPT) - systemctl restart neutron-linuxbridge-agent.service openstack-nova-compute.service (CPT) - ``` - -8. 验证 - - 验证 neutron 代理启动成功: - - ```shell - openstack network agent list - ``` - -### Cinder 安装 - -1. 创建数据库、服务凭证和 API 端点 - - 创建数据库: - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE cinder; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'localhost' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON cinder.* TO 'cinder'@'%' \ - IDENTIFIED BY 'CINDER_DBPASS'; - MariaDB [(none)]> exit - ``` - - ***注意*** - - **替换 `CINDER_DBPASS` 为cinder数据库设置密码。** - - ```shell - source ~/.admin-openrc - ``` - - 创建cinder服务凭证: - - ```shell - openstack user create --domain default --password-prompt cinder - openstack role add --project service --user cinder admin - openstack service create --name cinderv2 --description "OpenStack Block Storage" volumev2 - openstack service create --name cinderv3 --description "OpenStack Block Storage" volumev3 - ``` - - 创建块存储服务API端点: - - ```shell - openstack endpoint create --region RegionOne volumev2 public http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev2 internal http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev2 admin http://controller:8776/v2/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 public http://controller:8776/v3/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 internal http://controller:8776/v3/%\(project_id\)s - openstack endpoint create --region RegionOne volumev3 admin http://controller:8776/v3/%\(project_id\)s - ``` - -2. 安装软件包: - - ```shell - yum install openstack-cinder-api openstack-cinder-scheduler (CTL) - ``` - - ```shell - yum install lvm2 device-mapper-persistent-data scsi-target-utils rpcbind nfs-utils \ (STG) - openstack-cinder-volume openstack-cinder-backup - ``` - -3. 准备存储设备,以下仅为示例: - - ```shell - pvcreate /dev/vdb - vgcreate cinder-volumes /dev/vdb - - vim /etc/lvm/lvm.conf - - - devices { - ... - filter = [ "a/vdb/", "r/.*/"] - ``` - - ***解释*** - - 在devices部分,添加过滤以接受/dev/vdb设备拒绝其他设备。 - -4. 准备NFS - - ```shell - mkdir -p /root/cinder/backup - - cat << EOF >> /etc/export - /root/cinder/backup 192.168.1.0/24(rw,sync,no_root_squash,no_all_squash) - EOF - - ``` - -5. 配置cinder相关配置: - - ```shell - vim /etc/cinder/cinder.conf - - [DEFAULT] - transport_url = rabbit://openstack:RABBIT_PASS@controller - auth_strategy = keystone - my_ip = 10.0.0.11 - enabled_backends = lvm (STG) - backup_driver=cinder.backup.drivers.nfs.NFSBackupDriver (STG) - backup_share=HOST:PATH (STG) - - [database] - connection = mysql+pymysql://cinder:CINDER_DBPASS@controller/cinder - - [keystone_authtoken] - www_authenticate_uri = http://controller:5000 - auth_url = http://controller:5000 - memcached_servers = controller:11211 - auth_type = password - project_domain_name = Default - user_domain_name = Default - project_name = service - username = cinder - password = CINDER_PASS - - [oslo_concurrency] - lock_path = /var/lib/cinder/tmp - - [lvm] - volume_driver = cinder.volume.drivers.lvm.LVMVolumeDriver (STG) - volume_group = cinder-volumes (STG) - iscsi_protocol = iscsi (STG) - iscsi_helper = tgtadm (STG) - ``` - - ***解释*** - - [database]部分,配置数据库入口; - - [DEFAULT]部分,配置RabbitMQ消息队列入口,配置my_ip; - - [DEFAULT] [keystone_authtoken]部分,配置身份认证服务入口; - - [oslo_concurrency]部分,配置lock path。 - - ***注意*** - - **替换`CINDER_DBPASS`为 cinder 数据库的密码;** - - **替换`RABBIT_PASS`为 RabbitMQ 中 openstack 账户的密码;** - - **配置`my_ip`为控制节点的管理 IP 地址;** - - **替换`CINDER_PASS`为 cinder 用户的密码;** - - **替换`HOST:PATH`为 NFS 的HOSTIP和共享路径的密码;** - -6. 同步数据库: - - ```shell - su -s /bin/sh -c "cinder-manage db sync" cinder (CTL) - ``` - -7. 配置nova: - - ```shell - vim /etc/nova/nova.conf (CTL) - - [cinder] - os_region_name = RegionOne - ``` - -8. 重启计算API服务 - - ```shell - systemctl restart openstack-nova-api.service - ``` - -9. 启动cinder服务 - - ```shell - systemctl enable openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) - systemctl start openstack-cinder-api.service openstack-cinder-scheduler.service (CTL) - ``` - - ```shell - systemctl enable rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) - openstack-cinder-volume.service \ - openstack-cinder-backup.service - systemctl start rpcbind.service nfs-server.service tgtd.service iscsid.service \ (STG) - openstack-cinder-volume.service \ - openstack-cinder-backup.service - ``` - - ***注意*** - - 当cinder使用tgtadm的方式挂卷的时候,要修改/etc/tgt/tgtd.conf,内容如下,保证tgtd可以发现cinder-volume的iscsi target。 - - ```shell - include /var/lib/cinder/volumes/* - ``` - -10. 验证 - - ```shell - source ~/.admin-openrc - openstack volume service list - ``` - -### horizon 安装 - -1. 安装软件包 - - ```shell - yum install openstack-dashboard - ``` - -2. 修改文件 - - 修改变量 - - ```text - vim /etc/openstack-dashboard/local_settings - - OPENSTACK_HOST = "controller" - ALLOWED_HOSTS = ['*', ] - - SESSION_ENGINE = 'django.contrib.sessions.backends.cache' - - CACHES = { - 'default': { - 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', - 'LOCATION': 'controller:11211', - } - } - - OPENSTACK_KEYSTONE_URL = "http://%s:5000/v3" % OPENSTACK_HOST - OPENSTACK_KEYSTONE_MULTIDOMAIN_SUPPORT = True - OPENSTACK_KEYSTONE_DEFAULT_DOMAIN = "Default" - OPENSTACK_KEYSTONE_DEFAULT_ROLE = "user" - - OPENSTACK_API_VERSIONS = { - "identity": 3, - "image": 2, - "volume": 3, - } - ``` - -3. 重启 httpd 服务 - - ```shell - systemctl restart httpd.service memcached.service - ``` - -4. 验证 - 打开浏览器,输入网址,登录 horizon。 - - ***注意*** - - **替换HOSTIP为控制节点管理平面IP地址** - -### Tempest 安装 - -Tempest是OpenStack的集成测试服务,如果用户需要全面自动化测试已安装的OpenStack环境的功能,则推荐使用该组件。否则,可以不用安装。 - -1. 安装Tempest - - ```shell - yum install openstack-tempest - ``` - -2. 初始化目录 - - ```shell - tempest init mytest - ``` - -3. 修改配置文件。 - - ```shell - cd mytest - vi etc/tempest.conf - ``` - - tempest.conf中需要配置当前OpenStack环境的信息,具体内容可以参考[官方示例](https://docs.openstack.org/tempest/latest/sampleconf.html) - -4. 执行测试 - - ```shell - tempest run - ``` - -5. 安装tempest扩展(可选) - OpenStack各个服务本身也提供了一些tempest测试包,用户可以安装这些包来丰富tempest的测试内容。在Wallaby中,我们提供了Cinder、Glance、Keystone、Ironic、Trove的扩展测试,用户可以执行如下命令进行安装使用: - ``` - yum install python3-cinder-tempest-plugin python3-glance-tempest-plugin python3-ironic-tempest-plugin python3-keystone-tempest-plugin python3-trove-tempest-plugin - ``` - -### Ironic 安装 - -Ironic是OpenStack的裸金属服务,如果用户需要进行裸机部署则推荐使用该组件。否则,可以不用安装。 - -1. 设置数据库 - - 裸金属服务在数据库中存储信息,创建一个**ironic**用户可以访问的**ironic**数据库,替换**IRONIC_DBPASSWORD**为合适的密码 - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE ironic CHARACTER SET utf8; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'localhost' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic.* TO 'ironic'@'%' \ - IDENTIFIED BY 'IRONIC_DBPASSWORD'; - ``` - -2. 创建服务用户认证 - - 1、创建Bare Metal服务用户 - - ```shell - openstack user create --password IRONIC_PASSWORD \ - --email ironic@example.com ironic - openstack role add --project service --user ironic admin - openstack service create --name ironic - --description "Ironic baremetal provisioning service" baremetal - - openstack service create --name ironic-inspector --description "Ironic inspector baremetal provisioning service" baremetal-introspection - openstack user create --password IRONIC_INSPECTOR_PASSWORD --email ironic_inspector@example.com ironic_inspector - openstack role add --project service --user ironic-inspector admin - ``` - - 2、创建Bare Metal服务访问入口 - - ```shell - openstack endpoint create --region RegionOne baremetal admin http://$IRONIC_NODE:6385 - openstack endpoint create --region RegionOne baremetal public http://$IRONIC_NODE:6385 - openstack endpoint create --region RegionOne baremetal internal http://$IRONIC_NODE:6385 - openstack endpoint create --region RegionOne baremetal-introspection internal http://172.20.19.13:5050/v1 - openstack endpoint create --region RegionOne baremetal-introspection public http://172.20.19.13:5050/v1 - openstack endpoint create --region RegionOne baremetal-introspection admin http://172.20.19.13:5050/v1 - ``` - -3. 配置ironic-api服务 - - 配置文件路径/etc/ironic/ironic.conf - - 1、通过**connection**选项配置数据库的位置,如下所示,替换**IRONIC_DBPASSWORD**为**ironic**用户的密码,替换**DB_IP**为DB服务器所在的IP地址: - - ```shell - [database] - - # The SQLAlchemy connection string used to connect to the - # database (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 2、通过以下选项配置ironic-api服务使用RabbitMQ消息代理,替换**RPC_\***为RabbitMQ的详细地址和凭证 - - ```shell - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 用户也可自行使用json-rpc方式替换rabbitmq - - 3、配置ironic-api服务使用身份认证服务的凭证,替换**PUBLIC_IDENTITY_IP**为身份认证服务器的公共IP,替换**PRIVATE_IDENTITY_IP**为身份认证服务器的私有IP,替换**IRONIC_PASSWORD**为身份认证服务中**ironic**用户的密码: - - ```shell - [DEFAULT] - - # Authentication strategy used by ironic-api: one of - # "keystone" or "noauth". "noauth" should not be used in a - # production environment because all authentication will be - # disabled. (string value) - - auth_strategy=keystone - host = controller - memcache_servers = controller:11211 - enabled_network_interfaces = flat,noop,neutron - default_network_interface = noop - transport_url = rabbit://openstack:RABBITPASSWD@controller:5672/ - enabled_hardware_types = ipmi - enabled_boot_interfaces = pxe - enabled_deploy_interfaces = direct - default_deploy_interface = direct - enabled_inspect_interfaces = inspector - enabled_management_interfaces = ipmitool - enabled_power_interfaces = ipmitool - enabled_rescue_interfaces = no-rescue,agent - isolinux_bin = /usr/share/syslinux/isolinux.bin - logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(global_request_id)s %(request_id)s %(user_identity)s] %(instance)s%(message)s - - [keystone_authtoken] - # Authentication type to load (string value) - auth_type=password - # Complete public Identity API endpoint (string value) - www_authenticate_uri=http://PUBLIC_IDENTITY_IP:5000 - # Complete admin Identity API endpoint. (string value) - auth_url=http://PRIVATE_IDENTITY_IP:5000 - # Service username. (string value) - username=ironic - # Service account password. (string value) - password=IRONIC_PASSWORD - # Service tenant name. (string value) - project_name=service - # Domain name containing project (string value) - project_domain_name=Default - # User's domain name (string value) - user_domain_name=Default - - [agent] - deploy_logs_collect = always - deploy_logs_local_path = /var/log/ironic/deploy - deploy_logs_storage_backend = local - image_download_source = http - stream_raw_images = false - force_raw_images = false - verify_ca = False - - [oslo_concurrency] - - [oslo_messaging_notifications] - transport_url = rabbit://openstack:123456@172.20.19.25:5672/ - topics = notifications - driver = messagingv2 - - [oslo_messaging_rabbit] - amqp_durable_queues = True - rabbit_ha_queues = True - - [pxe] - ipxe_enabled = false - pxe_append_params = nofb nomodeset vga=normal coreos.autologin ipa-insecure=1 - image_cache_size = 204800 - tftp_root=/var/lib/tftpboot/cephfs/ - tftp_master_path=/var/lib/tftpboot/cephfs/master_images - - [dhcp] - dhcp_provider = none - ``` - - 4、创建裸金属服务数据库表 - - ```shell - ironic-dbsync --config-file /etc/ironic/ironic.conf create_schema - ``` - - 5、重启ironic-api服务 - - ```shell - sudo systemctl restart openstack-ironic-api - ``` - -4. 配置ironic-conductor服务 - - 1、替换**HOST_IP**为conductor host的IP - - ```shell - [DEFAULT] - - # IP address of this host. If unset, will determine the IP - # programmatically. If unable to do so, will use "127.0.0.1". - # (string value) - - my_ip=HOST_IP - ``` - - 2、配置数据库的位置,ironic-conductor应该使用和ironic-api相同的配置。替换**IRONIC_DBPASSWORD**为**ironic**用户的密码,替换DB_IP为DB服务器所在的IP地址: - - ```shell - [database] - - # The SQLAlchemy connection string to use to connect to the - # database. (string value) - - connection = mysql+pymysql://ironic:IRONIC_DBPASSWORD@DB_IP/ironic - ``` - - 3、通过以下选项配置ironic-api服务使用RabbitMQ消息代理,ironic-conductor应该使用和ironic-api相同的配置,替换**RPC_\***为RabbitMQ的详细地址和凭证 - - ```shell - [DEFAULT] - - # A URL representing the messaging driver to use and its full - # configuration. (string value) - - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - ``` - - 用户也可自行使用json-rpc方式替换rabbitmq - - 4、配置凭证访问其他OpenStack服务 - - 为了与其他OpenStack服务进行通信,裸金属服务在请求其他服务时需要使用服务用户与OpenStack Identity服务进行认证。这些用户的凭据必须在与相应服务相关的每个配置文件中进行配置。 - - ```shell - [neutron] - 访问OpenStack网络服务 - [glance] - 访问OpenStack镜像服务 - [swift] - 访问OpenStack对象存储服务 - [cinder] - 访问OpenStack块存储服务 - [inspector] - 访问OpenStack裸金属introspection服务 - [service_catalog] - 一个特殊项用于保存裸金属服务使用的凭证,该凭证用于发现注册在OpenStack身份认证服务目录中的自己的API URL端点 - ``` - - 简单起见,可以对所有服务使用同一个服务用户。为了向后兼容,该用户应该和ironic-api服务的[keystone_authtoken]所配置的为同一个用户。但这不是必须的,也可以为每个服务创建并配置不同的服务用户。 - - 在下面的示例中,用户访问OpenStack网络服务的身份验证信息配置为: - - ```shell - 网络服务部署在名为RegionOne的身份认证服务域中,仅在服务目录中注册公共端点接口 - - 请求时使用特定的CA SSL证书进行HTTPS连接 - - 与ironic-api服务配置相同的服务用户 - - 动态密码认证插件基于其他选项发现合适的身份认证服务API版本 - ``` - - ```shell - [neutron] - - # Authentication type to load (string value) - auth_type = password - # Authentication URL (string value) - auth_url=https://IDENTITY_IP:5000/ - # Username (string value) - username=ironic - # User's password (string value) - password=IRONIC_PASSWORD - # Project name to scope to (string value) - project_name=service - # Domain ID containing project (string value) - project_domain_id=default - # User's domain id (string value) - user_domain_id=default - # PEM encoded Certificate Authority to use when verifying - # HTTPs connections. (string value) - cafile=/opt/stack/data/ca-bundle.pem - # The default region_name for endpoint URL discovery. (string - # value) - region_name = RegionOne - # List of interfaces, in order of preference, for endpoint - # URL. (list value) - valid_interfaces=public - ``` - - 默认情况下,为了与其他服务进行通信,裸金属服务会尝试通过身份认证服务的服务目录发现该服务合适的端点。如果希望对一个特定服务使用一个不同的端点,则在裸金属服务的配置文件中通过endpoint_override选项进行指定: - - ```shell - [neutron] ... endpoint_override = - ``` - - 5、配置允许的驱动程序和硬件类型 - - 通过设置enabled_hardware_types设置ironic-conductor服务允许使用的硬件类型: - - ```shell - [DEFAULT] enabled_hardware_types = ipmi - ``` - - 配置硬件接口: - - ```shell - enabled_boot_interfaces = pxe enabled_deploy_interfaces = direct,iscsi enabled_inspect_interfaces = inspector enabled_management_interfaces = ipmitool enabled_power_interfaces = ipmitool - ``` - - 配置接口默认值: - - ```shell - [DEFAULT] default_deploy_interface = direct default_network_interface = neutron - ``` - - 如果启用了任何使用Direct deploy的驱动,必须安装和配置镜像服务的Swift后端。Ceph对象网关(RADOS网关)也支持作为镜像服务的后端。 - - 6、重启ironic-conductor服务 - - ```shell - sudo systemctl restart openstack-ironic-conductor - ``` - -5. 配置ironic-inspector服务 - - 配置文件路径/etc/ironic-inspector/inspector.conf - - 1、创建数据库 - - ```shell - # mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE ironic_inspector CHARACTER SET utf8; - - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'localhost' \ IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON ironic_inspector.* TO 'ironic_inspector'@'%' \ - IDENTIFIED BY 'IRONIC_INSPECTOR_DBPASSWORD'; - ``` - - 2、通过**connection**选项配置数据库的位置,如下所示,替换**IRONIC_INSPECTOR_DBPASSWORD**为**ironic_inspector**用户的密码,替换**DB_IP**为DB服务器所在的IP地址: - - ```shell - [database] - backend = sqlalchemy - connection = mysql+pymysql://ironic_inspector:IRONIC_INSPECTOR_DBPASSWORD@DB_IP/ironic_inspector - min_pool_size = 100 - max_pool_size = 500 - pool_timeout = 30 - max_retries = 5 - max_overflow = 200 - db_retry_interval = 2 - db_inc_retry_interval = True - db_max_retry_interval = 2 - db_max_retries = 5 - ``` - - 3、配置消息度列通信地址 - - ```shell - [DEFAULT] - transport_url = rabbit://RPC_USER:RPC_PASSWORD@RPC_HOST:RPC_PORT/ - - ``` - - 4、设置keystone认证 - - ```shell - [DEFAULT] - - auth_strategy = keystone - timeout = 900 - rootwrap_config = /etc/ironic-inspector/rootwrap.conf - logging_context_format_string = %(asctime)s.%(msecs)03d %(process)d %(levelname)s %(name)s [%(global_request_id)s %(request_id)s %(user_identity)s] %(instance)s%(message)s - log_dir = /var/log/ironic-inspector - state_path = /var/lib/ironic-inspector - use_stderr = False - - [ironic] - api_endpoint = http://IRONIC_API_HOST_ADDRRESS:6385 - auth_type = password - auth_url = http://PUBLIC_IDENTITY_IP:5000 - auth_strategy = keystone - ironic_url = http://IRONIC_API_HOST_ADDRRESS:6385 - os_region = RegionOne - project_name = service - project_domain_name = Default - user_domain_name = Default - username = IRONIC_SERVICE_USER_NAME - password = IRONIC_SERVICE_USER_PASSWORD - - [keystone_authtoken] - auth_type = password - auth_url = http://control:5000 - www_authenticate_uri = http://control:5000 - project_domain_name = default - user_domain_name = default - project_name = service - username = ironic_inspector - password = IRONICPASSWD - region_name = RegionOne - memcache_servers = control:11211 - token_cache_time = 300 - - [processing] - add_ports = active - processing_hooks = $default_processing_hooks,local_link_connection,lldp_basic - ramdisk_logs_dir = /var/log/ironic-inspector/ramdisk - always_store_ramdisk_logs = true - store_data =none - power_off = false - - [pxe_filter] - driver = iptables - - [capabilities] - boot_mode=True - ``` - - 5、配置ironic inspector dnsmasq服务 - - ```shell - # 配置文件地址:/etc/ironic-inspector/dnsmasq.conf - port=0 - interface=enp3s0 #替换为实际监听网络接口 - dhcp-range=172.20.19.100,172.20.19.110 #替换为实际dhcp地址范围 - bind-interfaces - enable-tftp - - dhcp-match=set:efi,option:client-arch,7 - dhcp-match=set:efi,option:client-arch,9 - dhcp-match=aarch64, option:client-arch,11 - dhcp-boot=tag:aarch64,grubaa64.efi - dhcp-boot=tag:!aarch64,tag:efi,grubx64.efi - dhcp-boot=tag:!aarch64,tag:!efi,pxelinux.0 - - tftp-root=/tftpboot #替换为实际tftpboot目录 - log-facility=/var/log/dnsmasq.log - ``` - - 6、关闭ironic provision网络子网的dhcp - - ``` - openstack subnet set --no-dhcp 72426e89-f552-4dc4-9ac7-c4e131ce7f3c - ``` - - 7、初始化ironic-inspector服务的数据库 - - 在控制节点执行: - - ``` - ironic-inspector-dbsync --config-file /etc/ironic-inspector/inspector.conf upgrade - ``` - - 8、启动服务 - - ```shell - systemctl enable --now openstack-ironic-inspector.service - systemctl enable --now openstack-ironic-inspector-dnsmasq.service - ``` - -6. 配置httpd服务 - - 1. 创建ironic要使用的httpd的root目录并设置属主属组,目录路径要和/etc/ironic/ironic.conf中[deploy]组中http_root 配置项指定的路径要一致。 - - ``` - mkdir -p /var/lib/ironic/httproot ``chown ironic.ironic /var/lib/ironic/httproot - ``` - - - - 2. 安装和配置httpd服务 - - - - 1. 安装httpd服务,已有请忽略 - - ``` - yum install httpd -y - ``` - - - - 2. 创建/etc/httpd/conf.d/openstack-ironic-httpd.conf文件,内容如下: - - ``` - Listen 8080 - - - ServerName ironic.openeuler.com - - ErrorLog "/var/log/httpd/openstack-ironic-httpd-error_log" - CustomLog "/var/log/httpd/openstack-ironic-httpd-access_log" "%h %l %u %t \"%r\" %>s %b" - - DocumentRoot "/var/lib/ironic/httproot" - - Options Indexes FollowSymLinks - Require all granted - - LogLevel warn - AddDefaultCharset UTF-8 - EnableSendfile on - - - ``` - - 注意监听的端口要和/etc/ironic/ironic.conf里[deploy]选项中http_url配置项中指定的端口一致。 - - 3. 重启httpd服务。 - - ``` - systemctl restart httpd - ``` - - - -7. deploy ramdisk镜像制作 - - W版的ramdisk镜像支持通过ironic-python-agent服务或disk-image-builder工具制作,也可以使用社区最新的ironic-python-agent-builder。用户也可以自行选择其他工具制作。 - 若使用W版原生工具,则需要安装对应的软件包。 - - ```shell - yum install openstack-ironic-python-agent - 或者 - yum install diskimage-builder - ``` - - 具体的使用方法可以参考[官方文档](https://docs.openstack.org/ironic/queens/install/deploy-ramdisk.html) - - 这里介绍下使用ironic-python-agent-builder构建ironic使用的deploy镜像的完整过程。 - - 1. 安装 ironic-python-agent-builder - - - 1. 安装工具: - - ```shell - pip install ironic-python-agent-builder - ``` - - 2. 修改以下文件中的python解释器: - - ```shell - /usr/bin/yum /usr/libexec/urlgrabber-ext-down - ``` - - 3. 安装其它必须的工具: - - ```shell - yum install git - ``` - - 由于`DIB`依赖`semanage`命令,所以在制作镜像之前确定该命令是否可用:`semanage --help`,如果提示无此命令,安装即可: - - ```shell - # 先查询需要安装哪个包 - [root@localhost ~]# yum provides /usr/sbin/semanage - 已加载插件:fastestmirror - Loading mirror speeds from cached hostfile - * base: mirror.vcu.edu - * extras: mirror.vcu.edu - * updates: mirror.math.princeton.edu - policycoreutils-python-2.5-34.el7.aarch64 : SELinux policy core python utilities - 源 :base - 匹配来源: - 文件名 :/usr/sbin/semanage - # 安装 - [root@localhost ~]# yum install policycoreutils-python - ``` - - 2. 制作镜像 - - 如果是`arm`架构,需要添加: - ```shell - export ARCH=aarch64 - ``` - - 基本用法: - - ```shell - usage: ironic-python-agent-builder [-h] [-r RELEASE] [-o OUTPUT] [-e ELEMENT] - [-b BRANCH] [-v] [--extra-args EXTRA_ARGS] - distribution - - positional arguments: - distribution Distribution to use - - optional arguments: - -h, --help show this help message and exit - -r RELEASE, --release RELEASE - Distribution release to use - -o OUTPUT, --output OUTPUT - Output base file name - -e ELEMENT, --element ELEMENT - Additional DIB element to use - -b BRANCH, --branch BRANCH - If set, override the branch that is used for ironic- - python-agent and requirements - -v, --verbose Enable verbose logging in diskimage-builder - --extra-args EXTRA_ARGS - Extra arguments to pass to diskimage-builder - ``` - - 举例说明: - - ```shell - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky - ``` - - 3. 允许ssh登陆 - - 初始化环境变量,然后制作镜像: - - ```shell - export DIB_DEV_USER_USERNAME=ipa \ - export DIB_DEV_USER_PWDLESS_SUDO=yes \ - export DIB_DEV_USER_PASSWORD='123' - ironic-python-agent-builder centos -o /mnt/ironic-agent-ssh -b origin/stable/rocky -e selinux-permissive -e devuser - ``` - - 4. 指定代码仓库 - - 初始化对应的环境变量,然后制作镜像: - - ```shell - # 指定仓库地址以及版本 - DIB_REPOLOCATION_ironic_python_agent=git@172.20.2.149:liuzz/ironic-python-agent.git - DIB_REPOREF_ironic_python_agent=origin/develop - - # 直接从gerrit上clone代码 - DIB_REPOLOCATION_ironic_python_agent=https://review.opendev.org/openstack/ironic-python-agent - DIB_REPOREF_ironic_python_agent=refs/changes/43/701043/1 - ``` - - 参考:[source-repositories](https://docs.openstack.org/diskimage-builder/latest/elements/source-repositories/README.html)。 - - 指定仓库地址及版本验证成功。 - - 5. 注意 - -原生的openstack里的pxe配置文件的模版不支持arm64架构,需要自己对原生openstack代码进行修改: - -在W版中,社区的ironic仍然不支持arm64位的uefi pxe启动,表现为生成的grub.cfg文件(一般位于/tftpboot/下)格式不对而导致pxe启动失败,如下: - -生成的错误配置文件: - -![erro](/Users/andy_lee/Downloads/erro.png) - -如上图所示,arm架构里寻找vmlinux和ramdisk镜像的命令分别是linux和initrd,上图所示的标红命令是x86架构下的uefi pxe启动。 - -需要用户对生成grub.cfg的代码逻辑自行修改。 - -ironic向ipa发送查询命令执行状态请求的tls报错: - -w版的ipa和ironic默认都会开启tls认证的方式向对方发送请求,跟据官网的说明进行关闭即可。 - -1. 修改ironic配置文件(/etc/ironic/ironic.conf)下面的配置中添加ipa-insecure=1: - -``` -[agent] -verify_ca = False - -[pxe] -pxe_append_params = nofb nomodeset vga=normal coreos.autologin ipa-insecure=1 -``` - -2) ramdisk镜像中添加ipa配置文件/etc/ironic_python_agent/ironic_python_agent.conf并配置tls的配置如下: - -/etc/ironic_python_agent/ironic_python_agent.conf (需要提前创建/etc/ironic_python_agent目录) - -``` -[DEFAULT] -enable_auto_tls = False -``` - -设置权限: - -``` -chown -R ipa.ipa /etc/ironic_python_agent/ -``` - -3. 修改ipa服务的服务启动文件,添加配置文件选项 - - vim usr/lib/systemd/system/ironic-python-agent.service - - ``` - [Unit] - Description=Ironic Python Agent - After=network-online.target - - [Service] - ExecStartPre=/sbin/modprobe vfat - ExecStart=/usr/local/bin/ironic-python-agent --config-file /etc/ironic_python_agent/ironic_python_agent.conf - Restart=always - RestartSec=30s - - [Install] - WantedBy=multi-user.target - ``` - - - -### Kolla 安装 - -Kolla为OpenStack服务提供生产环境可用的容器化部署的功能。openEuler 22.03 LTS中引入了Kolla和Kolla-ansible服务。 - -Kolla的安装十分简单,只需要安装对应的RPM包即可 - -``` -yum install openstack-kolla openstack-kolla-ansible -``` - -安装完后,就可以使用`kolla-ansible`, `kolla-build`, `kolla-genpwd`, `kolla-mergepwd`等命令了。 - -### Trove 安装 -Trove是OpenStack的数据库服务,如果用户使用OpenStack提供的数据库服务则推荐使用该组件。否则,可以不用安装。 - -1. 设置数据库 - - 数据库服务在数据库中存储信息,创建一个**trove**用户可以访问的**trove**数据库,替换**TROVE_DBPASSWORD**为合适的密码 - - ```sql - mysql -u root -p - - MariaDB [(none)]> CREATE DATABASE trove CHARACTER SET utf8; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'localhost' \ - IDENTIFIED BY 'TROVE_DBPASSWORD'; - MariaDB [(none)]> GRANT ALL PRIVILEGES ON trove.* TO 'trove'@'%' \ - IDENTIFIED BY 'TROVE_DBPASSWORD'; - ``` - -2. 创建服务用户认证 - - 1、创建**Trove**服务用户 - - ```shell - openstack user create --password TROVE_PASSWORD \ - --email trove@example.com trove - openstack role add --project service --user trove admin - openstack service create --name trove - --description "Database service" database - ``` - **解释:** `TROVE_PASSWORD` 替换为`trove`用户的密码 - - 2、创建**Database**服务访问入口 - - ```shell - openstack endpoint create --region RegionOne database public http://controller:8779/v1.0/%\(tenant_id\)s - openstack endpoint create --region RegionOne database internal http://controller:8779/v1.0/%\(tenant_id\)s - openstack endpoint create --region RegionOne database admin http://controller:8779/v1.0/%\(tenant_id\)s - ``` - -3. 安装和配置**Trove**各组件 - - 1、安装**Trove**包 - ```shell script - yum install openstack-trove python-troveclient - ``` - 2. 配置`trove.conf` - ```shell script - vim /etc/trove/trove.conf - - [DEFAULT] - bind_host=TROVE_NODE_IP - log_dir = /var/log/trove - network_driver = trove.network.neutron.NeutronDriver - management_security_groups = - nova_keypair = trove-mgmt - default_datastore = mysql - taskmanager_manager = trove.taskmanager.manager.Manager - trove_api_workers = 5 - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - reboot_time_out = 300 - usage_timeout = 900 - agent_call_high_timeout = 1200 - use_syslog = False - debug = True - - # Set these if using Neutron Networking - network_driver=trove.network.neutron.NeutronDriver - network_label_regex=.* - - - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - - [database] - connection = mysql+pymysql://trove:TROVE_DBPASS@controller/trove - - [keystone_authtoken] - project_domain_name = Default - project_name = service - user_domain_name = Default - password = trove - username = trove - auth_url = http://controller:5000/v3/ - auth_type = password - - [service_credentials] - auth_url = http://controller:5000/v3/ - region_name = RegionOne - project_name = service - password = trove - project_domain_name = Default - user_domain_name = Default - username = trove - - [mariadb] - tcp_ports = 3306,4444,4567,4568 - - [mysql] - tcp_ports = 3306 - - [postgresql] - tcp_ports = 5432 - ``` - **解释:** - - `[Default]`分组中`bind_host`配置为Trove部署节点的IP - - `nova_compute_url` 和 `cinder_url` 为Nova和Cinder在Keystone中创建的endpoint - - `nova_proxy_XXX` 为一个能访问Nova服务的用户信息,上例中使用`admin`用户为例 - - `transport_url` 为`RabbitMQ`连接信息,`RABBIT_PASS`替换为RabbitMQ的密码 - - `[database]`分组中的`connection` 为前面在mysql中为Trove创建的数据库信息 - - Trove的用户信息中`TROVE_PASS`替换为实际trove用户的密码 - - 5. 配置`trove-guestagent.conf` - ```shell script - vim /etc/trove/trove-guestagent.conf - - [DEFAULT] - log_file = trove-guestagent.log - log_dir = /var/log/trove/ - ignore_users = os_admin - control_exchange = trove - transport_url = rabbit://openstack:RABBIT_PASS@controller:5672/ - rpc_backend = rabbit - command_process_timeout = 60 - use_syslog = False - debug = True - - [service_credentials] - auth_url = http://controller:5000/v3/ - region_name = RegionOne - project_name = service - password = TROVE_PASS - project_domain_name = Default - user_domain_name = Default - username = trove - - [mysql] - docker_image = your-registry/your-repo/mysql - backup_docker_image = your-registry/your-repo/db-backup-mysql:1.1.0 - ``` - **解释:** `guestagent`是trove中一个独立组件,需要预先内置到Trove通过Nova创建的虚拟 - 机镜像中,在创建好数据库实例后,会起guestagent进程,负责通过消息队列(RabbitMQ)向Trove上 - 报心跳,因此需要配置RabbitMQ的用户和密码信息。 - **从Victoria版开始,Trove使用一个统一的镜像来跑不同类型的数据库,数据库服务运行在Guest虚拟机的Docker容器中。** - - `transport_url` 为`RabbitMQ`连接信息,`RABBIT_PASS`替换为RabbitMQ的密码 - - Trove的用户信息中`TROVE_PASS`替换为实际trove用户的密码 - - 6. 生成数据`Trove`数据库表 - ```shell script - su -s /bin/sh -c "trove-manage db_sync" trove - ``` -4. 完成安装配置 - 1. 配置**Trove**服务自启动 - ```shell script - systemctl enable openstack-trove-api.service \ - openstack-trove-taskmanager.service \ - openstack-trove-conductor.service - ``` - 2. 启动服务 - ```shell script - systemctl start openstack-trove-api.service \ - openstack-trove-taskmanager.service \ - openstack-trove-conductor.service - ``` -### Swift 安装 - -Swift 提供了弹性可伸缩、高可用的分布式对象存储服务,适合存储大规模非结构化数据。 - -1. 创建服务凭证、API端点。 - - 创建服务凭证 - - ``` shell - #创建swift用户: - openstack user create --domain default --password-prompt swift - #为swift用户添加admin角色: - openstack role add --project service --user swift admin - #创建swift服务实体: - openstack service create --name swift --description "OpenStack Object Storage" object-store - ``` - - 创建swift API 端点: - - ```shell - openstack endpoint create --region RegionOne object-store public http://controller:8080/v1/AUTH_%\(project_id\)s - openstack endpoint create --region RegionOne object-store internal http://controller:8080/v1/AUTH_%\(project_id\)s - openstack endpoint create --region RegionOne object-store admin http://controller:8080/v1 - ``` - - -2. 安装软件包: - - ```shell - yum install openstack-swift-proxy python3-swiftclient python3-keystoneclient python3-keystonemiddleware memcached (CTL) - ``` - -3. 配置proxy-server相关配置 - - Swift RPM包里已经包含了一个基本可用的proxy-server.conf,只需要手动修改其中的ip和swift password即可。 - - ***注意*** - - **注意替换password为您在身份服务中为swift用户选择的密码** - -4. 安装和配置存储节点 (STG) - - 安装支持的程序包: - ```shell - yum install xfsprogs rsync - ``` - - 将/dev/vdb和/dev/vdc设备格式化为 XFS - - ```shell - mkfs.xfs /dev/vdb - mkfs.xfs /dev/vdc - ``` - - 创建挂载点目录结构: - - ```shell - mkdir -p /srv/node/vdb - mkdir -p /srv/node/vdc - ``` - - 找到新分区的 UUID: - - ```shell - blkid - ``` - - 编辑/etc/fstab文件并将以下内容添加到其中: - - ```shell - UUID="" /srv/node/vdb xfs noatime 0 2 - UUID="" /srv/node/vdc xfs noatime 0 2 - ``` - - 挂载设备: - - ```shell - mount /srv/node/vdb - mount /srv/node/vdc - ``` - ***注意*** - - **如果用户不需要容灾功能,以上步骤只需要创建一个设备即可,同时可以跳过下面的rsync配置** - - (可选)创建或编辑/etc/rsyncd.conf文件以包含以下内容: - - ```shell - [DEFAULT] - uid = swift - gid = swift - log file = /var/log/rsyncd.log - pid file = /var/run/rsyncd.pid - address = MANAGEMENT_INTERFACE_IP_ADDRESS - - [account] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/account.lock - - [container] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/container.lock - - [object] - max connections = 2 - path = /srv/node/ - read only = False - lock file = /var/lock/object.lock - ``` - **替换MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址** - - 启动rsyncd服务并配置它在系统启动时启动: - - ```shell - systemctl enable rsyncd.service - systemctl start rsyncd.service - ``` - -5. 在存储节点安装和配置组件 (STG) - - 安装软件包: - - ```shell - yum install openstack-swift-account openstack-swift-container openstack-swift-object - ``` - - 编辑/etc/swift目录的account-server.conf、container-server.conf和object-server.conf文件,替换bind_ip为存储节点上管理网络的IP地址。 - - 确保挂载点目录结构的正确所有权: - - ```shell - chown -R swift:swift /srv/node - ``` - - 创建recon目录并确保其拥有正确的所有权: - - ```shell - mkdir -p /var/cache/swift - chown -R root:swift /var/cache/swift - chmod -R 775 /var/cache/swift - ``` - -6. 创建账号环 (CTL) - - 切换到/etc/swift目录。 - - ```shell - cd /etc/swift - ``` - - 创建基础account.builder文件: - - ```shell - swift-ring-builder account.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中: - - ```shell - swift-ring-builder account.builder add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6202 --device DEVICE_NAME --weight DEVICE_WEIGHT - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意 *** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder account.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder account.builder rebalance - ``` - -7. 创建容器环 (CTL) - - 切换到`/etc/swift`目录。 - - 创建基础`container.builder`文件: - - ```shell - swift-ring-builder container.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中: - - ```shell - swift-ring-builder container.builder \ - add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6201 \ - --device DEVICE_NAME --weight 100 - - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意*** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder container.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder container.builder rebalance - ``` - -8. 创建对象环 (CTL) - - 切换到`/etc/swift`目录。 - - 创建基础`object.builder`文件: - - ```shell - swift-ring-builder object.builder create 10 1 1 - ``` - - 将每个存储节点添加到环中 - - ```shell - swift-ring-builder object.builder \ - add --region 1 --zone 1 --ip STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS --port 6200 \ - --device DEVICE_NAME --weight 100 - ``` - - **替换STORAGE_NODE_MANAGEMENT_INTERFACE_IP_ADDRESS为存储节点上管理网络的IP地址。替换DEVICE_NAME为同一存储节点上的存储设备名称** - - ***注意 *** - **对每个存储节点上的每个存储设备重复此命令** - - 验证戒指内容: - - ```shell - swift-ring-builder object.builder - ``` - - 重新平衡戒指: - - ```shell - swift-ring-builder object.builder rebalance - ``` - - 分发环配置文件: - - 将`account.ring.gz`,`container.ring.gz`以及 `object.ring.gz`文件复制到每个存储节点和运行代理服务的任何其他节点上的`/etc/swift`目录。 - - - -9. 完成安装 - - 编辑`/etc/swift/swift.conf`文件 - - ``` shell - [swift-hash] - swift_hash_path_suffix = test-hash - swift_hash_path_prefix = test-hash - - [storage-policy:0] - name = Policy-0 - default = yes - ``` - - **用唯一值替换 test-hash** - - 将swift.conf文件复制到/etc/swift每个存储节点和运行代理服务的任何其他节点上的目录。 - - 在所有节点上,确保配置目录的正确所有权: - - ```shell - chown -R root:swift /etc/swift - ``` - - 在控制器节点和运行代理服务的任何其他节点上,启动对象存储代理服务及其依赖项,并将它们配置为在系统启动时启动: - - ```shell - systemctl enable openstack-swift-proxy.service memcached.service - systemctl start openstack-swift-proxy.service memcached.service - ``` - - 在存储节点上,启动对象存储服务并将它们配置为在系统启动时启动: - - ```shell - systemctl enable openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service - - systemctl start openstack-swift-account.service openstack-swift-account-auditor.service openstack-swift-account-reaper.service openstack-swift-account-replicator.service - - systemctl enable openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service - - systemctl start openstack-swift-container.service openstack-swift-container-auditor.service openstack-swift-container-replicator.service openstack-swift-container-updater.service - - systemctl enable openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service - - systemctl start openstack-swift-object.service openstack-swift-object-auditor.service openstack-swift-object-replicator.service openstack-swift-object-updater.service - ``` -### Cyborg 安装 - -Cyborg为OpenStack提供加速器设备的支持,包括 GPU, FPGA, ASIC, NP, SoCs, NVMe/NOF SSDs, ODP, DPDK/SPDK等等。 - -1. 初始化对应数据库 - -``` -CREATE DATABASE cyborg; -GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'localhost' IDENTIFIED BY 'CYBORG_DBPASS'; -GRANT ALL PRIVILEGES ON cyborg.* TO 'cyborg'@'%' IDENTIFIED BY 'CYBORG_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -$ openstack user create --domain default --password-prompt cyborg -$ openstack role add --project service --user cyborg admin -$ openstack service create --name cyborg --description "Acceleration Service" accelerator - -$ openstack endpoint create --region RegionOne \ - accelerator public http://:6666/v1 -$ openstack endpoint create --region RegionOne \ - accelerator internal http://:6666/v1 -$ openstack endpoint create --region RegionOne \ - accelerator admin http://:6666/v1 -``` - -3. 安装Cyborg - -``` -yum install openstack-cyborg -``` - -4. 配置Cyborg - -修改`/etc/cyborg/cyborg.conf` - -``` -[DEFAULT] -transport_url = rabbit://%RABBITMQ_USER%:%RABBITMQ_PASSWORD%@%OPENSTACK_HOST_IP%:5672/ -use_syslog = False -state_path = /var/lib/cyborg -debug = True - -[database] -connection = mysql+pymysql://%DATABASE_USER%:%DATABASE_PASSWORD%@%OPENSTACK_HOST_IP%/cyborg - -[service_catalog] -project_domain_id = default -user_domain_id = default -project_name = service -password = PASSWORD -username = cyborg -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password - -[placement] -project_domain_name = Default -project_name = service -user_domain_name = Default -password = PASSWORD -username = placement -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password - -[keystone_authtoken] -memcached_servers = localhost:11211 -project_domain_name = Default -project_name = service -user_domain_name = Default -password = PASSWORD -username = cyborg -auth_url = http://%OPENSTACK_HOST_IP%/identity -auth_type = password -``` - -自行修改对应的用户名、密码、IP等信息 - -5. 同步数据库表格 - -``` -cyborg-dbsync --config-file /etc/cyborg/cyborg.conf upgrade -``` - -6. 启动Cyborg服务 - -``` -systemctl enable openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent -systemctl start openstack-cyborg-api openstack-cyborg-conductor openstack-cyborg-agent -``` - -### Aodh 安装 - -1. 创建数据库 - -``` -CREATE DATABASE aodh; - -GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'localhost' IDENTIFIED BY 'AODH_DBPASS'; - -GRANT ALL PRIVILEGES ON aodh.* TO 'aodh'@'%' IDENTIFIED BY 'AODH_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt aodh - -openstack role add --project service --user aodh admin - -openstack service create --name aodh --description "Telemetry" alarming - -openstack endpoint create --region RegionOne alarming public http://controller:8042 - -openstack endpoint create --region RegionOne alarming internal http://controller:8042 - -openstack endpoint create --region RegionOne alarming admin http://controller:8042 -``` - -3. 安装Aodh - -``` -yum install openstack-aodh-api openstack-aodh-evaluator openstack-aodh-notifier openstack-aodh-listener openstack-aodh-expirer python3-aodhclient -``` - -4. 修改配置文件 - -``` -[database] -connection = mysql+pymysql://aodh:AODH_DBPASS@controller/aodh - -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller -auth_strategy = keystone - -[keystone_authtoken] -www_authenticate_uri = http://controller:5000 -auth_url = http://controller:5000 -memcached_servers = controller:11211 -auth_type = password -project_domain_id = default -user_domain_id = default -project_name = service -username = aodh -password = AODH_PASS - -[service_credentials] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_id = default -user_domain_id = default -project_name = service -username = aodh -password = AODH_PASS -interface = internalURL -region_name = RegionOne -``` - -5. 初始化数据库 - -``` -aodh-dbsync -``` - -6. 启动Aodh服务 - -``` -systemctl enable openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service - -systemctl start openstack-aodh-api.service openstack-aodh-evaluator.service openstack-aodh-notifier.service openstack-aodh-listener.service -``` - -### Gnocchi 安装 - -1. 创建数据库 - -``` -CREATE DATABASE gnocchi; - -GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'localhost' IDENTIFIED BY 'GNOCCHI_DBPASS'; - -GRANT ALL PRIVILEGES ON gnocchi.* TO 'gnocchi'@'%' IDENTIFIED BY 'GNOCCHI_DBPASS'; -``` - -2. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt gnocchi - -openstack role add --project service --user gnocchi admin - -openstack service create --name gnocchi --description "Metric Service" metric - -openstack endpoint create --region RegionOne metric public http://controller:8041 - -openstack endpoint create --region RegionOne metric internal http://controller:8041 - -openstack endpoint create --region RegionOne metric admin http://controller:8041 -``` - -3. 安装Gnocchi - -``` -yum install openstack-gnocchi-api openstack-gnocchi-metricd python3-gnocchiclient -``` - -4. 修改配置文件`/etc/gnocchi/gnocchi.conf` - -``` -[api] -auth_mode = keystone -port = 8041 -uwsgi_mode = http-socket - -[keystone_authtoken] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_name = Default -user_domain_name = Default -project_name = service -username = gnocchi -password = GNOCCHI_PASS -interface = internalURL -region_name = RegionOne - -[indexer] -url = mysql+pymysql://gnocchi:GNOCCHI_DBPASS@controller/gnocchi - -[storage] -# coordination_url is not required but specifying one will improve -# performance with better workload division across workers. -coordination_url = redis://controller:6379 -file_basepath = /var/lib/gnocchi -driver = file -``` - -5. 初始化数据库 - -``` -gnocchi-upgrade -``` - -6. 启动Gnocchi服务 - -``` -systemctl enable openstack-gnocchi-api.service openstack-gnocchi-metricd.service - -systemctl start openstack-gnocchi-api.service openstack-gnocchi-metricd.service -``` - -### Ceilometer 安装 - -1. 创建对应Keystone资源对象 - -``` -openstack user create --domain default --password-prompt ceilometer - -openstack role add --project service --user ceilometer admin - -openstack service create --name ceilometer --description "Telemetry" metering -``` - -2. 安装Ceilometer - -``` -yum install openstack-ceilometer-notification openstack-ceilometer-central -``` - -3. 修改配置文件`/etc/ceilometer/pipeline.yaml` - -``` -publishers: - # set address of Gnocchi - # + filter out Gnocchi-related activity meters (Swift driver) - # + set default archive policy - - gnocchi://?filter_project=service&archive_policy=low -``` - -4. 修改配置文件`/etc/ceilometer/ceilometer.conf` - -``` -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller - -[service_credentials] -auth_type = password -auth_url = http://controller:5000/v3 -project_domain_id = default -user_domain_id = default -project_name = service -username = ceilometer -password = CEILOMETER_PASS -interface = internalURL -region_name = RegionOne -``` - -5. 初始化数据库 - -``` -ceilometer-upgrade -``` - -6. 启动Ceilometer服务 - -``` -systemctl enable openstack-ceilometer-notification.service openstack-ceilometer-central.service - -systemctl start openstack-ceilometer-notification.service openstack-ceilometer-central.service -``` - -### Heat 安装 - -1. 创建**heat**数据库,并授予**heat**数据库正确的访问权限,替换**HEAT_DBPASS**为合适的密码 - -``` -CREATE DATABASE heat; -GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'localhost' IDENTIFIED BY 'HEAT_DBPASS'; -GRANT ALL PRIVILEGES ON heat.* TO 'heat'@'%' IDENTIFIED BY 'HEAT_DBPASS'; -``` - -2. 创建服务凭证,创建**heat**用户,并为其增加**admin**角色 - -``` -openstack user create --domain default --password-prompt heat -openstack role add --project service --user heat admin -``` - -3. 创建**heat**和**heat-cfn**服务及其对应的API端点 - -``` -openstack service create --name heat --description "Orchestration" orchestration -openstack service create --name heat-cfn --description "Orchestration" cloudformation -openstack endpoint create --region RegionOne orchestration public http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne orchestration internal http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne orchestration admin http://controller:8004/v1/%\(tenant_id\)s -openstack endpoint create --region RegionOne cloudformation public http://controller:8000/v1 -openstack endpoint create --region RegionOne cloudformation internal http://controller:8000/v1 -openstack endpoint create --region RegionOne cloudformation admin http://controller:8000/v1 -``` - -4. 创建stack管理的额外信息,包括**heat**domain及其对应domain的admin用户**heat_domain_admin**, -**heat_stack_owner**角色,**heat_stack_user**角色 - -``` -openstack user create --domain heat --password-prompt heat_domain_admin -openstack role add --domain heat --user-domain heat --user heat_domain_admin admin -openstack role create heat_stack_owner -openstack role create heat_stack_user -``` - -5. 安装软件包 - -``` -yum install openstack-heat-api openstack-heat-api-cfn openstack-heat-engine -``` - -6. 修改配置文件`/etc/heat/heat.conf` - -``` -[DEFAULT] -transport_url = rabbit://openstack:RABBIT_PASS@controller -heat_metadata_server_url = http://controller:8000 -heat_waitcondition_server_url = http://controller:8000/v1/waitcondition -stack_domain_admin = heat_domain_admin -stack_domain_admin_password = HEAT_DOMAIN_PASS -stack_user_domain_name = heat - -[database] -connection = mysql+pymysql://heat:HEAT_DBPASS@controller/heat - -[keystone_authtoken] -www_authenticate_uri = http://controller:5000 -auth_url = http://controller:5000 -memcached_servers = controller:11211 -auth_type = password -project_domain_name = default -user_domain_name = default -project_name = service -username = heat -password = HEAT_PASS - -[trustee] -auth_type = password -auth_url = http://controller:5000 -username = heat -password = HEAT_PASS -user_domain_name = default - -[clients_keystone] -auth_uri = http://controller:5000 -``` - -7. 初始化**heat**数据库表 - -``` -su -s /bin/sh -c "heat-manage db_sync" heat -``` - -8. 启动服务 - -``` -systemctl enable openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service -systemctl start openstack-heat-api.service openstack-heat-api-cfn.service openstack-heat-engine.service -``` - -## 快速安装 OpenStack - -OpenStack SIG还提供了一键部署OpenStack all in one或三节点的ansible脚本,用户可以使用该脚本快速部署一套基于openEuler RPM的OpenStack环境。下面以all in one举例说明使用方法 - -1. 安装OpenStack SIG工具 - - ```shell - pip install openstack-sig-tool - ``` - -2. 配置openstack yum 源 - - ```shell - yum install openstack-release-wallaby - ``` - - **注意**:如果你的环境的YUM源没有启用EPOL,需要同时配置EPOL - - ```shell - vi /etc/yum.repos.d/openEuler.repo - - [EPOL] - name=EPOL - baseurl=http://repo.openeuler.org/openEuler-22.03-LTS/EPOL/main/$basearch/ - enabled=1 - gpgcheck=1 - gpgkey=http://repo.openeuler.org/openEuler-22.03-LTS/OS/$basearch/RPM-GPG-KEY-openEuler - EOF - -3. 刷新ansible配置 - - 打开`/usr/local/etc/inventory/all_in_one.yaml`,根据当前机器环境和需求修改对应配置。内容如下 - - ```shell - all: - hosts: - controller: - ansible_host: - ansible_ssh_private_key_file: - ansible_ssh_user: root - vars: - mysql_root_password: root - mysql_project_password: root - rabbitmq_password: root - project_identity_password: root - enabled_service: - - keystone - - neutron - - cinder - - placement - - nova - - glance - - horizon - - aodh - - ceilometer - - cyborg - - gnocchi - - kolla - - heat - - swift - - trove - - tempest - neutron_provider_interface_name: br-ex - default_ext_subnet_range: 10.100.100.0/24 - default_ext_subnet_gateway: 10.100.100.1 - neutron_dataplane_interface_name: eth1 - cinder_block_device: vdb - swift_storage_devices: - - vdc - swift_hash_path_suffix: ash - swift_hash_path_prefix: has - children: - compute: - hosts: controller - storage: - hosts: controller - network: - hosts: controller - vars: - test-key: test-value - dashboard: - hosts: controller - vars: - allowed_host: '*' - kolla: - hosts: controller - vars: - # We add openEuler OS support for kolla in OpenStack Queens/Rocky release - # Set this var to true if you want to use it in Q/R - openeuler_plugin: false - ``` - - **关键配置** - - | 配置项 | 解释 | - |---|---| - | ansible_host | all in one节点IP | - | ansible_ssh_private_key_file | ansible脚本登录all in one节点时使用的登录秘钥 | - | ansible_ssh_user | ansible脚本登录all in one节点时使用的登录用户 | - | enabled_service | 安装服务列表,根据用户需求自行删减 | - | neutron_provider_interface_name | neutron L3网桥名称 | - | default_ext_subnet_range | neutron私网IP段 | - | default_ext_subnet_gateway | neutron私网gateway | - | neutron_dataplane_interface_name | neutron使用的网卡,推荐使用一张新的网卡,以免和现有网卡冲突,发现all in one主机断连的情况 | - | cinder_block_device | cinder使用的卷设备名 | - | swift_storage_devices | swift使用的卷设备名 | - -4. 执行安装命令 - - ```shell - oos env setup all_in_one - ``` - - 该命令执行后,OpenStack all in one环境就部署成功了 - - 环境变量文件在当前用户的根目录下,名叫`.admin-openrc` - -5. 初始化tempest环境 - - 如果用户想使用该环境运行tempest测试的话,可以执行命令`oos env init all_in_one`,会自动把tempest需要的OpenStack资源自动创建好。 - - 命令执行成功后,在用户的根目录下会生成`mytest`目录,进入其中就可以执行`tempest run`命令了。 diff --git a/docs/zh/docs/thirdparty_migration/openstack.md b/docs/zh/docs/thirdparty_migration/openstack.md new file mode 100644 index 000000000..831b8883b --- /dev/null +++ b/docs/zh/docs/thirdparty_migration/openstack.md @@ -0,0 +1 @@ +openEuler OpenStack相关文档已迁移至[OpenStack SIG官网文档](https://openeuler.gitee.io/openstack/)。请访问链接获取详细信息。 diff --git a/docs/zh/docs/thirdparty_migration/thidrparty.md b/docs/zh/docs/thirdparty_migration/thidrparty.md index 9fcf83bff..b52740748 100644 --- a/docs/zh/docs/thirdparty_migration/thidrparty.md +++ b/docs/zh/docs/thirdparty_migration/thidrparty.md @@ -1,6 +1,3 @@ # 第三方软件安装指南 -本文档介绍 openEuler 支持第三方软件 OpenStack 的移植与部署方法,以指导用户快速了解并使用其功能。 - 本文档适用于使用 openEuler 系统并希望了解和使用第三方软件的社区开发者、开源爱好者以及合作伙伴。使用人员需要具备基本的 Linux 操作系统知识。 - diff --git a/docs/zh/menu/index.md b/docs/zh/menu/index.md index 45371146f..ba9380147 100644 --- a/docs/zh/menu/index.md +++ b/docs/zh/menu/index.md @@ -177,7 +177,7 @@ headless: true - [运行测试pod]({{< relref "./docs/Kubernetes/运行测试pod.md" >}}) - [Kubeedge部署指南]({{< relref "./docs/Kubernetes/Kubernetes.md" >}}) - [第三方软件安装指南]({{< relref "./docs/thirdparty_migration/thidrparty.md" >}}) - - [OpenStack-Victoria部署指南]({{< relref "./docs/thirdparty_migration/OpenStack-victoria.md" >}}) + - [OpenStack]({{< relref "./docs/thirdparty_migration/openstack.md" >}}) - [HA 用户指南]({{< relref "./docs/desktop/ha.md" >}}) - [部署 HA]({{< relref "./docs/desktop/installha.md" >}}) - [HA 使用实例]({{< relref "./docs/desktop/usecase.md" >}}) -- Gitee From 4eee0b8f265aa1397e05a8ddbf1e9fe0d8fc0f19 Mon Sep 17 00:00:00 2001 From: liheavy Date: Tue, 16 Aug 2022 14:50:09 +0800 Subject: [PATCH 115/130] add pkgship-panel description and fix bugs --- docs/zh/docs/userguide/images/panel.png | Bin 0 -> 38165 bytes docs/zh/docs/userguide/patch-tracking.md | 2 +- docs/zh/docs/userguide/pkgship.md | 33 +++++++++++++++++++---- 3 files changed, 29 insertions(+), 6 deletions(-) create mode 100644 docs/zh/docs/userguide/images/panel.png diff --git a/docs/zh/docs/userguide/images/panel.png b/docs/zh/docs/userguide/images/panel.png new file mode 100644 index 0000000000000000000000000000000000000000..150eb8c8229f9e8cb47706f3b82f07516a505076 GIT binary patch literal 38165 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 literal 0 HcmV?d00001 diff --git a/docs/zh/docs/userguide/patch-tracking.md b/docs/zh/docs/userguide/patch-tracking.md index 4e9f1e05f..87f6632d1 100644 --- a/docs/zh/docs/userguide/patch-tracking.md +++ b/docs/zh/docs/userguide/patch-tracking.md @@ -322,6 +322,6 @@ patch-tracking 运行过程中,可能会出现如下报错: #### 原因分析 -以上问题是 patch-tracking 与 GitHub API 服务之间网络访问不稳定导致,请确保在与 GitHub API 服务之间网络稳定的环境中(如华为云任一国际站点)运行 patch-tracking。 +以上问题是 patch-tracking 与 GitHub API 服务之间网络访问不稳定导致,请确保在与 GitHub API 服务之间网络稳定的环境中(如使用[华为云ESC弹性云服务器](https://console.huaweicloud.com/))运行 patch-tracking。 diff --git a/docs/zh/docs/userguide/pkgship.md b/docs/zh/docs/userguide/pkgship.md index edb017f93..0b377d0fa 100644 --- a/docs/zh/docs/userguide/pkgship.md +++ b/docs/zh/docs/userguide/pkgship.md @@ -12,15 +12,16 @@ - [服务启动和停止](#服务启动和停止) - [工具使用](#工具使用) - [日志查看和转储](#日志查看和转储) + - [扩展工具pkgship-panel](#扩展工具pkgship-panel) ## 介绍 -pkgship是一款管理OS软件包依赖关系,提供依赖和被依赖关系完整图谱的查询工具,pkgship提供软件包依赖查询、生命周期管理、补丁查询等功能。 +pkgship是一款管理OS软件包依赖关系,提供依赖和被依赖关系完整图谱的查询工具,pkgship提供软件包依赖查询、生命周期管理等功能。 -1. 软件包依赖查询:方便社区人员在软件包引入、更新和删除的时候了解软件的影响范围。 -2. 补丁查询:方便社区人员了解openEuler软件包的补丁情况以及提取补丁内容,详细内容请参见[patch-tracking](../patch-tracking/README.md)。 +1. 软件包基本信息查询:方便社区人员快速获取软件包的名称,版本,描述等基本信息。 +2. 软件包依赖查询:方便社区人员在软件包引入、更新和删除的时候了解软件的影响范围。 ## 架构 @@ -28,11 +29,17 @@ pkgship是一款管理OS软件包依赖关系,提供依赖和被依赖关系 ![avatar](./images/packagemanagement.png) +## 在线使用 + +pkgship提供了公网地址https://pkgmanage.openeuler.org/Packagemanagement,若无定制化需求,可直接使用在线查询。 + +若需要定制查询数据源,可按照文档进行本地安装、配置、使用。 + ## 软件下载 * Repo源挂载正式发布地址: * 源码获取地址: -* RPM包版本获取地址: +* RPM包版本获取地址:https://build.openeuler.org/project/show/openEuler:Mainline:RISC-V ## 运行环境 @@ -42,6 +49,7 @@ pkgship是一款管理OS软件包依赖关系,提供依赖和被依赖关系 | -------- | ----------- | | CPU | 8核 | | 内存 | 32G,最小4G | +| 硬盘 | 20G | | 网络带宽 | 300M | | I/O | 375MB/sec | @@ -203,7 +211,7 @@ priority: 2 > > 不支持直接配置sqlite文件路径。 > -> dbname请使用小写字母或者数字,不支持大写字母。 +> dbname请使用小写字母或者数字开头和结尾,支持括号内字符(. - _ +),不支持大写字母。 ## 服务启动和停止 @@ -422,3 +430,18 @@ pkgshipd stop 停止服务 pkgship启动时转储脚本后台运行,从启动时,每隔1天进行转储压缩,共保留30份压缩文件,压缩文件名称为uwsgi.log-20201010x.zip, x为压缩时的小时数。 pkgship停止后转储脚本停止,不再进行转储,再次启动时,转储脚本重新执行。 + +## 扩展工具pkgship-panel + +### 介绍 + +pkgship-panel旨在将软件包构建信息和维护信息集成到一起,方便版本维护人员可以快速识别构建异常软件包并快速邮件通知相关责任人去解决,保证构建工程稳定性,提高IOS构建成功率。 + +### 架构 + +![](images/panel.png) + +### 工具使用 + +由于工具数据源不可配置,所以建议直接使用pkgship-panel官网:https://pkgmanage.openeuler.org/Infomanagement + -- Gitee From 8e771d0eec6ee505d7b349f295369c295860e6f2 Mon Sep 17 00:00:00 2001 From: hcy1012 <690765764@qq.com> Date: Tue, 23 Aug 2022 11:40:18 +0800 Subject: [PATCH 116/130] update docs of master --- .../Administration/basic-configuration.md | 2 +- .../Administration/configuring-the-network.md | 42 ++--- docs/en/docs/Gazelle/Gazelle.md | 155 +++++++++--------- ...talling-the-Kubernetes-software-package.md | 15 +- .../docs/Kubernetes/preparing-certificates.md | 4 +- .../StratoVirt/StratoVirt_introduction.md | 30 ++-- docs/en/docs/StratoVirt/VM_configuration.md | 4 +- .../introduction-to-virtualization.md | 4 +- .../virtualization-installation.md | 20 +-- .../docs/Virtualization/vm-configuration.md | 60 +++---- docs/zh/docs/Gazelle/Gazelle.md | 4 +- 11 files changed, 181 insertions(+), 159 deletions(-) diff --git a/docs/en/docs/Administration/basic-configuration.md b/docs/en/docs/Administration/basic-configuration.md index 2429a349a..af09da8bb 100644 --- a/docs/en/docs/Administration/basic-configuration.md +++ b/docs/en/docs/Administration/basic-configuration.md @@ -453,7 +453,7 @@ This section describes how to set the memory reserved for kdump and modify param #### Parameter Formats of the Memory Reserved for kdump -The memory reserved for kdump must be added to the bootargs in the **/boot/efi/EFI/openEuler/grub.cfg** configuration file. The memory reserved for kdump has been added to the released openEuler version by default and can be adjusted as required. After adding or modifying the bootargs, restart the system for the setting to take effect. The parameter formats of the memory reserved for kdump are as follows: +The memory reserved for kdump must be added to the bootargs in the **/boot/efi/EFI/openEuler/grub.cfg** (UEFI boot mode) or **/boot/grub2/grub.cfg** (legacy boot mode). The memory reserved for kdump has been added to openEuler releases by default and can be adjusted as required. After adding or modifying the bootargs, restart the system for the settings to take effect. The parameter formats of the memory reserved for kdump are as follows: | Bootarg| Description| Default Value| Remarks| |----------|----------|----------|----------| diff --git a/docs/en/docs/Administration/configuring-the-network.md b/docs/en/docs/Administration/configuring-the-network.md index ce912c339..3602aac63 100644 --- a/docs/en/docs/Administration/configuring-the-network.md +++ b/docs/en/docs/Administration/configuring-the-network.md @@ -16,7 +16,7 @@ - [IPv6 Differences \(vs IPv4\)](#ipv6-differences-vs-ipv4) - [Restrictions](#restrictions) - [Configuration Description](#configuration-description) - - [FAQ](#faq) + - [FAQs](#faqs) @@ -446,7 +446,7 @@ In the preceding command, **192.168.2.1** is the IP address of the target netw ### Configuring the Network Through the ifcfg File >![](./public_sys-resources/icon-note.gif) **NOTE:** ->The network configured in the **ifcfg** file does not take effect immediately. You need to run the **systemctl reload NetworkManager** command as the **root** user to restart the network service for the configuration to take effect. +>The network configured in the **ifcfg** file does not take effect immediately. After modifying the file (for example, **ifcfg-enp3s0**), you need to run the **nmcli con reload;nmcli con up enp3s0** command as the **root** user to reload the configuration file and activate the connection for the modification to take effect. #### Configuring a Static Network The following uses the **enp4s0** network interface as an example to describe how to configure a static network by modifying the **ifcfg** file as the **root** user. The **ifcfg-enp4s0** file is generated in the **/etc/sysconfig/network-scripts/** directory. Modify the following parameters in the file: @@ -1025,7 +1025,7 @@ Remarks: - preferred\_lft: preferred lifetime. The preferred\_lft address has not expired and can be used for normal communication. If there are multiple preferred addresses, the address is selected based on the kernel mechanism. - valid\_lft: valid lifetime. The address cannot be used for creating new connections within the period of \[preferred\_lft, valid\_lft\]. The existing connections are still valid. -##### ip link Command +##### Command ip link The commands are as follows: ``` @@ -1034,7 +1034,7 @@ ip link set IFNAME mtu MTU The minimum PMTU of IPv6 is 1280. If the MTU is set to a value smaller than 1280, IPv6 addresses will be lost. Other devices cannot ping the IPv6 address. -##### ip addr Command +##### Command ip addr 1. The commands are as follows: ``` @@ -1082,7 +1082,7 @@ The minimum PMTU of IPv6 is 1280. If the MTU is set to a value smaller than 1280 -##### ip route Command +##### Command ip route 1. The commands are as follows: ``` @@ -1102,7 +1102,7 @@ The minimum PMTU of IPv6 is 1280. If the MTU is set to a value smaller than 1280 You can choose whether to add the -6 option when deleting an IPv6 route. The ip route command determines whether an IPv4 address or an IPv6 address is used based on the address type. -##### ip rule command +##### Command ip rule 1. The commands are as follows: ``` @@ -1137,28 +1137,28 @@ The configuration differences in /etc/sysconfig/network are as follows:

NA

+

N/A

IPV6FORWARDING=yes|no

IPv6 forwarding. By default, IPv6 packets are not forwarded.

NA

+

N/A

IPV6_AUTOCONF=yes|no

If IPv6 forwarding is enabled, the value is no. Otherwise, the value is yes.

NA

+

N/A

IPV6_ROUTER=yes|no

If IPv6 forwarding is enabled, the value is yes. Otherwise, the value is no.

NA

+

N/A

IPV6_AUTOTUNNEL=yes|no

Indicates the default gateway in IPv6.

NA

+

N/A

IPV6_DEFAULTDEV=<interface> (optional)

Specifies the default forwarding NIC.

NA

+

N/A

IPV6_RADVD_PIDFILE=<pid-file> (optional)

The default path of ipv6_radvd_pid is /var/run/radvd/radvd.pid.

NA

+

N/A

IPV6_RADVD_TRIGGER_ACTION=startstop|reload|restart|SIGHUP (optional)

PREFIXn

NA

+

N/A

The network prefix, network alias, and PPP are invalid. The priority is higher than that of NETMASK.

NETMASKn

NA

+

N/A

Indicates the subnet mask. It is used only for the alias and PPP.

The default value is no. If this parameter is set to yes, ifup-eth exits when dhclient fails.

NA

+

N/A

IPV6_PRIVACY=rfc3041

Disabled by default.

NA

+

N/A

IPV6INIT=yes|no

IPv6 is enabled by default.

NA

+

N/A

IPV6FORWARDING=yes|no

-### FAQ +### FAQs -#### The iscsi-initiator-utils Does Not Support the fe80 IPv6 Address. +#### The iscsi-initiator-utils Does Not Support the fe80 IPv6 Address ##### Symptom When a client uses an IPv6 address to log in to the iSCSI server, run the iscsiadm -m node -p ipv6address -l command. If the global address is used, replace ipv6address in the command example with the global address. However, the link-local address \(IPv6 address starting with fe80\) cannot be used because the current mechanism of iscsi-initiator-utils does not support the link-local address to log in to the iSCSI server. @@ -1289,7 +1289,7 @@ If you use the iscsiadm -m node -p fe80::xxxx%enp3s0 -l format for login, the is Therefore, **the current mechanism of iscsi-initiator-utils does not support login to the iSCSI server using a link-local address.** -#### The IPv6 Address Is Lost After the NIC Is Down. +#### The IPv6 Address Is Lost After the NIC Is Down ##### Symptom Run the ip link down+up NIC or ifconfig down+up NIC command to disable the NIC and then enable it to go online. Check the IP address configured on the NIC. It is found that the IPv4 address is not lost but the configured IPv6 address is lost. diff --git a/docs/en/docs/Gazelle/Gazelle.md b/docs/en/docs/Gazelle/Gazelle.md index 380a8876b..ee47cad68 100644 --- a/docs/en/docs/Gazelle/Gazelle.md +++ b/docs/en/docs/Gazelle/Gazelle.md @@ -1,6 +1,6 @@ # Gazelle User Guide -## Introduction +## Overview Gazelle is a high-performance user-mode protocol stack. It directly reads and writes NIC packets in user mode based on DPDK and transmit the packets through shared hugepage memory, and uses the LwIP protocol stack. Gazelle greatly improves the network I/O throughput of applications and accelerates the network for the databases, such as MySQL and Redis. - High Performance @@ -13,7 +13,6 @@ In the single-process scenario where the NIC supports multiple queues, **liblsta ## Installation Configure the Yum source of openEuler and run the`yum` command to install Gazelle. ```sh -#dpdk >= 21.11-2 yum install dpdk yum install libconfig yum install numactl @@ -21,17 +20,19 @@ yum install libboundscheck yum install libpcap yum install gazelle ``` +>NOTE: +dpdk >= 21.11-2 -## Usage -To configure the running environment and use Gazelle to accelerate applications, perform the following steps: +## How to Use +To configure the operating environment and use Gazelle to accelerate applications, perform the following steps: ### 1. Installing the .ko File as the **root** User Install the .ko files based on the site requirements to enable the virtual network ports and bind NICs to the user-mode driver. To enable the virtual network port function, use **rte_kni.ko**. -``` sh +```sh modprobe rte_kni carrier="on" ``` Bind the NIC from the kernel driver to the user-mode driver. Choose one of the following .ko files based on the site requirements. -``` sh +```sh #If the IOMMU is available modprobe vfio-pci @@ -42,81 +43,85 @@ modprobe vfio-pci #Other cases modprobe igb_uio ``` +>NOTE: +You can check whether the IOMMU is enabled based on the BIOS configuration. ### 2. Binding the NIC Using DPDK Bind the NIC to the driver selected in Step 1 to provide an interface for the user-mode NIC driver to access the NIC resources. -``` sh -# Using vfio-pci +```sh +#Using vfio-pci dpdk-devbind -b vfio-pci enp3s0 -# Using igb_uio +#Using igb_uio dpdk-devbind -b igb_uio enp3s0 ``` ### 3. Configuring Memory Huge Pages Gazelle uses hugepage memory to improve efficiency. You can configure any size for the memory huge pages reserved by the system using the **root** permissions. Each memory huge page requires a file descriptor. If the memory is large, you are advised to use 1 GB huge pages to avoid occupying too many file descriptors. Select a page size based on the site requirements and configure sufficient memory huge pages. Run the following commands to configure huge pages: -``` sh -# Configuring 1024 2 MB huge pages on node0. Total memory is 2 GB. +```sh +#Configuring 1024 2 MB huge pages on node0. The total memory is 2 GB. echo 1024 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages -# Configuring 5 1 GB huge pages on node0. Total memory is 5 GB. +#Configuring 5 1 GB huge pages on node0. The total memory is 5 GB. echo 5 > /sys/devices/system/node/node0/hugepages/hugepages-1048576kB/nr_hugepages - -# Viewing configuration results. -grep Huge /proc/meminfo ``` +>NOTE: +Run the **cat** command to query the actual number of reserved pages. If the continuous memory is insufficient, the number may be less than expected. ### 4. Mounting Memory Huge Pages Create two directories for the lstack and ltran processes to access the memory huge pages. Run the following commands: -``` sh -mkdir -p /mnt/hugepages -mkdir -p /mnt/hugepages-2M -chmod -R 700 /mnt/hugepages -chmod -R 700 /mnt/hugepages-2M -mount -t hugetlbfs nodev /mnt/hugepages -mount -t hugetlbfs nodev /mnt/hugepages-2M +```sh +mkdir -p /mnt/hugepages-ltran +mkdir -p /mnt/hugepages-lstack +chmod -R 700 /mnt/hugepages-ltran +chmod -R 700 /mnt/hugepages-lstack + +mount -t hugetlbfs nodev /mnt/hugepages-ltran -o pagesize=2M +mount -t hugetlbfs nodev /mnt/hugepages-lstack -o pagesize=2M ``` +>NOTE: +The huge pages mounted to **/mnt/hugepages-ltran** and **/mnt/hugepages-lstack** must be in the same page size. ### 5. Enabling Gazelle for an Application Enable Gazelle for an application using either of the following methods as required. -- Recompiling the application to link the Gazelle library. -Modify the makefile of the application to link to **liblstack.so**. The following is an example: -``` -# Add the Makefile of Gazelle to the application makefile. +- Recompile the application and replace the sockets interface. +```sh +#Add the Makefile of Gazelle to the application makefile. -include /etc/gazelle/lstack.Makefile -# Add the LSTACK_LIBS variable when compiling the source code. +#Add the LSTACK_LIBS variable when compiling the source code. gcc test.c -o test ${LSTACK_LIBS} ``` -- Using the **LD_PRELOAD** environment variable to load the Gazelle library. +- Use the **LD_PRELOAD** environment variable to load the Gazelle library. Use the **GAZELLE_BIND_PROCNAME** environment variable to specify the process name, and **LD_PRELOAD** to specify the Gazelle library path. -``` +```sh GAZELLE_BIND_PROCNAME=test LD_PRELOAD=/usr/lib64/liblstack.so ./test ``` ### 6. Configuring Gazelle - The **lstack.conf** file is used to specify the startup parameters of lstack. The default path is **/etc/gazelle/lstack.conf**. The parameters in the configuration file are as follows: -|Parameter|Value|Description| +|Options|Value|Remarks| |:---|:---|:---| -|dpdk_args|--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-type (mandatory)
--legacy-mem
--map-perfect
|DPDK initialization parameter. For details, see the DPDK description.| +|dpdk_args|--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-type (mandatory)
--legacy-mem
--map-perfect
-d|DPDK initialization parameter. For details, see the DPDK description.
**--map-perfect** is an extended feature. It is used to prevent the DPDK from occupying excessive address space and ensure that extra address space is available for lstack.
The **-d** option is used to load the specified .so library file.| +|listen_shadow| 0/1 | Whether to use the shadow file descriptor for listening. This function is enabled when there is a single listen thread and multiple protocol stack threads.| |use_ltran| 0/1 | Whether to use ltran.| |num_cpus|"0,2,4 ..."|IDs of the CPUs bound to the lstack threads. The number of IDs is the number of lstack threads (less than or equal to the number of NIC queues). You can select CPUs by NUMA nodes.| -|num_wakeup|"1,3,5 ..."|IDs of the CPUs bound to the wakeup threads. The number of IDs is the number of wakeup threads, which is the same as the number of lstack threads. Select CPUs of the same NUMA nodes of the num_cpus parameter respectively. If this parameter is not set, the wakeup thread is not used.| +|num_wakeup|"1,3,5 ..."|IDs of the CPUs bound to the wakeup threads. The number of IDs is the number of wakeup threads, which is the same as the number of lstack threads. Select CPUs of the same NUMA nodes of the **num_cpus** parameter respectively. If this parameter is not set, the wakeup thread is not used.| |low_power_mode|0/1|Whether to enable the low-power mode. This parameter is not supported currently.| -|kni_swith|0/1|Whether to enable the rte_kni module. The default value is 0. This module can be enabled only when ltran is not used.| -|host_addr|"192.168.xx.xx"|IP address of the protocol stack, which must be consistent with the **bind** field in the redis-server configuration file.| +|kni_switch|0/1|Whether to enable the rte_kni module. The default value is **0**. This module can be enabled only when ltran is not used.| +|host_addr|"192.168.xx.xx"|IP address of the protocol stack, which is also the IP address of the application.| |mask_addr|"255.255.xx.xx"|Subnet mask.| -|gateway_addr|"192.168.xx.1"|Gateway IP address.| +|gateway_addr|"192.168.xx.1"|Gateway address.| |devices|"aa:bb:cc:dd:ee:ff"|MAC address for NIC communication. The value must be the same as that of **bond_macs** in the **ltran.conf** file.| -**lstack.conf** example: -``` conf -dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-2M", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] +lstack.conf example: +```sh +dpdk_args=["--socket-mem", "2048,0,0,0", "--huge-dir", "/mnt/hugepages-lstack", "--proc-type", "primary", "--legacy-mem", "--map-perfect"] use_ltran=1 kni_switch=0 @@ -134,23 +139,23 @@ devices="aa:bb:cc:dd:ee:ff" - The **ltran.conf** file is used to specify ltran startup parameters. The default path is **/etc/gazelle/ltran.conf**. To enable ltran, set **use_ltran=1** in the **lstack.conf** file. The configuration parameters are as follows: -|**Function**|Parameter|Value|Description| -|:---|:---|:---|:---| -|kit|forward_kit|"dpdk"|Specifies the transceiver module of an NIC.
This field is reserved and is not used currently.| -||forward_kit_args|-l
--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-TYPE (mandatory)
--legacy-mem (mandatory)
--map-perfect (mandatory)
|DPDK initialization parameter. For details, see the DPDK description.
Note: **--map-perfect** is an extended feature. It is used to prevent the DPDK from occupying excessive address space and ensure that extra address space is available for lstack.| -|kni|kni_switch|0/1|Whether to enable the rte_kni module. The default value is 0.| -|dispatcher|dispatch_max_clients|n|Maximum number of clients supported by ltran.
1. In the multi-process single-thread scenario, the number of lstack instances cannot exceed 32. Each lstack instance has one network thread.
2. In the single-process multi-thread scenario, one lstack instance is supported. The number of network threads of the lstack instance cannot exceed 32.| -||dispatch_subnet|192.168.xx.xx|Subnet mask, which is the subnet segment of the IP addresses that can be identified by ltran. The value is an example. Set the subnet based on the site requirements.| -||dispatch_subnet_length|n|Length of the Subnet that can be identified by ltran. For example, if the value of length is 4, the value ranges from 192.168.1.1 to 192.168.1.16.| -|bond|bond_mode|n|Bond mode. Currently, only Active Backup (Mode1) is supported. The value is 1.| -||bond_miimon|n|Bond link monitoring time. The unit is millisecond. The value ranges from 1 to 2^64 - 1 - (1000 x 1000).| -||bond_ports|"0xaa"|DPDK NIC to be used. The value 0x1 indicates the first NIC.| -||bond_macs|"aa:bb:cc:dd:ee:ff"|MAC address of the bound NIC, which must be the same as the MAC address of the KNI.| -||bond_mtu|n|Maximum transmission unit. The default and maximum value is 1500. The minimum value is 68.| - -**ltran.conf** example: -``` conf -forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages --proc-type primary --legacy-mem --map-perfect --syslog daemon" +|Options|Value|Remarks| +|:---|:---|:---| +|forward_kit|"dpdk"|Specified transceiver module of an NIC.
This field is reserved and is not used currently.| +|forward_kit_args|-l
--socket-mem (mandatory)
--huge-dir (mandatory)
--proc-TYPE (mandatory)
--legacy-mem (mandatory)
--map-perfect (mandatory)
-d|DPDK initialization parameter. For details, see the DPDK description.
**--map-perfect** is an extended feature. It is used to prevent the DPDK from occupying excessive address space and ensure that extra address space is available for lstack.
The **-d** option is used to load the specified .so library file.| +|kni_switch|0/1|Whether to enable the rte_kni module. The default value is **0**.| +|dispatch_max_clients|n|Maximum number of clients supported by ltran.
The total number of lstack protocol stack threads cannot exceed 32.| +|dispatch_subnet|192.168.xx.xx|Subnet mask, which is the subnet segment of the IP addresses that can be identified by ltran. The value is an example. Set the subnet based on the site requirements.| +|dispatch_subnet_length|n|Length of the Subnet that can be identified by ltran. For example, if the value of length is 4, the value ranges from 192.168.1.1 to 192.168.1.16.| +|bond_mode|n|Bond mode. Currently, only Active Backup(Mode1) is supported. The value is 1.| +|bond_miimon|n|Bond link monitoring time. The unit is millisecond. The value ranges from 1 to 2^64 - 1 - (1000 x 1000).| +|bond_ports|"0x01"|DPDK NIC to be used. The value **0x01** indicates the first NIC.| +|bond_macs|"aa:bb:cc:dd:ee:ff"|MAC address of the bound NIC, which must be the same as the MAC address of the KNI.| +|bond_mtu|n|Maximum transmission unit. The default and maximum value is 1500. The minimum value is 68.| + +ltran.conf example: +```sh +forward_kit_args="-l 0,1 --socket-mem 1024,0,0,0 --huge-dir /mnt/hugepages-ltran --proc-type primary --legacy-mem --map-perfect --syslog daemon" forward_kit="dpdk" kni_switch=0 @@ -171,12 +176,12 @@ tcp_conn_scan_interval=10 - Start the ltran process. If there is only one process and the NIC supports multiple queues, the NIC multi-queue is used to distribute packets to each thread. You do not need to start the ltran process. Set the value of **use_ltran** in the **lstack.conf** file to **0**. If you do not use `-config-file` to specify a configuration file when starting ltran, the default configuration file path **/etc/gazelle/ltran.conf** is used. -``` sh +```sh ltran --config-file ./ltran.conf ``` - Start the application. If the environment variable **LSTACK_CONF_PATH** is not used to specify the configuration file before the application is started, the default configuration file path **/etc/gazelle/lstack.conf** is used. -``` sh +```sh export LSTACK_CONF_PATH=./lstack.conf LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-server redis.conf ``` @@ -185,11 +190,11 @@ LD_PRELOAD=/usr/lib64/liblstack.so GAZELLE_BIND_PROCNAME=redis-server redis-ser Gazelle wraps the POSIX interfaces of the application. The code of the application does not need to be modified. ### 9. Commissioning Commands -- If ltran is not used, the `gazellectl ltran xxx` and `lstack -r` commands are not supported. -``` +- If the ltran mode is not used, the **gazellectl ltran xxx** and **gazellectl lstack show {ip | pid} -r** commands are not supported. +```sh Usage: gazellectl [-h | help] - or: gazellectl ltran {quit | show} [LTRAN_OPTIONS] [time] - or: gazellectl lstack show {ip} [LSTACK_OPTIONS] [time] + or: gazellectl ltran {quit | show | set} [LTRAN_OPTIONS] [time] + or: gazellectl lstack {show | set} {ip | pid} [LSTACK_OPTIONS] [time] quit ltran process exit @@ -199,6 +204,8 @@ Usage: gazellectl [-h | help] -i, instance show ltran instance register info -b, burst show ltran NIC packet len per second -l, latency show ltran latency + set: + loglevel {error | info | debug} set ltran loglevel where LSTACK_OPTIONS := show lstack all statistics @@ -206,7 +213,9 @@ Usage: gazellectl [-h | help] -s, snmp show lstack snmp -c, connetct show lstack connect -l, latency show lstack latency - + set: + loglevel {error | info | debug} set lstack loglevel + lowpower {0 | 1} set lowpower enable [time] measure latency time default 1S ``` @@ -215,7 +224,7 @@ Usage: gazellectl [-h | help] For the **root** user, the configuration file is stored in the **/var/run/dpdk** directory after the DPDK is started. For a non-root user, the path of the DPDK configuration file is determined by the environment variable **XDG_RUNTIME_DIR**. - If **XDG_RUNTIME_DIR** is not set, the DPDK configuration file is stored in **/tmp/dpdk**. -- If **XDG_RUNTIME_DIR** is set, the DPDK configuration file is stored in in the path specified by **XDG_RUNTIME_DIR**. +- If **XDG_RUNTIME_DIR** is set, the DPDK configuration file is stored in the path specified by **XDG_RUNTIME_DIR**. - Note that **XDG_RUNTIME_DIR** is set by default on some servers. ## Restrictions @@ -237,27 +246,27 @@ Restrictions of Gazelle are as follows: - The minimum huge page memory required by ltran is 1 GB. - The minimum hugepage memory of each application instance protocol stack thread is 800 MB. - Gazelle supports only 64-bit OSs. -- The `-march=native` option is used when building the x86 version of Gazelle to optimize Gazelle based on the CPU instruction set of the build environment (Intel® Xeon® Gold 5118 CPU @ 2.30GHz). Therefore, the CPU of the running environment must support the SSE4.2, AVX, AVX2, and AVX-512 instruction set extensions. +- The `-march=native` option is used when building the x86 version of Gazelle to optimize Gazelle based on the CPU instruction set of the build environment (Intel® Xeon® Gold 5118 CPU @ 2.30GHz). Therefore, the CPU of the operating environment must support the SSE4.2, AVX, AVX2, and AVX-512 instruction set extensions. - The maximum number of IP fragments is 10 (the maximum ping packet length is 14,790 bytes). TCP does not use IP fragments. - You are advised to set the **rp_filter** parameter of the NIC to 1 using the `sysctl` command. Otherwise, the Gazelle protocol stack may not be used as expected. Instead, the kernel protocol stack is used. - If ltran is not used, the KNI cannot be configured to be used only for local communication. In addition, you need to configure the NetworkManager not to manage the KNI network adapter before starting Gazelle. - The IP address and MAC address of the virtual KNI must be the same as those in the **lstack.conf** file. -## Risk Warning -Gazelle may have the following security risks. You need to evaluate the risks based on the application scenario. +## Precautions +You need to evaluate the use of Gazelle based on application scenarios. -Shared memory +**Shared Memory** - Current situation: - The memory huge pages are mounted to the **/mnt/hugepages-2M** directory. During the initialization of a process that links to **liblstack.so**, files are created in the **/mnt/hugepages-2M** directory. Each file corresponds to a 2 MB memory huge page, and the mmap function is performed on the files. After receiving the registration information of lstask, ltran also perform the mmap function on the file in the directory based on the huge page memory configuration information to implement shared huge page memory. - The procedure also applies to the files in the **/mnt/hugepages** directory. -- Current Mitigation Measures + The memory huge pages are mounted to the **/mnt/hugepages-lstack** directory. During process initialization, files are created in the **/mnt/hugepages-lstack** directory. Each file corresponds to a huge page, and the mmap function is performed on the files. After receiving the registration information of lstask, ltran also perform the mmap function on the file in the directory based on the huge page memory configuration information to implement shared huge page memory. + The procedure also applies to the files in the **/mnt/hugepages-ltran** directory. +- Current mitigation measures The huge page file permission is **600**. Only the owner can access the files. The default owner is the **root** user. Other users can be configured. Huge page files are locked by DPDK and cannot be directly written or mapped. -- Risks: +- Caution Malicious processes belonging to the same user imitate the DPDK implementation logic to share huge page memory using huge page files and perform write operations to damage the huge page memory. As a result, the Gazelle program crashes. It is recommended that the processes of a user belong to the same trust domain. -**Traffic Limit**: +**Traffic Limit** Gazelle does not limit the traffic. Users can send packets at the maximum NIC line rate to the network, which may congest the network. -**Process spoofing**: +**Process Spoofing** If two lstack processes A and B are legitimately registered with ltran, A can impersonate B to send spoofing messages to ltran and modify the ltran forwarding control information. As a result, the communication of B becomes abnormal, and information leakage occurs when packets for B are sent to A. Ensure that all lstack processes are trusted. diff --git a/docs/en/docs/Kubernetes/installing-the-Kubernetes-software-package.md b/docs/en/docs/Kubernetes/installing-the-Kubernetes-software-package.md index 51ffbde22..e88f1adec 100644 --- a/docs/en/docs/Kubernetes/installing-the-Kubernetes-software-package.md +++ b/docs/en/docs/Kubernetes/installing-the-Kubernetes-software-package.md @@ -1 +1,14 @@ -# Installing the Kubernetes Software Package ```bash $ dnf install -y docker conntrack-tools socat ``` In versions later than EPOL, K8S can be directly installed through DNF. ```bash $ rpm -ivh kubernetes*.rpm ``` \ No newline at end of file +# Installing the Kubernetes Software Package + + +```bash +$ dnf install -y docker conntrack-tools socat +``` + +After the EPOL source is configured, you can directly install Kubernetes through DNF. + +```bash +$ rpm -ivh kubernetes*.rpm +``` + + diff --git a/docs/en/docs/Kubernetes/preparing-certificates.md b/docs/en/docs/Kubernetes/preparing-certificates.md index eb5d459e5..df4f4f9a0 100644 --- a/docs/en/docs/Kubernetes/preparing-certificates.md +++ b/docs/en/docs/Kubernetes/preparing-certificates.md @@ -175,7 +175,7 @@ Compile the CSR configuration of kube-controller-manager: Generate a certificate: ```bash -cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json-profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager +cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager ``` The result is as follows: @@ -289,7 +289,7 @@ EOF # generate ca echo "generate: ${nodes[$i]} ${IPs[$i]}" - cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -hostname=${nodes[$i]},${IPs[$i]}-profile=kubernetes ${nodes[$i]}-csr.json | cfssljson -bare ${nodes[$i]} + cfssl gencert -ca=../ca/ca.pem -ca-key=../ca/ca-key.pem -config=../ca/ca-config.json -hostname=${nodes[$i]},${IPs[$i]} -profile=kubernetes ${nodes[$i]}-csr.json | cfssljson -bare ${nodes[$i]} done ``` diff --git a/docs/en/docs/StratoVirt/StratoVirt_introduction.md b/docs/en/docs/StratoVirt/StratoVirt_introduction.md index 3fd1bd928..f7a5afcb4 100644 --- a/docs/en/docs/StratoVirt/StratoVirt_introduction.md +++ b/docs/en/docs/StratoVirt/StratoVirt_introduction.md @@ -26,26 +26,26 @@ Figure 1 shows the overall architecture. ## Features -- Highly isolated based on hardware; -- Fast cold boot: Benefiting from the minimalist design, a microVM can be started within 50ms; -- Low memory overhead: StratoVirt works with a memory footprint less than 4MB; -- I/O enhancement: StratoVirt offers normal I/O ability and minimalist I/O device emulation; -- OCI compatibility: StratoVirt works with iSula and Kata container, and can be integrated into Kubernetes ecosystem perfectly; -- Multi-platform support: Fully supports Intel and Arm platforms; -- Expandability: StratoVirt has interface and design for importing more features, and can expand to standard virtualization support; -- Security: lower than 46 syscalls while running; +- Highly isolated based on hardware. +- Fast cold boot: Benefiting from the minimalist design, a microVM can be started within 50ms. +- Low memory overhead: StratoVirt works with a memory footprint of less than 4 MB. +- I/O enhancement: StratoVirt offers normal I/O capabilities and minimalist I/O device emulation. +- OCI compatibility: StratoVirt works with iSula and Kata containers, and can be integrated into the Kubernetes ecosystem perfectly. +- Multi-platform support: StratoVirt fully supports Intel and Arm platforms. +- Extensibility: StratoVirt has interface and design for importing more features, and can be extended to support standard virtualization. +- Security: fewer than 46 syscalls while running. ## Implementation #### Running Architecture -- A StratoVirt VM is an independent process in Linux. The process has three types of threads: main thread, vCPU thread and I/O thread: - - The main thread is a cycle for asynchronous collecting and processing events from external modules, such as a vCPU thread; - - Each vCPU has a thread to handle trap events of this vCPU; - - I/O threads can be configured for I/O devices to improve I/O performance; +- A StratoVirt VM is an independent process in Linux. The process has three types of threads: main thread, vCPU thread, and I/O thread: + - The main thread is a cycle for asynchronously collecting and processing events from external modules, such as a vCPU thread. + - Each vCPU has a thread to handle trap events of this vCPU. + - I/O threads can be configured for I/O devices to improve I/O performance. ## Restrictions -- Only the Linux operating system is supported; The recommended kernel version is 4.19, 5.10; -- Only Linux is supported as the operating system of the VM, and the recommended kernel version is 4.19, 5.10; -- Supports a maximum of 254 CPUs; +- Only the Linux operating system is supported, and the recommended kernel versions are 4.19 and 5.10. +- Only Linux is supported as the operating system of the VM, and the recommended kernel versions are 4.19 and 5.10. +- A maximum of 254 CPUs are supported. diff --git a/docs/en/docs/StratoVirt/VM_configuration.md b/docs/en/docs/StratoVirt/VM_configuration.md index 3b14ec577..2112cbfb3 100644 --- a/docs/en/docs/StratoVirt/VM_configuration.md +++ b/docs/en/docs/StratoVirt/VM_configuration.md @@ -75,7 +75,7 @@ The following table lists the basic configuration information. | -append | console=ttyS0 root=/dev/vda reboot=k panic=1 rw | Configures the kernel command line parameter. For the standard virtualization AArch64 platform, set **console** to **ttyAMA0** instead of **ttyS0**.| | -initrd | /path/to/initrd.img | Configures the initrd file.| | -smp | [cpus=] CPU count| Configures the number of CPUs. The value range is [1, 254].| -| -m | Memory size (MiB/GiB). The default unit is MB.| Configures the memory size. The value range is [256 MiB, 512 GiB].| +| -m | Memory size (MiB/GiB). The default unit is MiB.| Configures the memory size. The value range is [256 MiB, 512 GiB].| | -qmp | unix:/path/to/socket,server,nowait | Configures api-channel. Before running api-channel, ensure that the socket file does not exist.| | -D | /path/to/logfile | Configures the log file.| | -pidfile | /path/to/pidfile | Configures the pid file. This parameter must be used together with **-daemonize**. Ensure that the pid file does not exist before running the script.| @@ -107,7 +107,7 @@ VM disk configuration includes the following configuration items: - **bus**: bus to which the device is to be mounted. - **addr**: IDs of the slot and function to which the device is to be mounted. - **multifunction** (optional): whether to enable PCI multi-function. -- **bootindex** (optional, only for standard machine): set the boot order of block device. If not set, the priority is lowest. The number ranges from 0 to 255, the smaller the number, the higher the priority. +- **bootindex** (optional, only for standard machine): boot priority of the block device. If this parameter is not set, the priority is default to the lowest. The value ranges from 0 to 255. A smaller value indicates a higher priority. #### Disk Configuration Modes diff --git a/docs/en/docs/Virtualization/introduction-to-virtualization.md b/docs/en/docs/Virtualization/introduction-to-virtualization.md index 0abe43ba5..c32dbb9e3 100644 --- a/docs/en/docs/Virtualization/introduction-to-virtualization.md +++ b/docs/en/docs/Virtualization/introduction-to-virtualization.md @@ -4,7 +4,7 @@ In computer technologies, virtualization is a resource management technology. It abstracts various physical resources \(such as processors, memory, disks, and network adapters\) of a computer, converts the resources, and presents the resources for segmentation and combination into one or more computer configuration environments. This resource management technology breaks the inseparable barrier of the physical structure, and makes these resources not restricted by the architecture, geographical or physical configuration of the existing resources after virtualization. In this way, users can better leverage the computer hardware resources and maximize the resource utilization. -Virtualization enables multiple virtual machines \(VMs\) to run on a physical server. The VMs share the processor, memory, and I/O resources of the physical server, but are logically isolated from each other. In the virtualization technology, the physical server is called a host machine, the VM running on the host machine is called a guest, and the operating system \(OS\) running on the VM is called a guest OS. A layer of software, called the virtualization layer, exists between a host machine and a VM to simulate virtual hardware. This virtualization layer is called a VM monitor, as shown in the following figure. +Virtualization enables multiple virtual machines \(VMs\) to run on a physical server. VMs share resources such as processors, memory, and I/O devices of physical machines, but are logically isolated from each other. In the virtualization technology, the physical server is called a host machine, the VM running on the host machine is called a guest, and the operating system \(OS\) running on the VM is called a guest OS. A layer of software, called the virtualization layer, exists between a host machine and a VM to simulate virtual hardware. This virtualization layer is called a VM monitor, as shown in the following figure. **Figure 1** Virtualized architecture ![](./figures/virtualized-architecture.png "virtualized-architecture") @@ -22,7 +22,7 @@ Currently, mainstream virtualization technologies are classified into two types In this model, physical resources are managed by a host OS, which is a traditional OS, such as Linux and Windows. The host OS does not provide the virtualization capability. The VMM that provides the virtualization capability runs on the host OS as a driver or software of the system. The VMM invokes the host OS service to obtain resources and simulate the processor, memory, and I/O devices. The virtualization implementation of this model includes KVM and Virtual Box. -Kernel-based Virtual Machine \(KVM\) is a kernel module of Linux. It makes Linux a hypervisor. [Figure 2](#fig310953013541) shows the KVM architecture. KVM does not simulate any hardware device. It is used to enable virtualization capabilities provided by the hardware, such as Intel VT-x, AMD-V, Arm virtualization extensions. The user-mode QEMU simulates the mainboard, memory, and I/O devices. The user-mode QEMU works with the kernel KVM module to simulate VM hardware. The guest OS runs on the hardware simulated by the QEMU and KVM. +Kernel-based Virtual Machine \(KVM\) is a kernel module of Linux. It makes Linux a hypervisor. [Figure 2](#fig310953013541) shows the KVM architecture. KVM does not simulate any hardware device. It is used to enable virtualization capabilities provided by the hardware, such as Intel VT-x, AMD-V, ARM virtualization extensions. The user-mode QEMU simulates the mainboard, memory, and I/O devices. The user-mode QEMU works with the KVM module to simulate VM hardware. The guest OS runs on the hardware simulated by the QEMU and KVM. **Figure 2** KVM architecture ![](./figures/kvm-architecture.png "kvm-architecture") diff --git a/docs/en/docs/Virtualization/virtualization-installation.md b/docs/en/docs/Virtualization/virtualization-installation.md index 88e10ed85..0029c084d 100644 --- a/docs/en/docs/Virtualization/virtualization-installation.md +++ b/docs/en/docs/Virtualization/virtualization-installation.md @@ -1,12 +1,12 @@ -# Installation Guide +# Installing Virtualization Components This chapter describes how to install virtualization components in openEuler. -- [Installation Guide](#installation-guide) - - [Minimum Hardware Requirements](#minimum-hardware-requirements) - - [Installing Core Virtualization Components](#installing-core-virtualization-components) - - [Installation Methods](#installation-methods) - - [Verifying the Installation](#verifying-the-installation) +- [Installing Virtualization Components](#installing-virtualization-components) + - [Minimum Hardware Requirements](#minimum-hardware-requirements) + - [Installing Core Virtualization Components](#installing-core-virtualization-components) + - [Installation Methods](#installation-methods) + - [Verifying the Installation](#verifying-the-installation) ## Minimum Hardware Requirements @@ -36,10 +36,10 @@ The minimum hardware requirements for installing virtualization components on op # yum install -y qemu ``` - >![](./public_sys-resources/icon-caution.gif) ** Notice: ** - >The QEMU component runs as the user qemu and user group qemu by default. If you do not understand the rights management of Linux user and users groups, you may encounter insufficient rights when creating and starting virtual machines. There are two solutions: - >Solution 1: Modify the QEMU configuration file. Open the QEMU configuration file with the following command, `sudo vim /etc/libvirt/qemu.conf`, find the following two fields, `user = "root"` and `group = "root"`, uncomment (ie delete the preceding `#`), save and exit. - >Solution 2: Modify the owner of the virtual machine file. First, you need to ensure that the user qemu has access to the folder where the virtual machine files are stored. Use the following command to modify the owner of the file, `sudo chown qemu:qemu xxx.qcow2`, and modify all virtual machine files that need to be read and written. + >![](./public_sys-resources/icon-caution.gif) Notice: + >By default, the QEMU component runs as user qemu and user group qemu. If you are not familiar with Linux user group and user permission management, you may encounter insufficient permission when creating and starting VMs. You can use either of the following methods to solve this problem: + >Method 1: Modify the QEMU configuration file. Run the `sudo vim /etc/libvirt/qemu.conf` command to open the QEMU configuration file, find `user = "root"` and `group = "root"`, uncomment them (delete `#`), save the file, and exit. + >Method 2: Change the owner of the VM files. Ensure that user qemu has the permission to access the folder where VM files are stored. Run the `sudo chown qemu:qemu xxx.qcow2` command to change the owner of the VM files that need to be read and written. 2. Install the libvirt component. diff --git a/docs/en/docs/Virtualization/vm-configuration.md b/docs/en/docs/Virtualization/vm-configuration.md index 5153271ef..3d83ed539 100644 --- a/docs/en/docs/Virtualization/vm-configuration.md +++ b/docs/en/docs/Virtualization/vm-configuration.md @@ -23,7 +23,7 @@ Libvirt tool uses XML files to describe a VM feature, including the VM name, CPU The VM XML configuration file uses domain as the root element, which contains multiple other elements. Some elements in the XML configuration file can contain corresponding attributes and attribute values to describe VM information in detail. Different attributes of the same element are separated by spaces. -The basic format of the XML configuration file is as follows. In the format, **label** indicates the label name, **attribute** indicates the attribute, and **value** indicates the attribute value. Change them based on the site requirements. +The basic format of the XML configuration file is as follows. In the format, **label** indicates the label name, **attribute** indicates the attribute, and **value** indicates the attribute value. Change them as required. ``` @@ -111,15 +111,15 @@ This section describes how to configure the vCPU and virtual memory. Sub-element **feature**: A sub-element of the element cpu, used to enable/disable a CPU feature when **mode** is custom. The attribute **name** describes the name of the CPU feature. And whether enable the CPU feature is controlled by the attribute **policy**: - - **force**: force enable the CPU feature regardless of it being supported by host CPU. + - **force**: forcibly enables the CPU feature regardless of whether it is supported by the host CPU. - - **require**: enable the CPU feature. + - **require**: enables the CPU feature. If both the host CPU and hypervisor do not support this feature, the VM will fail to be created. - - **optional**: the CPU feature will be enabled if and only if it is supported by host CPU. + - **optional**: The CPU feature will be enabled if it is supported by the host CPU. - - **disable**: disable the CPU feature. + - **disable**: disables the CPU feature. - - **forbid**: disable the CPU feature and guest creation will fail if the feature is supported by host CPU. + - **forbid**: disables the CPU feature. Guest creation will fail if the feature is supported by the host CPU. ### Configuration Example @@ -194,9 +194,9 @@ The XML configuration file uses the **disk** element to configure storage devi | Subelement | Subelement Description | Attribute Description | | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ | | source | Specifies the backend storage medium, which corresponds to the type specified by the **type** attribute of the **disk** element. | **file**: file type. The value is the fully qualified path of the corresponding file.
**dev**: block type. The value is the fully qualified path of the corresponding host device.
**dir**: directory type. The value is the fully qualified path of the disk directory.
**protocol**: protocol in use.
**name**: RBD disk name. The format is as follows: pool/pool/volume .**host name**: mon address.
**port**: port of the mon address.
| -| driver | Details about the specified backend driver | **type**: disk format type. The value can be **raw** or **qcow2**, which must be the same as that of source.
**io**: disk I/O mode. The options are **native** and **threads**.
**cache**: disk cache mode. The value can be **none**, **writethrough**, **writeback**, or **directsync**.
**iothread**: I/O thread allocated to the disk.
**error_policy**: processing policy when an I/O write error occurs. The value can be stop, report, ignore, enospace, or retry.
**rerror_policy**: processing policy when an I/O read error occurs. The value can be stop, report, ignore, enospac, or retry.
**retry_interval**: I/O retry interval. The value ranges from 0 to MAX_INT, in milliseconds. This parameter can be set only when error_policy or rerror_policy is set to retry.
**retry_timeout**: I/O retry timeout interval. The value ranges from 0 to MAX_INT, in milliseconds. This parameter can be set only when error_policy or rerror_policy is set to retry. | -| target | The bus and device that a disk presents to a VM. | **dev**: specifies the logical device name of a disk, for example, sd[a-p] for SCSI, SATA, and USB buses and hd[a-d] for IDE disks.

**bus**: specifies the type of a disk. Common types include scsi, usb, sata, and virtio. | -| boot | The disk can be used as the boot disk. | **order**: specifies the disk startup sequence. | +| driver | Details about the specified backend driver | **type**: disk format type. The value can be **raw** or **qcow2**, which must be the same as that of source.
**io**: disk I/O mode. The options are **native** and **threads**.
**cache**: disk cache mode. The value can be **none**, **writethrough**, **writeback**, or **directsync**.
**iothread**: I/O thread allocated to the disk.
**error_policy**: processing policy when an I/O write error occurs. The value can be stop, report, ignore, enospace, or retry.
**rerror_policy**: processing policy when an I/O read error occurs. The value can be **stop**, **report**, **ignore**, **enospac**, or **retry**.
**retry_interval**: I/O retry interval. The value ranges from 0 to MAX_INT, in milliseconds. This parameter can be set only when **error_policy** or **rerror_policy** is set to **retry**.
**retry_timeout**: I/O retry timeout interval. The value ranges from 0 to MAX_INT, in milliseconds. This parameter can be set only when **error_policy** or **rerror_policy** is set to **retry**. | +| target | The bus and device that a disk presents to a VM. | **dev**: logical device name of a disk, for example, sd[a-p] for SCSI, SATA, and USB buses and hd[a-d] for IDE disks.

**bus**: type of a disk. Common types include **scsi**, **usb**, **sata**, and **virtio**. | +| boot | The disk can be used as the boot disk. | **order**: disk startup sequence. | | readonly | The disk is read-only and cannot be modified by the VM. Generally, it is used together with the CD-ROM drive. | - | #### Configuration Example @@ -260,7 +260,7 @@ In the XML configuration file, the element **interface** is used, and its attr

The mac address of the vNIC.

address: specifies the mac address. If this parameter is not set, the system automatically generates a mac address.

+

address: MAC address. If this parameter is not set, the system automatically generates a MAC address.

target

@@ -281,7 +281,7 @@ In the XML configuration file, the element **interface** is used, and its attr

The NIC can be used for remote startup.

order: specifies the startup sequence of NICs.

+

order: startup sequence of NICs.

model

@@ -303,7 +303,7 @@ In the XML configuration file, the element **interface** is used, and its attr

Backend driver type

name: driver name. The value is vhost.

-

queues: the number of NIC queues.

+

queues: number of NIC queues.

The address type is storage device address, indicating the owning disk controller and its position on the bus.

controller: the number of the owning controller.

+

controller: number of the owning controller.

bus: channel number of the device output.

target: target number of the storage device.

-

unit: lun number of the storage device.

+

unit: LUN number of the storage device.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口

+

说明

+

int BM_Init(char *ockPath, int flags);

+

int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); int BM_Exit(void);

+

初始化

+

带属性的初始化

+

退出

+

int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId);

+

int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId);

+

int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen);

+

Namespace创建和销毁、查询

+

int BM_AllocSec(BmInfo *bminfo, size_t size, int flags, BmAffinity* affinity);

+

int BM_FreeSec(BmInfo *bminfo, int flags);

+

int BM_BatchFreeSec(char *bmIdArray[], int num, int flags, const char *ns, const char *secId);

+

Bigmemory对象申请和释放

+

int BM_ExpandSec(BmInfo *bminfo, size_t size, int flags);

+

bigMemory扩容

+

int BM_MapSec(BmInfo *bminfo, int prot, int flags, void **ptr);

+

int BM_Unmap(char *bmId, void *ptr);

+

bigMemory到连续虚拟空间map和unmap

+

int BM_CopySec(BmInfo *srcBM, size_t srcOffset, BmInfo *dstBM, size_t dstOffset, size_t length, int flags);

+

bigMemory对象间拷贝

+

int BM_SpecificObjSwapInSec(DiskFileDesc *file, BmInfo *bminfo, int flags, size_t offset, size_t length);

+

文件内容换入bigmemory对象

+

int BM_ReadSec(BmInfo *bminfo, size_t offset, size_t length, void *buffer, int flags);

+

int BM_WriteSec(BmInfo *bminfo, size_t offset, size_t length, const void *buffer, int flags);

+

Bigmemory读写

+

int BM_GatherSec(intptr_t *inputInfo, BmOperatorCode operatorCode, int flags, BmInfo *bminfo, size_t *bmLen);

+

聚合操作接口

+
+ -- Gitee From 22345b9ca184f7bf6b5033a99e8c25cb26acf679 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 2 Sep 2022 02:30:08 +0000 Subject: [PATCH 127/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?docs/zh/docs/memory-fabric/Memory=20Fabric=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...4\250\346\210\267\346\214\207\345\215\227" | 57 ------------------- 1 file changed, 57 deletions(-) delete mode 100644 "docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" deleted file mode 100644 index 0c0d86eb8..000000000 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227" +++ /dev/null @@ -1,57 +0,0 @@ -# Memory Fabric用户指南 - - - -- [#Memory Fabric用户指南](#Memory Fabric用户指南) - - [简介](#简介) - - [部署](#部署) - - [启动](#启动) - - [接口](#接口) - - - -## 简介 -内存池套件设计目标为基于内存型介质和新型网络技术,构建高性能的分布式内存资源池,并通过BigMemory、MemPlog、MemKV等语义对应用提供服务。内存池套件使用和管理的资源来自于计算节点或者单独资源节点提供的可共享的DRAM/Persistent Memory/内存盘等(不支持普通disk直接互联池化)。结合新型互联协议(RDMA,CXL,UBUS)us级传输时延,期望内存池套件通过极低的软件时延和节点CPU开销带来整体性能提升。 -## 部署 -Memory Fabric需要支持多场景应用集成部署,根据节点类型、资源分布情况和应用需求对集成部署做如下描述: -(1) 计算和MF资源共节点时支持client和server同节点部署,如下图node1、node2所示。 -(2) 资源独立提供时也支持client、server分离节点部署,如下图node3、node4所示。 -(3) 支持(1)(2)场景混合部署。 -(4) 节点内支持多client,也支持多server模式部署,如下图node2所示。 -(5) client与同节点的server通信使用IPC,配置支持连接远端server时使用RPC通信。 -(6) server端接入集群管理服务中,用于统一的节点编号和资源信息广播。 - -## 启动 -Memory Fabric启动分为server和client两个部分。在节点上优先启动server端,完成集群注册、监控流程,然后启动本地资源注册(总容量通过配置文件获取)和通信建链流程,初始化完成后支持本地多client与server建立链接,可对外启动业务服务 - -## 接口 -| 接口 | 说明 | -| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -|int BM_Init(char *ockPath, int flags); | 初始化 - int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); | 带属性的初始化 - int BM_Exit(void); | 退出 | -|int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId); - int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId); - int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen); | Namespace创建和销毁、查询 | -| Python | 版本 3.8及以上 | - -接口 说明 -int BM_Init(char *ockPath, int flags); -int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); int BM_Exit(void); 初始化 -带属性的初始化 -退出 -int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId); -int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId); -int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen); Namespace创建和销毁、查询 -int BM_AllocSec(BmInfo *bminfo, size_t size, int flags, BmAffinity* affinity); -int BM_FreeSec(BmInfo *bminfo, int flags); -int BM_BatchFreeSec(char *bmIdArray[], int num, int flags, const char *ns, const char *secId); Bigmemory对象申请和释放 -int BM_ExpandSec(BmInfo *bminfo, size_t size, int flags); bigMemory扩容 -int BM_MapSec(BmInfo *bminfo, int prot, int flags, void **ptr); -int BM_Unmap(char *bmId, void *ptr); bigMemory到连续虚拟空间map和unmap -int BM_CopySec(BmInfo *srcBM, size_t srcOffset, BmInfo *dstBM, size_t dstOffset, size_t length, int flags); bigMemory对象间拷贝 -int BM_SpecificObjSwapInSec(DiskFileDesc *file, BmInfo *bminfo, int flags, size_t offset, size_t length); 文件内容换入bigmemory对象 -int BM_ReadSec(BmInfo *bminfo, size_t offset, size_t length, void *buffer, int flags); -int BM_WriteSec(BmInfo *bminfo, size_t offset, size_t length, const void *buffer, int flags); Bigmemory读写 -int BM_GatherSec(intptr_t *inputInfo, BmOperatorCode operatorCode, int flags, BmInfo *bminfo, size_t *bmLen); 聚合操作接口 - -- Gitee From 1eb1e4e4a0182ea71b60048b6976c62d699f81fc Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 2 Sep 2022 02:39:56 +0000 Subject: [PATCH 128/130] =?UTF-8?q?=E6=96=B0=E5=BB=BA=20image?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/memory-fabric/image/.keep | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/zh/docs/memory-fabric/image/.keep diff --git a/docs/zh/docs/memory-fabric/image/.keep b/docs/zh/docs/memory-fabric/image/.keep new file mode 100644 index 000000000..e69de29bb -- Gitee From 5c4050409e6015aa18c6595911b704c26afcfde3 Mon Sep 17 00:00:00 2001 From: Dream03 Date: Fri, 2 Sep 2022 02:42:28 +0000 Subject: [PATCH 129/130] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=96=87=E4=BB=B6=20?= =?UTF-8?q?docs/zh/docs/memory-fabric/Memory=20Fabric=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=8C=87=E5=8D=97.md?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...50\346\210\267\346\214\207\345\215\227.md" | 97 ------------------- 1 file changed, 97 deletions(-) delete mode 100644 "docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" diff --git "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" "b/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" deleted file mode 100644 index 786dfc6d2..000000000 --- "a/docs/zh/docs/memory-fabric/Memory Fabric\347\224\250\346\210\267\346\214\207\345\215\227.md" +++ /dev/null @@ -1,97 +0,0 @@ -# Memory Fabric用户文档 - -- [简介](简介.md) -- [部署](部署.md) -- [启动](启动.md) -- [接口](接口.md) - -# 简介 - -内存池套件是基于内存型介质和新型网络技术,构建高性能的分布式内存资源池,并通过BigMemory、MemPlog、MemKV等语义对应用提供服务。 - -内存池套件使用和管理的资源来自计算节点或者单独资源节点提供的可共享的DRAM/Persistent Memory/内存盘等(不支持普通disk直接互联池化),结合新型互联协议(RDMA,CXL,UBUS)us级传输时延,期望内存池套件通过极低的软件时延和节点CPU开销带来整体性能提升。 - -# 部署 - -Memory Fabric需要根据节点类型、资源分布情况和应用需求做到多场景应用集成部署,具体描述如下: - -- 计算和MF资源共节点时支持client和server同节点部署,如[图1](#fig17349154610267)node1、node2所示。 -- 资源独立提供时也支持client、server分离节点部署,如[图1](#fig17349154610267)node3、node4所示。 -- 支持同节点部署和分离节点部署两种场景混合部署。 -- 节点内支持多client,也支持多server模式部署,如[图1](#fig17349154610267)node2所示。 -- client与同节点的server通信使用IPC,配置支持连接远端server时使用RPC通信。 -- server端接入集群管理服务中,用于统一的节点编号和资源信息广播。 - -**图 1** 集成部署 -![](figures/集成部署.png "集成部署") - -# 启动 - -Memory Fabric启动分为server和client两个部分。在节点上优先启动server端,完成集群注册、监控流程,然后启动本地资源注册\(总容量通过配置文件获取\)和通信建链流程,初始化完成后支持本地多client与server建立连接,可对外启动业务服务。 - -# 接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口

-

说明

-

int BM_Init(char *ockPath, int flags);

-

int BM_InitWithExtAttr(char *ockPath, int flags, void *attr); int BM_Exit(void);

-

初始化

-

带属性的初始化

-

退出

-

int BM_CreateNSSec(const char *poolName, const char *ns, int attribute, const char *secId);

-

int BM_DestroyNSSec(const char *poolName, const char *ns, const char *secId);

-

int BM_QueryNSCache(QueryNsCache *buff, size_t buffLen);

-

Namespace创建和销毁、查询

-

int BM_AllocSec(BmInfo *bminfo, size_t size, int flags, BmAffinity* affinity);

-

int BM_FreeSec(BmInfo *bminfo, int flags);

-

int BM_BatchFreeSec(char *bmIdArray[], int num, int flags, const char *ns, const char *secId);

-

Bigmemory对象申请和释放

-

int BM_ExpandSec(BmInfo *bminfo, size_t size, int flags);

-

bigMemory扩容

-

int BM_MapSec(BmInfo *bminfo, int prot, int flags, void **ptr);

-

int BM_Unmap(char *bmId, void *ptr);

-

bigMemory到连续虚拟空间map和unmap

-

int BM_CopySec(BmInfo *srcBM, size_t srcOffset, BmInfo *dstBM, size_t dstOffset, size_t length, int flags);

-

bigMemory对象间拷贝

-

int BM_SpecificObjSwapInSec(DiskFileDesc *file, BmInfo *bminfo, int flags, size_t offset, size_t length);

-

文件内容换入bigmemory对象

-

int BM_ReadSec(BmInfo *bminfo, size_t offset, size_t length, void *buffer, int flags);

-

int BM_WriteSec(BmInfo *bminfo, size_t offset, size_t length, const void *buffer, int flags);

-

Bigmemory读写

-

int BM_GatherSec(intptr_t *inputInfo, BmOperatorCode operatorCode, int flags, BmInfo *bminfo, size_t *bmLen);

-

聚合操作接口

-
- -- Gitee From 10c73f8356fdb708ab44c1a4437f71e8315df4d3 Mon Sep 17 00:00:00 2001 From: jiang-dawei15 Date: Thu, 8 Sep 2022 16:04:17 +0800 Subject: [PATCH 130/130] =?UTF-8?q?LibcarePlus.md:=E4=BF=AE=E6=94=B9libcar?= =?UTF-8?q?eplus=E4=B8=ADmakefile=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh/docs/Virtualization/LibcarePlus.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/zh/docs/Virtualization/LibcarePlus.md b/docs/zh/docs/Virtualization/LibcarePlus.md index f1c84e985..ca0db830e 100644 --- a/docs/zh/docs/Virtualization/LibcarePlus.md +++ b/docs/zh/docs/Virtualization/LibcarePlus.md @@ -245,10 +245,10 @@ LibcarePlus 支持如下方式制作热补丁: -2. 编写编译 foo.c 的 MakeFile 文件,具体如下所示: +2. 编写编译 foo.c 的 Makefile 文件,具体如下所示:
- 点击展开 MakeFile + 点击展开 Makefile

``` makefile @@ -269,7 +269,7 @@ LibcarePlus 支持如下方式制作热补丁:

-3. 编写好 MakeFile 之后,直接调用 **libcare-patch-make** 即可。若 **libcare-patch-make** 询问选择哪个文件进行打补丁操作,输入原文件名即可,具体如下所示: +3. 编写好 Makefile 之后,直接调用 **libcare-patch-make** 即可。若 **libcare-patch-make** 询问选择哪个文件进行打补丁操作,输入原文件名即可,具体如下所示: ``` shell # libcare-patch-make --clean -i 0001 foo.patch -- Gitee