1+ #! /bin/bash
2+
3+ # VHBA 자동 복원 스크립트
4+ # /etc/vhba 경로의 dumpxml 파일들을 사용하여 vHBA 복원
5+ # WWN 기반으로 vHBA 이름을 고정
6+
7+ VHBA_DIR=" /etc/vhba"
8+ LOG_FILE=" /var/log/cloudstack/vhba-restore.log"
9+ MAPPING_FILE=" /etc/vhba/wwn_mapping.conf"
10+
11+ # 로그 함수
12+ log_message () {
13+ echo " $( date ' +%Y-%m-%d %H:%M:%S' ) - $1 " | tee -a " $LOG_FILE "
14+ }
15+
16+ # WWN 매핑 파일 생성/업데이트
17+ update_wwn_mapping () {
18+ log_message " WWN 매핑 업데이트 시작"
19+
20+ # 매핑 파일 초기화
21+ > " $MAPPING_FILE "
22+
23+ # 현재 활성 vHBA들의 WWN 정보 수집
24+ for vhba in $( virsh nodedev-list | grep " ^scsi_host" ) ; do
25+ wwnn=$( virsh nodedev-dumpxml " $vhba " 2> /dev/null | grep " <wwnn>" | sed ' s/.*<wwnn>\(.*\)<\/wwnn>.*/\1/' )
26+ wwpn=$( virsh nodedev-dumpxml " $vhba " 2> /dev/null | grep " <wwpn>" | sed ' s/.*<wwpn>\(.*\)<\/wwpn>.*/\1/' )
27+
28+ if [ -n " $wwnn " ] && [ -n " $wwpn " ]; then
29+ echo " ${wwnn} :${wwpn} =$vhba " >> " $MAPPING_FILE "
30+ log_message " WWN 매핑 추가: ${wwnn} :${wwpn} -> $vhba "
31+ fi
32+ done
33+
34+ log_message " WWN 매핑 업데이트 완료"
35+ }
36+
37+ # WWN으로 vHBA 이름 찾기
38+ find_vhba_by_wwn () {
39+ local wwnn=" $1 "
40+ local wwpn=" $2 "
41+ local wwn_key=" ${wwnn} :${wwpn} "
42+
43+ if [ -f " $MAPPING_FILE " ]; then
44+ grep " ^$wwn_key =" " $MAPPING_FILE " | cut -d' =' -f2
45+ fi
46+ }
47+
48+ log_message " VHBA 복원 시작"
49+
50+ # /etc/vhba 디렉토리 존재 확인
51+ if [ ! -d " $VHBA_DIR " ]; then
52+ log_message " /etc/vhba 디렉토리가 존재하지 않습니다: $VHBA_DIR "
53+ exit 0
54+ fi
55+
56+ # libvirtd 서비스가 완전히 시작될 때까지 대기
57+ log_message " libvirtd 서비스 대기 중..."
58+ for i in {1..30}; do
59+ if systemctl is-active --quiet libvirtd; then
60+ log_message " libvirtd 서비스가 활성화되었습니다."
61+ break
62+ fi
63+ log_message " libvirtd 서비스 대기 중... ($i /30)"
64+ sleep 2
65+ done
66+
67+ # 추가 대기 시간 (디바이스 스캔 완료 대기)
68+ log_message " 디바이스 스캔 완료 대기 중..."
69+ sleep 5
70+
71+ # 기존 vHBA들의 WWN 매핑 업데이트
72+ update_wwn_mapping
73+
74+ # /etc/vhba 경로의 XML 파일들로 vHBA 복원
75+ restore_count=0
76+ failed_count=0
77+
78+ for xml_file in " $VHBA_DIR " /* .xml; do
79+ if [ -f " $xml_file " ]; then
80+ filename=$( basename " $xml_file " )
81+ device_name=$( basename " $xml_file " .xml)
82+
83+ log_message " vHBA 복원 시도: $filename "
84+
85+ # XML 파일 유효성 검사
86+ if ! grep -q " <name>" " $xml_file " || ! grep -q " <path>" " $xml_file " ; then
87+ log_message " XML 파일이 불완전함 (name 또는 path 태그 누락): $filename "
88+ failed_count=$(( failed_count + 1 ))
89+ continue
90+ fi
91+
92+ # 백업된 vHBA의 WWN 추출
93+ backup_wwnn=$( grep " <wwnn>" " $xml_file " | sed ' s/.*<wwnn>\(.*\)<\/wwnn>.*/\1/' )
94+ backup_wwpn=$( grep " <wwpn>" " $xml_file " | sed ' s/.*<wwpn>\(.*\)<\/wwpn>.*/\1/' )
95+
96+ if [ -n " $backup_wwnn " ] && [ -n " $backup_wwpn " ]; then
97+ log_message " vHBA WWN: $backup_wwnn :$backup_wwpn "
98+
99+ # WWN으로 기존 vHBA 찾기
100+ existing_vhba=$( find_vhba_by_wwn " $backup_wwnn " " $backup_wwpn " )
101+
102+ if [ -n " $existing_vhba " ]; then
103+ log_message " 동일한 WWN을 가진 vHBA 발견: $existing_vhba "
104+
105+ # 기존 vHBA가 있으면 삭제
106+ log_message " 기존 vHBA 삭제 중: $existing_vhba "
107+ virsh nodedev-destroy " $existing_vhba " 2> /dev/null
108+ sleep 1
109+ fi
110+ fi
111+
112+ # 부모 디바이스 확인
113+ parent_device=$( grep " <parent>" " $xml_file " | sed ' s/.*<parent>\(.*\)<\/parent>.*/\1/' )
114+ if [ -n " $parent_device " ]; then
115+ log_message " 부모 디바이스 확인: $parent_device "
116+ if ! virsh nodedev-list | grep -q " ^$parent_device $" ; then
117+ log_message " 부모 디바이스가 존재하지 않음: $parent_device "
118+ failed_count=$(( failed_count + 1 ))
119+ continue
120+ fi
121+ fi
122+
123+ # virsh nodedev-create로 vHBA 디바이스 생성
124+ result=$( virsh nodedev-create " $xml_file " 2>&1 )
125+
126+ if [ $? -eq 0 ]; then
127+ log_message " 복원 성공: $filename "
128+ restore_count=$(( restore_count + 1 ))
129+
130+ # 생성된 vHBA의 실제 이름 추출
131+ created_vhba=$( echo " $result " | grep " created" | sed ' s/.*created from.*//' | tr -d ' ' )
132+ if [ -n " $created_vhba " ]; then
133+ log_message " 생성된 vHBA: $created_vhba "
134+
135+ # 새로운 vHBA의 WWN 매핑 업데이트
136+ new_wwnn=$( virsh nodedev-dumpxml " $created_vhba " 2> /dev/null | grep " <wwnn>" | sed ' s/.*<wwnn>\(.*\)<\/wwnn>.*/\1/' )
137+ new_wwpn=$( virsh nodedev-dumpxml " $created_vhba " 2> /dev/null | grep " <wwpn>" | sed ' s/.*<wwpn>\(.*\)<\/wwpn>.*/\1/' )
138+
139+ if [ -n " $new_wwnn " ] && [ -n " $new_wwpn " ]; then
140+ # 기존 매핑 제거
141+ sed -i " /^${new_wwnn} :${new_wwpn} =/d" " $MAPPING_FILE " 2> /dev/null
142+ # 새 매핑 추가
143+ echo " ${new_wwnn} :${new_wwpn} =$created_vhba " >> " $MAPPING_FILE "
144+ log_message " WWN 매핑 업데이트: ${new_wwnn} :${new_wwpn} -> $created_vhba "
145+ fi
146+ fi
147+ else
148+ log_message " 복원 실패: $filename - $result "
149+ failed_count=$(( failed_count + 1 ))
150+ fi
151+ fi
152+ done
153+
154+ # 복원 후 상태 확인
155+ final_vhbas=$( virsh nodedev-list | grep " ^scsi_host" 2> /dev/null | wc -l)
156+ log_message " 복원 후 활성 vHBA 디바이스 수: $final_vhbas "
157+
158+ # 복원 결과 요약
159+ log_message " VHBA 복원 완료: 성공 $restore_count 개, 실패 $failed_count 개"
160+ log_message " VHBA 복원 프로세스 완료"
0 commit comments