#!/bin/bash
set -eo pipefail
RED='\e[31m'
GREEN='\e[32m'
YELLOW='\e[33m'
BLUE='\e[34m'
NC='\e[0m'
NAMESPACE="euler-copilot"
PLUGINS_DIR="/var/lib/eulercopilot"
client_id=""
client_secret=""
eulercopilot_address=""
authhub_address=""
SCRIPT_PATH="$(
cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1
pwd
)/$(basename "${BASH_SOURCE[0]}")"
DEPLOY_DIR="$(
canonical_path=$(readlink -f "$SCRIPT_PATH" 2>/dev/null || echo "$SCRIPT_PATH")
dirname "$(dirname "$(dirname "$canonical_path")")"
)"
show_help() {
echo -e "${GREEN}Usage: $0 [options]"
echo -e "Options:"
echo -e " --help Show this help message"
echo -e " --eulercopilot_address Specify openEuler Intelligence frontend access URL"
echo -e " --authhub_address Specify Authhub frontend access URL"
echo -e ""
echo -e "Example:"
echo -e " $0 --eulercopilot_address http://myhost:30080 --authhub_address http://myhost:30081${NC}"
exit 0
}
parse_arguments() {
while [[ $# -gt 0 ]]; do
case "$1" in
--help)
show_help
;;
--eulercopilot_address)
if [ -n "$2" ]; then
eulercopilot_address="$2"
shift
else
echo -e "${RED}Error: --eulercopilot_address requires a value${NC}" >&2
exit 1
fi
;;
--authhub_address)
if [ -n "$2" ]; then
authhub_address="$2"
shift
else
echo -e "${RED}Error: --authhub_address requires a value${NC}" >&2
exit 1
fi
;;
*)
echo -e "${RED}Unknown option: $1${NC}" >&2
show_help
exit 1
;;
esac
shift
done
}
get_architecture() {
local arch=$(uname -m)
case "$arch" in
x86_64) arch="x86" ;;
aarch64) arch="arm" ;;
*)
echo -e "${RED}Error: Unsupported architecture $arch${NC}" >&2
return 1
;;
esac
echo -e "${GREEN}Detected system architecture: ${arch} (original: $(uname -m))${NC}" >&2
echo "$arch"
}
get_network_ip() {
echo -e "${BLUE}Auto-detecting business network interface IP address...${NC}" >&2
local timeout=20
local start_time=$(date +%s)
local interface=""
local host=""
while [ $(( $(date +%s) - start_time )) -lt $timeout ]; do
interfaces=$(ip -o link show | awk -F': ' '{print $2}' | grep -vE '^lo$|docker|veth|br-|virbr|tun')
for intf in $interfaces; do
if ip link show "$intf" | grep -q 'state UP'; then
ip_addr=$(ip addr show "$intf" | grep -w inet | awk '{print $2}' | cut -d'/' -f1)
if [ -n "$ip_addr" ]; then
interface=$intf
host=$ip_addr
break 2
fi
fi
done
sleep 1
done
if [ -z "$interface" ]; then
echo -e "${RED}Error: No available business network interface found${NC}" >&2
exit 1
fi
echo -e "${GREEN}Using network interface: ${interface}, IP address: ${host}${NC}" >&2
echo "$host"
}
get_address_input() {
if [ -n "$eulercopilot_address" ] && [ -n "$authhub_address" ]; then
echo -e "${GREEN}Using command line parameters:"
echo "openEuler Intelligence address: $eulercopilot_address"
echo "Authhub address: $authhub_address"
return
fi
eulercopilot_address=${EULERCOPILOT_ADDRESS:-"http://127.0.0.1:30080"}
authhub_address=${AUTHHUB_ADDRESS:-"http://127.0.0.1:30081"}
if [ -t 0 ]; then
echo -e "${BLUE}Enter openEuler Intelligence frontend access URL (e.g., http://\$IP:30080):${NC}"
read -p "> " input_euler
[ -n "$input_euler" ] && eulercopilot_address=$input_euler
echo -e "${BLUE}Enter Authhub frontend access URL (e.g., http://\$IP:30081):${NC}"
read -p "> " input_auth
[ -n "$input_auth" ] && authhub_address=$input_auth
fi
echo -e "${GREEN}Using configuration:"
echo "openEuler Intelligence address: $eulercopilot_address"
echo "Authhub address: $authhub_address"
}
get_client_info_auto() {
get_address_input
local temp_file
temp_file=$(mktemp)
python3 "${DEPLOY_DIR}/scripts/9-other-script/get_client_id_and_secret.py" "${eulercopilot_address}" > "$temp_file" 2>&1
if [ $? -ne 0 ]; then
echo -e "${RED}Error: Python script execution failed${NC}"
cat "$temp_file"
rm -f "$temp_file"
return 1
fi
client_id=$(grep "client_id: " "$temp_file" | awk '{print $2}')
client_secret=$(grep "client_secret: " "$temp_file" | awk '{print $2}')
rm -f "$temp_file"
if [ -z "$client_id" ] || [ -z "$client_secret" ]; then
echo -e "${RED}Error: Unable to get valid client credentials${NC}" >&2
return 1
fi
echo -e "${GREEN}==============================${NC}"
echo -e "${GREEN}Client ID: ${client_id}${NC}"
echo -e "${GREEN}Client Secret: ${client_secret}${NC}"
echo -e "${GREEN}==============================${NC}"
}
get_client_info_manual() {
if [ -t 0 ]; then
echo -e "${BLUE}Enter Client ID: domain (endpoint info: Client ID): ${NC}"
read -p "> " input_id
[ -n "$input_id" ] && client_id=$input_id
echo -e "${BLUE}Enter Client Secret: domain (endpoint info: Client Secret):${NC}"
read -p "> " input_secret
[ -n "$input_secret" ] && client_secret=$input_secret
fi
echo -e "${GREEN}Using configuration:"
echo "Client ID: $client_id"
echo "Client Secret: $client_secret"
}
check_directories() {
echo -e "${BLUE}Checking if semantic interface directory exists...${NC}" >&2
local REQUIRED_OWNER="root:root"
if [ -d "${PLUGINS_DIR}" ]; then
echo -e "${GREEN}Directory exists: ${PLUGINS_DIR}${NC}" >&2
local current_owner=$(stat -c "%u:%g" "${PLUGINS_DIR}" 2>/dev/null)
if [ "$current_owner" != "$REQUIRED_OWNER" ]; then
echo -e "${YELLOW}Current directory permissions: ${current_owner}, modifying to ${REQUIRED_OWNER}...${NC}" >&2
if chown root:root "${PLUGINS_DIR}"; then
echo -e "${GREEN}Directory permissions successfully modified to ${REQUIRED_OWNER}${NC}" >&2
else
echo -e "${RED}Error: Unable to modify directory permissions to ${REQUIRED_OWNER}${NC}" >&2
exit 1
fi
else
echo -e "${GREEN}Directory permissions correct (${REQUIRED_OWNER})${NC}" >&2
fi
else
if mkdir -p "${PLUGINS_DIR}"; then
echo -e "${GREEN}Directory created: ${PLUGINS_DIR}${NC}" >&2
chown root:root "${PLUGINS_DIR}"
else
echo -e "${RED}Error: Unable to create directory ${PLUGINS_DIR}${NC}" >&2
exit 1
fi
fi
}
uninstall_eulercopilot() {
echo -e "${YELLOW}Checking if openEuler Intelligence is already deployed...${NC}" >&2
if helm list -n euler-copilot --short | grep -q '^euler-copilot$'; then
echo -e "${GREEN}Found Helm Release: euler-copilot, starting cleanup...${NC}"
if ! helm uninstall euler-copilot -n euler-copilot; then
echo -e "${RED}Error: Failed to delete Helm Release euler-copilot!${NC}" >&2
return 1
fi
else
echo -e "${YELLOW}No Helm Release found to clean: euler-copilot${NC}"
fi
local pvc_name="framework-semantics-claim"
if kubectl get pvc "$pvc_name" -n euler-copilot &>/dev/null; then
echo -e "${GREEN}Found PVC: ${pvc_name}, starting cleanup...${NC}"
if ! kubectl delete pvc "$pvc_name" -n euler-copilot --force --grace-period=0; then
echo -e "${RED}Error: Failed to delete PVC ${pvc_name}!${NC}" >&2
return 1
fi
else
echo -e "${YELLOW}No PVC found to clean: ${pvc_name}${NC}"
fi
local secret_name="euler-copilot-system"
if kubectl get secret "$secret_name" -n euler-copilot &>/dev/null; then
echo -e "${GREEN}Found Secret: ${secret_name}, starting cleanup...${NC}"
if ! kubectl delete secret "$secret_name" -n euler-copilot; then
echo -e "${RED}Error: Failed to delete Secret ${secret_name}!${NC}" >&2
return 1
fi
else
echo -e "${YELLOW}No Secret found to clean: ${secret_name}${NC}"
fi
echo -e "${GREEN}Resource cleanup completed${NC}"
}
modify_yaml() {
local host=$1
local preserve_models=$2
echo -e "${BLUE}Starting YAML configuration file modification...${NC}" >&2
local set_args=()
set_args+=(
"--set" "login.client.id=${client_id}"
"--set" "login.client.secret=${client_secret}"
"--set" "domain.euler_copilot=${eulercopilot_address}"
"--set" "domain.authhub=${authhub_address}"
)
if [[ "$preserve_models" != [Yy]* ]]; then
set_args+=(
"--set" "models.answer.endpoint=http://$host:11434/v1"
"--set" "models.answer.key=sk-123456"
"--set" "models.answer.name=deepseek-llm-7b-chat:latest"
"--set" "models.functionCall.backend=ollama"
"--set" "models.functionCall.endpoint=http://$host:11434"
"--set" "models.embedding.type=openai"
"--set" "models.embedding.endpoint=http://$host:11434/v1"
"--set" "models.embedding.key=sk-123456"
"--set" "models.embedding.name=bge-m3:latest"
)
fi
python3 "${DEPLOY_DIR}/scripts/9-other-script/modify_eulercopilot_yaml.py" \
"${DEPLOY_DIR}/chart/euler_copilot/values.yaml" \
"${DEPLOY_DIR}/chart/euler_copilot/values.yaml" \
"${set_args[@]}" || {
echo -e "${RED}Error: YAML file modification failed${NC}" >&2
exit 1
}
echo -e "${GREEN}YAML file modified successfully!${NC}" >&2
}
enter_chart_directory() {
echo -e "${BLUE}Entering Chart directory...${NC}" >&2
cd "${DEPLOY_DIR}/chart/" || {
echo -e "${RED}Error: Unable to enter Chart directory ${DEPLOY_DIR}/chart/${NC}" >&2
exit 1
}
}
pre_install_checks() {
command -v kubectl >/dev/null 2>&1 || error_exit "kubectl not installed"
command -v helm >/dev/null 2>&1 || error_exit "helm not installed"
kubectl cluster-info >/dev/null 2>&1 || error_exit "Unable to connect to Kubernetes cluster"
kubectl get storageclasses >/dev/null 2>&1 || error_exit "Unable to get storage class information"
}
execute_helm_install() {
local arch=$1
echo -e "${BLUE}Starting openEuler Intelligence deployment (architecture: $arch)...${NC}" >&2
enter_chart_directory
helm upgrade --install $NAMESPACE -n $NAMESPACE ./euler_copilot --set globals.arch=$arch --create-namespace || {
echo -e "${RED}Helm installation of openEuler Intelligence failed!${NC}" >&2
exit 1
}
echo -e "${GREEN}Helm installation of openEuler Intelligence successful!${NC}" >&2
}
check_pods_status() {
echo -e "${BLUE}==> Waiting for initialization (30 seconds)...${NC}" >&2
sleep 30
local timeout=300
local start_time=$(date +%s)
echo -e "${BLUE}Starting pod status monitoring (total timeout 300 seconds)...${NC}" >&2
while true; do
local current_time=$(date +%s)
local elapsed=$((current_time - start_time))
if [ $elapsed -gt $timeout ]; then
echo -e "${YELLOW}Warning: Deployment timeout! Please check the following resources:${NC}" >&2
kubectl get pods -n $NAMESPACE -o wide
echo -e "\n${YELLOW}Suggested checks:${NC}"
echo "1. Check logs of unready pods: kubectl logs -n $NAMESPACE <pod-name>"
echo "2. Check PVC status: kubectl get pvc -n $NAMESPACE"
echo "3. Check Service status: kubectl get svc -n $NAMESPACE"
return 1
fi
local not_running=$(kubectl get pods -n $NAMESPACE -o jsonpath='{range .items[*]}{.metadata.name} {.status.phase} {.status.conditions[?(@.type=="Ready")].status}{"\n"}{end}' \
| awk '$2 != "Running" || $3 != "True" {print $1 " " $2}')
if [ -z "$not_running" ]; then
echo -e "${GREEN}All pods are running normally!${NC}" >&2
kubectl get pods -n $NAMESPACE -o wide
return 0
else
echo "Waiting for pods to be ready (waited ${elapsed} seconds)..."
echo "Current unready pods:"
echo "$not_running" | awk '{print " - " $1 " (" $2 ")"}'
sleep 10
fi
done
}
main() {
parse_arguments "$@"
pre_install_checks
local arch host
arch=$(get_architecture) || exit 1
host=$(get_network_ip) || exit 1
uninstall_eulercopilot
if ! get_client_info_auto; then
get_client_info_manual
fi
check_directories
if [ -t 0 ]; then
echo -e "${YELLOW}Keep existing model configuration?${NC}"
echo -e " ${BLUE}Y) Keep existing configuration${NC}"
echo -e " ${BLUE}n) Use default configuration${NC}"
read -p "Please choose (Y/N): " input_preserve
while true; do
case "${input_preserve:-Y}" in
[YyNn]) preserve_models=${input_preserve:-Y}; break ;;
*) echo -e "${RED}Invalid input, please choose Y or n${NC}" ;;
esac
done
else
preserve_models="N"
fi
echo -e "${BLUE}Starting YAML configuration modification...${NC}"
modify_yaml "$host" "$preserve_models"
echo -e "${BLUE}Starting Helm installation...${NC}"
execute_helm_install "$arch"
if check_pods_status; then
echo -e "${GREEN}All components are ready!${NC}"
show_success_message "$host" "$arch"
else
echo -e "${YELLOW}Some components are not ready, recommended to investigate!${NC}"
fi
}
show_success_message() {
local host=$1
local arch=$2
echo -e "\n${GREEN}==================================================${NC}"
echo -e "${GREEN} openEuler Intelligence Deployment Completed! ${NC}"
echo -e "${GREEN}==================================================${NC}"
echo -e "${YELLOW}Access Information:${NC}"
echo -e "openEuler Intelligence UI: ${eulercopilot_address}"
echo -e "AuthHub Admin UI: ${authhub_address}"
echo -e "\n${YELLOW}System Information:${NC}"
echo -e "Internal IP: ${host}"
echo -e "System Arch: $(uname -m) (identified as: ${arch})"
echo -e "Plugins Dir: ${PLUGINS_DIR}"
echo -e "Chart Dir: ${DEPLOY_DIR}/chart/"
echo -e "${BLUE}Operation Guide:${NC}"
echo -e "1. Check cluster status: kubectl get pod -n $NAMESPACE"
echo -e "2. View real-time logs: kubectl logs -f <POD_NAME> -n $NAMESPACE "
echo -e " Example: kubectl logs -f framework-deploy-5577c87b6-h82g8 -n euler-copilot"
echo -e "3. Check POD status: kubectl get pods -n $NAMESPACE"
}
main "$@"