반응형
개요
ssh를 이용한 VMware ESXi VM 생성 및 삭제 Script를 AWX를 이용하여 실행하고 결과 값을 Slack Webhook을 통해 전송 할 수 있다.
- AWX : docker image ansible/awx:17.1.0
- inventory에 vm 생성 관련 변수 값을 정의해놓고 참조하여 local script로 실행.
- VMware ESXi vm 생성 및 삭제 스크립트 참조 :
- Slack Webhook : VMware ESXi VM 스크립트를 수정하여 전송
- AWX 로그를 이용한 slack webhook 전송 참조 : ansible | AWX Playbook Task 실패 시 알림 설정
설정
awx_task Docker Container 수정
- awx 관련 docker container 확인
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9b5665c67d98 ansible/awx:17.1.0 "/usr/bin/tini -- /u…" 5 weeks ago Up 3 days 8052/tcp awx_task
f708e1f818fa ansible/awx:17.1.0 "/usr/bin/tini -- /b…" 5 weeks ago Up 3 days 0.0.0.0:80->8052/tcp, :::80->8052/tcp awx_web
7fb8ab51a84b redis "docker-entrypoint.s…" 5 weeks ago Up 3 days 6379/tcp awx_redis
1a57eb1638a2 postgres:12 "docker-entrypoint.s…" 5 weeks ago Up 3 days 5432/tcp awx_postgres
- AWX 설치 참조 : https://ploz.tistory.com/entry/3-AWX-%EC%84%A4%EC%B9%98
- awx_task container에서 실제 job template이 실행 되며 실행하고자 하는 local script도 awx_task에서 실행된다.
- [VMware ESXi] ssh를 통한 VM 생성, 삭제 하기(1) 에서 python 2.7을 사용한 반면 awx_task는 python 3.6 을 사용한다.
- awx_task에 직접 접속하여 pip를 통해 scp와 cryptography를 설치한다.
- awx_task 접속
> docker exec -it awx_task bash
- pip 설치
> pip3 install scp
# cryptography는 2.3이 기본 설치 되어 있다.
# 3.1.1 에서도 이상없이 돌아가는것을 확인하였으므로 설치해 주어도 상관없다.
> pip3 install cryptography==3.1.1
VMware ESXi VM 스크립트 수정
- python 2.7 -> python 3.6 으로 변경 됨에 따라 변경 되는 print 문법을 수정하여 준다.
# 03.esxi-vm-create2 파일 수정
#!/usr/bin/python -> /usr/bin/python3
# print 문 수정
# 아래 예로 모두 수정
print 'ERROR: Missing required option --name'
->
print('ERROR: Missing required option --name')
...
- esxi_vm_functions.py 에 setup_config 함수내 ESXi ssh PORT 추가
# esxi_vm_functions.py 파일에 PORT 추가
def setup_config():
#
# System wide defaults
#
ConfigData = dict(
...
# ESXi host/IP, root login & password
HOST="172.16.10.48",
PORT="22",
USER="root",
PASSWORD="***********",
...
- 03.esxi-vm-create2, 02.esxi-vm-destory 파일내에 PORT 변수 추가
# PORT = ConfigData['PORT']
ConfigData = setup_config()
...
HOST = ConfigData['HOST']
USER = ConfigData['USER']
PORT = ConfigData['PORT']
PASSWORD = ConfigData['PASSWORD']
CPU = ConfigData['CPU']
MEM = ConfigData['MEM']
...
- sftp 사용을 위하여 03.esxi-vm-create2 파일 paramiko 설정 수정
# paramiko ssh 설정
...
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(HOST, PORT, USER, PASSWORD)
...
# 맨 마지막줄 추가
ssh.close()
# paramiko sftp 설정
if not isDryRun and not CheckHasErrors:
...
# Create NAME.vmx
if isVerbose:
print("Create " + NAME + ".vmx file")
(stdin, stdout, stderr) = ssh.exec_command("mkdir " + FullPath )
type(stdin)
fp = open('/tmp/'+NAME+'.vmx', 'a')
for line in VMX:
fp.write(line)
fp.write('\n')
fp.close()
sftp = ssh.open_sftp()
sftp.put('/tmp/'+NAME+'.vmx',MyVM+'.vmx')
sftp.close()
...
- 03.esxi-vm-create2, 02.esxi-vm-destory 파일에 Slack Webhook 부분 추가
# import json
...
import warnings
import json
import subprocess
from esxi_vm_functions import *
...
# 03.esxi-vm-create2 파일에 LOG 쌓는 부분을 slack webhook payload로 수정
...
# Print Summary
#
# The output log string
LogOutput += '"ESXi_Host":"' + HOST + '",'
LogOutput += '"VM_Name":"' + NAME + '",'
LogOutput += '"VM_CPU":"' + str(CPU) + ' Core",'
LogOutput += '"VM_Mem":"' + str(MEM) + ' GB",'
LogOutput += '"VM_DISK_Volume":"' + str(HDISK) + ' GB",'
LogOutput += '"VM_Disk_Provisioning":"' + DISKFORMAT + '",'
LogOutput += '"VM_iSCSI_Controller":"' + VIRTDEV + '",'
LogOutput += '"VM_Storage_Pool":"' + STORE + '",'
#LogOutput += '"VM_Storage_Pool_Path":"' + DSPATH + '",'
LogOutput += '"VM_NIC_Driver":"' + NETDRIVER + '",'
LogOutput += '"VM_Network":"' + NET + '",'
LogOutput += '"VM_ISO":"' + ISOarg + '",'
#LogOutput += '"ISO used":"' + ISO + '",'
LogOutput += '"VM_Guest OS":"' + GUESTOS + '",'
LogOutput += '"VM_MAC":"' + MACarg + '",'
LogOutput += '"VM_MAC Used":"' + GeneratedMAC + '",'
#LogOutput += '"Dry Run":"' + str(isDryRun) + '",'
#LogOutput += '"Verbose":"' + str(isVerbose) + '",'
if ErrorMessages != "":
slack_color = 'danger'
slack_title = 'Failed :: The "' + os.path.basename(__file__) + '" Script'
LogOutput += '"Error Message":"' + ErrorMessages + '",'
else:
slack_color = 'good'
slack_title = 'OK :: The "' + os.path.basename(__file__) + '" Script'
LogOutput += '"Result":"' + Result + '",'
LogOutput += '"Completion Time":"' + str(theCurrDateTime()) + '"'
LogOutput += '}'
## slack var
slack_channel = 'test-channel'
slack_user = 'script for ' + os.path.basename(__file__)
slack_emoji = ':slack:'
slack_url = 'https://hooks.slack.com/services/***************'
## slack payload data append
def append_payload(title,value,short,payload):
append_data = {'title': title, 'value': value, 'short': short}
payload['attachments'][0]['fields'].append(append_data)
return(payload)
try:
log_j = json.loads(LogOutput)
payload = {}
payload['channel'] = slack_channel
payload['username'] = slack_user
payload['icon_emoji'] = slack_emoji
payload['attachments'] = [{}]
payload['attachments'][0]['fallback'] = slack_title
payload['attachments'][0]['pretext'] = slack_title
payload['attachments'][0]['title'] = slack_title
payload['attachments'][0]['color'] = slack_color
payload['attachments'][0]['fields']=[{}]
payload['attachments'][0]['fields'][0]['title']='Script Name'
payload['attachments'][0]['fields'][0]['value']=os.path.basename(__file__)
payload['attachments'][0]['fields'][0]['short']='true'
for key, value in log_j.items():
payload=append_payload(key,value,'true',payload)
payload_a=json.dumps(payload)
slack_send = "curl -X POST --data-urlencode 'payload={a}' {b}".format(a=payload_a,b=slack_url)
subprocess.check_output(slack_send, shell=True, universal_newlines=True)
except:
print("Error writing to log file: " + LOG)
...
# 02.esxi-vm-destroy Log 쌓는 부분을 slack webhook payload로 수정
...
# Print Summary
#
# The output log string
LogOutput += '"ESXi_Host":"' + HOST + '",'
LogOutput += '"VM_Name":"' + NAME + '",'
LogOutput += '"VM_Storage_Pool_Path":"' + DSPATH + '",'
LogOutput += '"Verbose":"' + str(isVerbose) + '",'
if ErrorMessages != "":
slack_color = 'danger'
slack_title = 'Failed :: The "' + os.path.basename(__file__) + '" Script'
LogOutput += '"Error Message":"' + ErrorMessages + '",'
else:
slack_color = 'good'
slack_title = 'OK :: The "' + os.path.basename(__file__) + '" Script'
LogOutput += '"Result":"' + Result + '",'
LogOutput += '"Completion Time":"' + str(theCurrDateTime()) + '"'
LogOutput += '}'
## slack var
slack_channel = 'test-channel'
slack_user = 'script for ' + os.path.basename(__file__)
slack_emoji = ':slack:'
slack_url = 'https://hooks.slack.com/services/********************'
## slack payload data append
def append_payload(title,value,short,payload):
append_data = {'title': title, 'value': value, 'short': short}
payload['attachments'][0]['fields'].append(append_data)
return(payload)
try:
log_j = json.loads(LogOutput)
payload = {}
payload['channel'] = slack_channel
payload['username'] = slack_user
payload['icon_emoji'] = slack_emoji
payload['attachments'] = [{}]
payload['attachments'][0]['fallback'] = slack_title
payload['attachments'][0]['pretext'] = slack_title
payload['attachments'][0]['title'] = slack_title
payload['attachments'][0]['color'] = slack_color
payload['attachments'][0]['fields']=[{}]
payload['attachments'][0]['fields'][0]['title']='Script Name'
payload['attachments'][0]['fields'][0]['value']=os.path.basename(__file__)
payload['attachments'][0]['fields'][0]['short']='true'
for key, value in log_j.items():
payload=append_payload(key,value,'true',payload)
payload_a=json.dumps(payload)
slack_send = "curl -X POST --data-urlencode 'payload={a}' {b}".format(a=payload_a,b=slack_url)
result = subprocess.check_output(slack_send, shell=True, universal_newlines=True)
print(result)
except:
print("Error writing to log file: " + LOG)
...
- 최종 수정 스크립트 파일
awx_task container에 ESXi VM 스크립트 넣기
- awx_task 는 /opt/awx/projects <-> /var/lib/awx/projects 의 볼룸이 마운트 되어 있다.
> docker inspect awx_task
...
"Mounts": [
...
{
"Type": "bind",
"Source": "/opt/awx/projects",
"Destination": "/var/lib/awx/projects",
"Mode": "rw",
"RW": true,
"Propagation": "rprivate"
},
...
- 03.esxi-vm-create2, 02.esxi-vm-destory 파일은 /opt/awx/projects에 복사
> cp -arf /opt/esxi-vm-create/03.esxi-vm-create2 /opt/awx/projects/
> cp -arf /opt/esxi-vm-create/02.esxi-vm-destory /opt/awx/projects/
> cp -arf /opt/esxi-vm-create/esxi_VM_functions.py /opt/awx/projects/
- esxi_vm_functions.py python sys path 경로에 추가
> docker exec -it awx_task bash
> mv /opt/awx/projects/esxi_vm_functions.py /usr/lib/python3.6/site-packages/
inventory 작성
- inventory host 변수에 VM 생성에 관한 변수값을 정의한다.
> 01.test_win.ini
[test_win]
172.16.10.131
[test_win:vars]
# vm 생성 관련
spec_disk=100
spec_cpu=8
spec_memory=4
host_alias=test_win2
iso_image=20220524_auto_w2012x64_ko_clean.ISO
network_alias=ME2ON_Private
guest_os=windows8srv-64
disk_provisioning=zeroedthick
disk_controller=lsisas1068
nic_driver=e1000e
# vm을 생성하고자 하는 esxi host
esxi_server=172.16.10.48
# windows image 백업을 위한 변수
backup_drive=c:
backup_target_dir="\\\\172.16.10.32\SE_Backup\test_win"
backup_target_host_user=admin
backup_target_host_password=*******
ansible_connection=winrm
ansible_winrm_server_cert_validation=ignore
#ansible_user=administrator
#ansible_password="**********"
playbook 작성
- local_action을 이용하여 local script 를 정의 하고 스크립트와 함께 사용 할 파라미터를 정의 한다.
- vm 생성
> 08.script_create_esxi_vm.yml
---
- hosts: all
gather_facts: no
ignore_unreachable: yes
vars:
esxi_vars: "-H {{esxi_server}} -n {{ host_alias}} -c {{ spec_cpu}} -m {{ spec_memory}} -v {{ spec_disk}} --iso {{ iso_image}} -N {{ network_alias}} -g {{ guest_os}} -f {{ disk_provisioning }} -s {{ disk_controller }} -a {{ nic_driver }}"
tasks:
- name: create esxi vm
local_action : script /var/lib/awx/projects/03.esxi-vm-create2 {{ esxi_vars }}
- vm 삭제
> 09.script_destory_esxi_vm.yml
---
- hosts: all
gather_facts: no
ignore_unreachable: yes
vars:
esxi_vars: "-H {{esxi_server}} -n {{host_alias}}"
tasks:
- name: destory esxi vm
local_action : script /var/lib/awx/projects/02.esxi-vm-destroy {{ esxi_vars }}
- git을 이용하여 gitlab에 push
> git add .
> git commit -a
> git status
> git push origin push
- awx와 gitlab 연동 참조 : https://ploz.tistory.com/entry/32-AWX-Project-source-control
AWX Job Template 작성 및 실행
- vm 생성
- vm 삭제
- Job template 실행 후 slack 메세지 확인
반응형
'Automation Tools > Ansible' 카테고리의 다른 글
[ansible AWX] 지나간 Jobs 삭제하기 (0) | 2023.07.10 |
---|---|
ansible | [playbook] AWX에 windows data backup 스케줄 등록하기(win_copy+win_find+win_file) (0) | 2022.07.06 |
ansible | inventory 내 다른 host 변수 참조 (0) | 2022.06.27 |
ansible | AWX Playbook Task 실패(or 성공) 시 알림 설정 (0) | 2022.06.22 |
ansible | [AWX] JOB Template 의 Schedule과 Notification (0) | 2022.06.20 |