diff --git a/plugins/dify/config.yaml b/plugins/dify/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..06da6e93283b039a2f380252c197641b387c1eed --- /dev/null +++ b/plugins/dify/config.yaml @@ -0,0 +1,31 @@ +all: + hosts: + # 待修改,NODE_NAME 为节点唯一标识。示例值:dify_node + NODE_NAME: + # 待修改,NODE_IP 为节点 IP地址。示例值:192.168.10.1 + ansible_host: NODE_IP + # 待修改,NODE_PORT 为节点端口号。示例值:22 + ansible_port: NODE_PORT + # 待修改,NODE_USER 为节点用户名。示例值:root + ansible_user: NODE_USER + # 待修改,NODE_PASSWORD 为节点密码。 + ansible_password: NODE_PASSWORD + vars: + # 目标节点最小配置要求 + # 最小 CPU 核心数 + MIN_CPU: 2 + # 最小内存 + MIN_MEM_GB: 4 + + # Docker 镜像加速站 + DOCKER_IMAGE_URL: https://docker.m.daocloud.io + + # Dify 源码目录 + DIFY_CODE_DIR: /opt/dify + # Dify github 地址 + DIFY_GIT_URL: https://github.com/langgenius/dify.git + # github 代理代理 + GITHUB_PROXY: https://gh.idayer.com/ + + # 跳过 ssh 校验(如需禁用此功能,请注释以下配置项) + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' \ No newline at end of file diff --git a/plugins/dify/doc/readme.md b/plugins/dify/doc/readme.md new file mode 100644 index 0000000000000000000000000000000000000000..963e21d2447454128927814ce0108910d21ae65f --- /dev/null +++ b/plugins/dify/doc/readme.md @@ -0,0 +1,119 @@ +# Dify 插件使用说明 + +## 1. 准备环境 + +准备两个节点(三层网络互通),OS 版本为 openEuler 24.03 或 22.03 的任意 LTS 版本,规格大于 2U4G。 + +## 2. 安装 oedp + +在控制节点上,下载并安装 oeDeploy 的命令行工具`oedp (version >= 1.1.0-2)`。 + +````bash +wget https://repo.oepkgs.net/openEuler/rpm/openEuler-24.03-LTS/contrib/oedp/noarch/oedp-1.1.0-2.oe2403sp2.noarch.rpm +yum install -y oedp-1.1.0-3.oe2403sp2.noarch.rpm +```` + +## 3. 获取插件和插件介绍 + +在控制节点上下载插件 `dify.tar.gz`,然后将其解压。插件的目录结构如下所示: + +``` +dify +├── config.yaml +├── doc +│ └── readme.md +├── main.yaml +└── workspace + ├── check-env.yaml + ├── files + │ └── openEuler2409.repo + ├── install-dify.yaml + ├── install-docker.yaml + ├── templates + │ └── daemon.j2 + └── uninstall-dify.yaml +``` + +我们主要需要关注 `dify/config.yaml` 文件,在运行插件之前,需要确保配置值 `NODE_NAME`、`NODE_IP`、`NODE_PORT`、`NODE_USER`、`NODE_PASSWORD`得到正确的修改。其内容如下: +```yaml +all: + hosts: + # 待修改,NODE_NAME 为节点唯一标识。示例值:dify_node + NODE_NAME: + # 待修改,NODE_IP 为节点 IP地址。示例值:192.168.10.1 + ansible_host: NODE_IP + # 待修改,NODE_PORT 为节点端口号。示例值:22 + ansible_port: NODE_PORT + # 待修改,NODE_USER 为节点用户名。示例值:root + ansible_user: NODE_USER + # 待修改,NODE_PASSWORD 为节点密码。 + ansible_password: NODE_PASSWORD + vars: + # 目标节点最小配置要求 + # 最小 CPU 核心数 + MIN_CPU: 2 + # 最小内存 + MIN_MEM_GB: 4 + + # Docker 镜像加速站 + DOCKER_IMAGE_URL: https://docker.m.daocloud.io + + # Dify 源码目录 + DIFY_CODE_DIR: /opt/dify + # Dify github 地址 + DIFY_GIT_URL: https://github.com/langgenius/dify.git + # github 代理 + GITHUB_PROXY: https://gh.idayer.com/ + + # 跳过 ssh 校验(如需禁用此功能,请注释以下配置项) + ansible_ssh_common_args: '-o StrictHostKeyChecking=no' +``` + +> **注意** +> - 如果使用 SSH 密钥对进行认证,并提前将控制节点的公钥加入目标节点的 ~/.ssh/authorized_keys 文件中,则 `NODE_PASSWORD` 替换为空值。 +> - 如果使用 `GITHUB_PROXY` 会导致 git clone 代码失败,可以尝试将其设置为空值,然后重试。 + +同时对如下两个文件进行说明: + +- 文件 `dify/workspace/files/openEuler24.09.repo` 提供了 Docker 的安装源,会放置到目标节点的目录 `/etc/yum.repo.d` 下。 + +- 文件 `dify/workspace/templates/daemon.j2` 为 Docker 的配置文件,会放置到目标节点的目录 `/etc/docker` 下并更名为 `daemon.json`。 + +## 4. 执行插件 + +### 4.1 查看插件信息 + +```bash +oedp info -p ./dify +``` + +> 选项 `-p` 后面跟插件解压后的目录路径。 + +输出如下: + +``` +[ INFO ] - [info_cmd] - name: dify +version: +description: install and uninstall Dify +action: ++---+-----------+----------------+ +| # | Action | Description | ++---+-----------+----------------+ +| 1 | install | Install Dify | +| 2 | uninstall | Uninstall Dify | ++---+-----------+----------------+ +``` + +> 输出表示 dify 插件有两个操作,分别是安装和卸载 Dify + +### 4.2 安装 Dify + +```bash +oedp run install -p ./dify +``` + +### 4.3 卸载 Dify + +```bash +oedp run uninstall -p ./dify +``` \ No newline at end of file diff --git a/plugins/dify/main.yaml b/plugins/dify/main.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ecc08866a6452b09e8d0bbaca6d78a433d0fbc54 --- /dev/null +++ b/plugins/dify/main.yaml @@ -0,0 +1,21 @@ +name: dify +description: install and uninstall Dify +action: + install: + description: Install Dify + tasks: + - name: Check env + playbook: check-env.yaml + scope: all + - name: Install Docker + playbook: install-docker.yaml + scope: all + - name: Install Dify + playbook: install-dify.yaml + scope: all + uninstall: + description: Uninstall Dify + tasks: + - name: Uninstall Dify + playbook: uninstall-dify.yaml + scope: all \ No newline at end of file diff --git a/plugins/dify/workspace/check-env.yaml b/plugins/dify/workspace/check-env.yaml new file mode 100644 index 0000000000000000000000000000000000000000..acaf821f16964e2279b781eaac3d9b0dfeb2786c --- /dev/null +++ b/plugins/dify/workspace/check-env.yaml @@ -0,0 +1,24 @@ +- name: Check env + hosts: all + + tasks: + - name: Check the number of CPU cores + ansible.builtin.assert: + that: + - ansible_processor_vcpus >= MIN_CPU + success_msg: "Current CPU cores: {{ ansible_processor_vcpus }} (meets requirement)." + fail_msg: "Current CPU cores: {{ ansible_processor_vcpus }} (does not meet requirement)." + + - name: Check memory size + ansible.builtin.assert: + that: + - ansible_memtotal_mb >= (MIN_MEM_GB * 1024) + success_msg: "Current memory: {{ (ansible_memtotal_mb / 1024) | round(2) }} GB (meets requirement)." + fail_msg: "Current memory: {{ (ansible_memtotal_mb / 1024) | round(2) }} GB (does not meet requirement)." + + - name: Install packages + yum: + name: + - python3-libselinux + - git + state: present \ No newline at end of file diff --git a/plugins/dify/workspace/files/openEuler2409.repo b/plugins/dify/workspace/files/openEuler2409.repo new file mode 100644 index 0000000000000000000000000000000000000000..10471507d27eae1164b0a8cf742c1311fbcb42db --- /dev/null +++ b/plugins/dify/workspace/files/openEuler2409.repo @@ -0,0 +1,18 @@ +[openEuler2409-everything] +name=openEuler2409-everything +baseurl=https://repo.huaweicloud.com/openeuler/openEuler-24.09/everything/$basearch/ +enabled=1 +gpgcheck=0 +gpgkey=https://repo.huaweicloud.com/openeuler/openEuler-24.09/everything/$basearch/RPM-GPG-KEY-openEuler + +[openEuler2409-EPOL] +name=openEuler2409-epol +baseurl=https://repo.huaweicloud.com/openeuler/openEuler-24.09/EPOL/main/$basearch/ +enabled=1 +gpgcheck=0 + +[openEuler2409-update] +name=openEuler2409-update +baseurl=https://repo.huaweicloud.com/openeuler/openEuler-24.09/update/$basearch/ +enabled=1 +gpgcheck=0 diff --git a/plugins/dify/workspace/install-dify.yaml b/plugins/dify/workspace/install-dify.yaml new file mode 100644 index 0000000000000000000000000000000000000000..07d908125d04c34142d27813175b0a39aa27271f --- /dev/null +++ b/plugins/dify/workspace/install-dify.yaml @@ -0,0 +1,44 @@ +- name: Install Dify + hosts: all + become: yes + + tasks: + - name: Validate code directory + ansible.builtin.stat: + path: "{{ DIFY_CODE_DIR }}" + register: dir_check + tags: always + + - name: Clone Dify code + ansible.builtin.git: + repo: "{{ GITHUB_PROXY }}{{ DIFY_GIT_URL }}" + dest: "{{ DIFY_CODE_DIR }}" + when: not dir_check.stat.exists + + - name: Check if file exists + ansible.builtin.stat: + path: "{{ DIFY_CODE_DIR }}/docker/.env.example" + register: file_check + + - name: Fail if file doesn't exist + ansible.builtin.fail: + msg: "文件 {{ DIFY_CODE_DIR }}/docker/.env.example 不存在" + when: not file_check.stat.exists or not file_check.stat.isreg + + - name: Copy file in specified directory + ansible.builtin.copy: + src: "{{ DIFY_CODE_DIR }}/docker/.env.example" + dest: "{{ DIFY_CODE_DIR }}/docker/.env" + remote_src: yes + mode: preserve + force: yes + when: file_check.stat.exists + + - name: Launch Docker stack with retry + ansible.builtin.command: + cmd: docker compose up -d + chdir: "{{ DIFY_CODE_DIR }}/docker" + register: stack_result + retries: 5 + delay: 30 + until: stack_result is succeeded \ No newline at end of file diff --git a/plugins/dify/workspace/install-docker.yaml b/plugins/dify/workspace/install-docker.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e5725299d2a0855f2f7e74f9d50e6219937e4529 --- /dev/null +++ b/plugins/dify/workspace/install-docker.yaml @@ -0,0 +1,169 @@ +- name: Install Docker + hosts: all + become: yes + + vars: + MIN_DOCKER_VERSION: "24.0.0" + DOCKER_PKGS: + - docker + + tasks: + - name: Check if Docker is installed + ansible.builtin.command: "docker --version" + register: docker_check + ignore_errors: yes + changed_when: false + tags: install + + - name: Get raw Docker version + ansible.builtin.shell: | + docker --version 2>/dev/null | awk -F'[ ,]' '/version/ {print $3}' | tr -d ' ' + register: docker_version_raw + changed_when: false + args: + executable: /bin/bash + when: docker_check is succeeded + tags: install + + - name: Extract docker version + ansible.builtin.set_fact: + installed_docker_version: "{{ docker_version_raw.stdout | trim | default('unknown') }}" + when: docker_check is succeeded + tags: install + + - name: Validate version format + ansible.builtin.assert: + that: + - installed_docker_version is match('^\\d+\\.\\d+\\.\\d+$') + fail_msg: "Docker version extraction failed, current value: {{ installed_docker_version }}" + when: docker_check is succeeded and installed_docker_version != 'unknown' + tags: install + + - name: Determine installation requirement + ansible.builtin.set_fact: + requires_installation: >- + {{ + docker_check is failed or + ( + (installed_docker_version | default('0.0.0', true) | trim) + is version( + MIN_DOCKER_VERSION, + '<' + ) + ) + }} + tags: install + + - name: Copy openEuler2409.repo to /etc/yum.repo.d + ansible.builtin.copy: + src: openEuler2409.repo + dest: /etc/yum.repos.d/openEuler2409.repo + owner: root + group: root + mode: 0644 + when: requires_installation + notify: Clean yum cache + tags: install + + - name: Install Docker packages + ansible.builtin.yum: + name: "{{ DOCKER_PKGS }}" + state: latest + update_cache: yes + when: requires_installation + notify: Start docker service + tags: install + + - name: Get raw Docker version after installation + ansible.builtin.shell: | + docker --version 2>/dev/null | awk -F'[ ,]' '/version/ {print $3}' | tr -d ' ' + register: docker_version_raw + changed_when: false + args: + executable: /bin/bash + when: requires_installation + tags: install + + - name: Extract docker version after installation + ansible.builtin.set_fact: + installed_docker_version: "{{ docker_version_raw.stdout | trim | default('unknown') }}" + when: requires_installation + tags: install + + - name: Validate version after installation + ansible.builtin.assert: + that: >- + {{ + (installed_docker_version | default('0.0.0', true) | trim) + is version(MIN_DOCKER_VERSION, '>=') + }} + fail_msg: "Docker version check FAILED after installation!" + success_msg: "Docker version check PASSED" + when: requires_installation + tags: install + + - name: Create /etc/docker directory + file: + path: /etc/docker + state: directory + mode: '0755' + owner: root + group: root + + - name: Deploy new configuration template + ansible.builtin.template: + src: daemon.j2 + dest: /etc/docker/daemon.json + mode: "0644" + backup: yes + notify: Restart docker service + + - name: Set dynamic docker-compose-plugin download URL + ansible.builtin.set_fact: + download_url: "https://repo.oepkgs.net/openEuler/rpm/openEuler-24.03-LTS/contrib/oedp/files/docker-compose-plugin-2.27.1-1.{{ ansible_architecture }}.tar.gz" + + - name: Download docker-compose-plugin tarball + ansible.builtin.get_url: + url: "{{ download_url }}" + dest: /opt/ + timeout: 900 + register: download_result + until: download_result is success + retries: 3 + delay: 10 + + - name: Unarchive docker-compose-plugin package + unarchive: + src: "/opt/docker-compose-plugin-2.27.1-1.{{ ansible_architecture }}.tar.gz" + dest: /opt + remote_src: yes + + - name: Copy docker-compose binary file + ansible.builtin.command: "cp -rf /opt/docker-compose-plugin-2.27.1-1.{{ ansible_architecture }}/usr/libexec/docker /usr/libexec" + changed_when: false + + - name: Start and enable Docker service + ansible.builtin.service: + name: docker + state: started + enabled: yes + + handlers: + - name: Clean yum cache + ansible.builtin.command: "yum clean all" + listen: "Clean yum cache" + + - name: Start docker service + ansible.builtin.service: + name: docker + state: started + enabled: yes + listen: "Start docker service" + + - name: Restart docker service + ansible.builtin.service: + name: docker + state: restarted + enabled: yes + daemon_reload: yes + listen: "Restart docker service" diff --git a/plugins/dify/workspace/templates/daemon.j2 b/plugins/dify/workspace/templates/daemon.j2 new file mode 100644 index 0000000000000000000000000000000000000000..d2ba0b418003933ed1734ebfa790873576b8985e --- /dev/null +++ b/plugins/dify/workspace/templates/daemon.j2 @@ -0,0 +1,3 @@ +{ + "registry-mirrors": ["{{ DOCKER_IMAGE_URL }}"] +} diff --git a/plugins/dify/workspace/uninstall-dify.yaml b/plugins/dify/workspace/uninstall-dify.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e9c4f69a62ba5437610e5b0c677d4169fd645297 --- /dev/null +++ b/plugins/dify/workspace/uninstall-dify.yaml @@ -0,0 +1,35 @@ +- name: Uninstall RAGFlow + hosts: all + become: yes + + vars: + target_containers: + - docker-nginx-1 + - docker-worker-1 + - docker-api-1 + - docker-plugin_daemon-1 + - docker-sandbox-1 + - docker-db-1 + - docker-ssrf_proxy-1 + - docker-redis-1 + - docker-web-1 + - docker-weaviate-1 + + tasks: + - name: Stop containers + shell: "docker stop {{ item }} || true" + loop: "{{ target_containers }}" + changed_when: false + register: stop_output + + - name: Force remove containers + shell: "docker rm -f {{ item }} || true" + loop: "{{ target_containers }}" + register: remove_output + + - name: Check removal status + shell: "docker ps -a --filter 'name={{ item }}' --format '{{ '{{.Names}}' }}'" + loop: "{{ target_containers }}" + register: check_result + failed_when: check_result.stdout != "" + changed_when: false \ No newline at end of file