7 Commits
v0.3 ... main

9 changed files with 463 additions and 28 deletions

View File

@@ -6,24 +6,26 @@
# Note that environment variables can be set in several places # Note that environment variables can be set in several places
# See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence # See https://docs.gitlab.com/ee/ci/variables/#cicd-variable-precedence
stages: stages:
- build - build
- test - build-sonar
- deploy - test
- review - deploy
- dast - review
- staging - dast
- canary - staging
- production - canary
- incremental rollout 10% - production
- incremental rollout 25% - incremental rollout 10%
- incremental rollout 50% - incremental rollout 25%
- incremental rollout 100% - incremental rollout 50%
- performance - incremental rollout 100%
- cleanup - performance
- cleanup
sast: sast:
stage: test stage: test
include: include:
- template: Auto-DevOps.gitlab-ci.yml - template: Auto-DevOps.gitlab-ci.yml
- local: .gitlab/ci/*.gitlab-ci.yml
python_tests: python_tests:
stage: test stage: test

View File

@@ -0,0 +1,26 @@
image:
name: sonarsource/sonar-scanner-cli:11
entrypoint: [""]
variables:
SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
build-sonar:
stage: build-sonar
cache:
policy: pull-push
key: "sonar-cache-$CI_COMMIT_REF_SLUG"
paths:
- "${SONAR_USER_HOME}/cache"
- sonar-scanner/
script:
- sonar-scanner -Dsonar.host.url="${SONAR_HOST_URL}"
allow_failure: true
rules:
- if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- if: $CI_COMMIT_BRANCH == 'master'
- if: $CI_COMMIT_BRANCH == 'main'
- if: $CI_COMMIT_BRANCH == 'develop'

93
AUTO_NIC_SETUP_README.md Normal file
View File

@@ -0,0 +1,93 @@
# 자동 NIC 설정 시스템
이 시스템은 새로운 네트워크 인터페이스(NIC)가 감지되면 자동으로 DHCP를 통해 IP를 할당받고, Policy-Based Routing(PBR) 규칙을 업데이트하는 자동화 시스템입니다.
## 구성 요소
### 1. udev 규칙
- **파일**: `/etc/udev/rules.d/99-auto-nic-setup.rules`
- **기능**: 새로운 네트워크 인터페이스가 추가되거나 활성화될 때 자동으로 스크립트 실행
- **지원 인터페이스**: ens*, eth*, enp*
### 2. 자동 설정 스크립트
- **파일**: `/usr/local/bin/auto-nic-setup.sh`
- **기능**:
- 인터페이스 상태 확인
- DHCP를 통한 IP 할당
- Policy Routing 규칙 자동 업데이트
- 상세한 로깅
### 3. NetworkManager Dispatcher
- **파일**: `/etc/NetworkManager/dispatcher.d/99-policy-routing`
- **기능**: NetworkManager에서 인터페이스가 up 상태가 될 때 추가적으로 스크립트 실행
### 4. 로그 파일
- **파일**: `/var/log/auto-nic-setup.log`
- **기능**: 모든 자동화 작업의 상세 로그 기록
## 동작 방식
1. **NIC 감지**: 새로운 NIC가 시스템에 추가되면 udev 규칙이 트리거됨
2. **자동 활성화**: 인터페이스가 DOWN 상태면 자동으로 UP 상태로 변경
3. **DHCP 설정**: dhclient를 사용하여 자동으로 IP 주소 할당 시도
4. **PBR 업데이트**: IP 할당이 성공하면 policy_routing.py의 apply_changes 실행
5. **로깅**: 모든 과정이 `/var/log/auto-nic-setup.log`에 기록됨
## 현재 설정된 인터페이스
```bash
# 현재 PBR 규칙 확인
ip rule show
# 현재 라우팅 테이블 확인
ip route show table nic1
ip route show table nic2
ip route show table nic3
# 로그 확인
sudo tail -f /var/log/auto-nic-setup.log
```
## 수동 테스트
새로운 NIC가 추가되었을 때 수동으로 테스트하려면:
```bash
# 수동으로 스크립트 실행
sudo /usr/local/bin/auto-nic-setup.sh ens9
# 또는 udev 이벤트 시뮬레이션
sudo udevadm trigger --subsystem-match=net --action=add
```
## 문제 해결
### 로그 확인
```bash
sudo tail -n 50 /var/log/auto-nic-setup.log
```
### udev 규칙 다시 로드
```bash
sudo udevadm control --reload-rules
```
### 수동으로 PBR 규칙 적용
```bash
cd /home/pieroot/policy-routing
sudo python3 policy_routing.py apply_changes
```
## 주의사항
- 이 시스템은 물리적 네트워크 인터페이스(ens*, eth*, enp*)에만 적용됩니다
- 가상 인터페이스(docker*, veth*, br-*)는 자동으로 제외됩니다
- DHCP 서버가 있는 네트워크에서만 정상 동작합니다
- 시스템 부팅 시에도 자동으로 적용됩니다
## 설치된 파일 목록
- `/usr/local/bin/auto-nic-setup.sh` - 메인 자동화 스크립트
- `/etc/udev/rules.d/99-auto-nic-setup.rules` - udev 규칙
- `/etc/NetworkManager/dispatcher.d/99-policy-routing` - NetworkManager dispatcher
- `/var/log/auto-nic-setup.log` - 로그 파일

View File

@@ -18,9 +18,9 @@ NIC 의 ip 설정이 미리 되어 있어야 합니다.
스크립트는 아래 명령어로 다운로드 받을 수 있습니다 스크립트는 아래 명령어로 다운로드 받을 수 있습니다
```bash ```bash
wget -O policy_routing.py https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py wget -O policy_routing.py https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py
# or # or
curl -o policy_routing.py https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py curl -o policy_routing.py https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py
``` ```
다운로드한 스크립트를 setup 옵션으로 시스템 데몬으로 설치할 수 있습니다 다운로드한 스크립트를 setup 옵션으로 시스템 데몬으로 설치할 수 있습니다
@@ -33,4 +33,62 @@ ip rule 을 확인하여 정책 기반 라우팅이 설정되었는지 확인할
```bash ```bash
ip rule ls ip rule ls
``` ```
## packer 를 사용하여 이미지 배포
openstack 에 자동으로 PBR 시스템을 구성하는 packer template 을 제공합니다.
### Packer 설치
https://developer.hashicorp.com/packer/tutorials/docker-get-started/get-started-install-cli
### Packer OpenStack plugin 설치
openstack 에서 사용할 수 있게 하려면 Packer OpenStack 플러그인을 설치해야 합니다. 아래 명령어를 사용하여 설치할 수 있습니다.
```bash
packer plugins install github.com/hashicorp/openstack
```
### Packer OpenStack 템플릿 설정
packer 를 사용하기 전에 openrc를 설정해야합니다
```bash
vi admin-openrc
```
설정 파일 내용은 아래 내용들을 채워야합니다.
```bash
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_TENANT_NAME=$OS_PROJECT_NAME
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASSWORD
export OS_AUTH_URL=http://OPENSTACK_KEYSTONE_HOST/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export OS_SOURCE_IMAGE_ID=원본_이미지_ID
export OS_NETWORK_NAME=이미지_빌드에_사용할_네트워크_ID
export OS_FLOATING_IP_POOL=플로팅_IP_풀_이름
```
위 환경 변수들은 실제 환경에 맞게 수정해야 합니다. 예를 들어, `ADMIN_PASSWORD`는 OpenStack 관리자의 비밀번호로 설정해야 하며, `OPENSTACK_KEYSTONE_HOST`는 OpenStack Keystone 서비스의 호스트 주소로 설정해야 합니다.
```bash
source admin-openrc
```
packer 를 실행할 수 있는지 확인합니다.
```bash
packer validate packer-openstack-ubuntu.json
```
### Packer OpenStack 템플릿 실행
```bash
packer build packer-openstack-ubuntu.json
```

11
admin-openrc.sample Normal file
View File

@@ -0,0 +1,11 @@
export OS_USER_DOMAIN_NAME=Default
export OS_PROJECT_NAME=admin
export OS_TENANT_NAME=$OS_PROJECT_NAME
export OS_USERNAME=admin
export OS_PASSWORD=ADMIN_PASSWORD
export OS_AUTH_URL=http://OPENSTACK_KEYSTONE_HOST/v3
export OS_IDENTITY_API_VERSION=3
export OS_IMAGE_API_VERSION=2
export OS_SOURCE_IMAGE_ID=원본_이미지_ID
export OS_NETWORK_NAME=이미지_빌드에_사용할_네트워크_ID
export OS_FLOATING_IP_POOL=플로팅_IP_풀_이름

View File

@@ -9,7 +9,7 @@
"source_image_id": "{{env `OS_SOURCE_IMAGE_ID`}}", "source_image_id": "{{env `OS_SOURCE_IMAGE_ID`}}",
"flavor_name": "cpu.2c_2g", "flavor_name": "cpu.2c_2g",
"network_name": "{{env `OS_NETWORK_NAME`}}", "network_name": "{{env `OS_NETWORK_NAME`}}",
"image_name": "ubuntu 22.04-{{timestamp}} server", "image_name": "ubuntu 24.04 server-{{timestamp}}",
"floating_ip_pool": "{{env `OS_FLOATING_IP_POOL`}}", "floating_ip_pool": "{{env `OS_FLOATING_IP_POOL`}}",
"ssh_username": "ubuntu" "ssh_username": "ubuntu"
}, },
@@ -36,6 +36,7 @@
"use_floating_ip": true, "use_floating_ip": true,
"ssh_timeout": "10m", "ssh_timeout": "10m",
"image_disk_format": "raw", "image_disk_format": "raw",
"image_visibility": "public",
"use_blockstorage_volume": true "use_blockstorage_volume": true
} }
], ],

View File

@@ -2,20 +2,20 @@
write_files: write_files:
- path: /tmp/pbr-script-cloud-init.sh - path: /tmp/pbr-script-cloud-init.sh
permissions: '0755' permissions: "0755"
owner: root:root owner: root:root
content: | content: |
#!/bin/bash #!/bin/bash
# GitLab 스크립트 URL (공개 저장소 또는 접근 가능한 URL) # GitLab 스크립트 URL (공개 저장소 또는 접근 가능한 URL)
# 예시: GitLab Pages, Raw 파일 URL 등 # 예시: GitLab Pages, Raw 파일 URL 등
# private repository인 경우 인증 관련 부분을 추가해야 합니다. (아래 설명) # private repository인 경우 인증 관련 부분을 추가해야 합니다. (아래 설명)
SCRIPT_URL="https://git.dmslab.xyz/dmslab/policy-routing/-/raw/v0.3/policy_routing.py" SCRIPT_URL="https://raw.githubusercontent.com/jung-geun/policy-routing/v0.3/policy_routing.py"
DEST_PATH="/opt/PBR/routing.py" DEST_PATH="/opt/PBR/routing.py"
# 스크립트 저장될 디렉토리 생성 (필요하다면) # 스크립트 저장될 디렉토리 생성 (필요하다면)
mkdir -p $(dirname "${DEST_PATH}") mkdir -p $(dirname "${DEST_PATH}")
echo "Downloading script from ${SCRIPT_URL}..." echo "Downloading script from ${SCRIPT_URL}..."
# wget 또는 curl 사용 # wget 또는 curl 사용
# wget이 일반적으로 더 많이 사용됨 # wget이 일반적으로 더 많이 사용됨
@@ -29,17 +29,17 @@ write_files:
echo "Error: Neither wget nor curl found. Cannot download script." echo "Error: Neither wget nor curl found. Cannot download script."
exit 1 exit 1
fi fi
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "Script downloaded successfully to ${DEST_PATH}. Executing..." echo "Script downloaded successfully to ${DEST_PATH}. Executing..."
chmod +x "${DEST_PATH}" # 실행 권한 부여 chmod +x "${DEST_PATH}" # 실행 권한 부여
"${DEST_PATH}" install # 스크립트 실행 "${DEST_PATH}" setup --force # 스크립트 실행
else else
echo "Error: Failed to download script from ${SCRIPT_URL}." echo "Error: Failed to download script from ${SCRIPT_URL}."
exit 1 exit 1
fi fi
echo "Script execution finished." echo "Script execution finished."
runcmd: runcmd:
- /tmp/pbr-script-cloud-init.sh - /tmp/pbr-script-cloud-init.sh

244
policy_routing.py Normal file → Executable file
View File

@@ -4,6 +4,8 @@ Ubuntu 22.04 Multi-NIC Policy Based Routing Setup Script
Python Implementation Python Implementation
""" """
__version__ = "0.3" # 현재 스크립트 버전
import subprocess import subprocess
import logging import logging
import os import os
@@ -13,6 +15,7 @@ import re
import ipaddress import ipaddress
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
import requests # requests 라이브러리 추가
class PolicyBasedRoutingManager: class PolicyBasedRoutingManager:
@@ -31,6 +34,7 @@ class PolicyBasedRoutingManager:
# 네트워크 인터페이스 설정 (초기에는 비워둠) # 네트워크 인터페이스 설정 (초기에는 비워둠)
self.config = {"nics": {}} self.config = {"nics": {}}
self.github_repo_url = "https://raw.githubusercontent.com/jung-geun/policy-routing/main/policy_routing.py"
def run_command(self, cmd, ignore_error=False): def run_command(self, cmd, ignore_error=False):
"""시스템 명령어 실행""" """시스템 명령어 실행"""
@@ -44,6 +48,88 @@ class PolicyBasedRoutingManager:
self.logger.error(f"명령어 실행 실패: {cmd} - {e}") self.logger.error(f"명령어 실행 실패: {cmd} - {e}")
return None return None
def get_latest_version(self):
"""GitHub에서 최신 버전 정보 가져오기"""
try:
response = requests.get(self.github_repo_url)
response.raise_for_status() # HTTP 오류 발생 시 예외 발생
# 파일 내용에서 __version__ 라인 찾기
for line in response.text.splitlines():
if "__version__" in line:
match = re.search(
r'__version__\s*=\s*["\'](\d+\.\d+\.\d+)["\']', line
)
if match:
return match.group(1)
return None
except requests.exceptions.RequestException as e:
self.logger.error(f"최신 버전 정보를 가져오는 데 실패했습니다: {e}")
return None
def check_for_updates(self):
"""업데이트 확인 및 사용자에게 알림"""
self.logger.info("최신 버전 확인 중...")
latest_version = self.get_latest_version()
current_version = __version__
if latest_version:
self.logger.info(
f"현재 버전: {current_version}, 최신 버전: {latest_version}"
)
# 버전 비교 (간단한 문자열 비교, 실제로는 semantic versioning 라이브러리 사용 권장)
if latest_version > current_version:
self.logger.info("새로운 버전이 사용 가능합니다!")
response = input("업데이트를 진행하시겠습니까? (y/N): ")
if response.lower() == "y":
return True
else:
self.logger.info("업데이트가 취소되었습니다.")
return False
else:
self.logger.info("현재 최신 버전을 사용 중입니다.")
return False
else:
self.logger.warning(
"최신 버전 정보를 가져올 수 없어 업데이트 확인을 건너뜁니다."
)
return False
def perform_update(self):
"""스크립트를 최신 버전으로 업데이트"""
self.logger.info("스크립트 업데이트를 시작합니다...")
try:
response = requests.get(self.github_repo_url)
response.raise_for_status() # HTTP 오류 발생 시 예외 발생
script_content = response.text
current_script_path = Path(sys.argv[0]) # 현재 실행 중인 스크립트의 경로
# 현재 스크립트 파일을 백업
backup_path = current_script_path.with_suffix(
f".py.bak_{datetime.now().strftime('%Y%m%d%H%M%S')}"
)
current_script_path.rename(backup_path)
self.logger.info(f"현재 스크립트 백업 완료: {backup_path}")
# 최신 내용으로 스크립트 파일 덮어쓰기
with open(current_script_path, "w") as f:
f.write(script_content)
# 실행 권한 유지
current_script_path.chmod(0o755)
self.logger.info(
"스크립트 업데이트가 성공적으로 완료되었습니다. 스크립트를 다시 실행해주세요."
)
sys.exit(0) # 업데이트 후 스크립트 재시작을 위해 종료
except requests.exceptions.RequestException as e:
self.logger.error(f"스크립트 다운로드 실패: {e}")
except Exception as e:
self.logger.error(f"스크립트 업데이트 중 오류 발생: {e}")
return False
def get_network_interfaces(self): def get_network_interfaces(self):
"""활성화된 네트워크 인터페이스 목록 가져오기""" """활성화된 네트워크 인터페이스 목록 가져오기"""
interfaces = {} interfaces = {}
@@ -65,6 +151,7 @@ class PolicyBasedRoutingManager:
and not interface.startswith("docker") and not interface.startswith("docker")
and not interface.startswith("veth") and not interface.startswith("veth")
and not interface.startswith("br-") and not interface.startswith("br-")
and not interface.startswith("ovs-")
and "state UP" in line and "state UP" in line
): ):
interfaces[interface] = {} interfaces[interface] = {}
@@ -342,6 +429,20 @@ class PolicyBasedRoutingManager:
# 기존 default 라우트 제거 # 기존 default 라우트 제거
self.run_command("ip route del default", ignore_error=True) self.run_command("ip route del default", ignore_error=True)
# DNS 서버 목록 (널리 사용되는 공용 DNS)
dns_servers = [
"8.8.8.8", # Google DNS
"8.8.4.4", # Google DNS
"1.1.1.1", # Cloudflare DNS
"1.0.0.1", # Cloudflare DNS
"208.67.222.222", # OpenDNS
"208.67.220.220", # OpenDNS
]
# 기존 DNS 서버 라우트 제거
for dns in dns_servers:
self.run_command(f"ip route del {dns}", ignore_error=True)
# metric 순으로 정렬하여 default 라우트 추가 # metric 순으로 정렬하여 default 라우트 추가
sorted_nics = sorted(self.config["nics"].items(), key=lambda x: x[1]["metric"]) sorted_nics = sorted(self.config["nics"].items(), key=lambda x: x[1]["metric"])
@@ -357,6 +458,25 @@ class PolicyBasedRoutingManager:
f"Default 라우트 추가: {gateway} via {interface} (metric: {metric})" f"Default 라우트 추가: {gateway} via {interface} (metric: {metric})"
) )
# DNS 서버들을 NIC별로 분산하여 라우팅 설정
self.logger.info("DNS 서버 라우팅 설정 중...")
for i, dns in enumerate(dns_servers):
# DNS 서버를 NIC 개수만큼 순환하여 분산
nic_index = i % len(sorted_nics)
nic_name, nic_config = sorted_nics[nic_index]
interface = nic_config["interface"]
gateway = nic_config["gateway"]
metric = nic_config["metric"]
self.run_command(
f"ip route add {dns} via {gateway} dev {interface} metric {metric}"
)
self.logger.info(
f"DNS 라우트 추가: {dns} via {gateway} (interface: {interface}, metric: {metric})"
)
def check_interfaces(self): def check_interfaces(self):
"""네트워크 인터페이스 상태 확인""" """네트워크 인터페이스 상태 확인"""
self.logger.info("네트워크 인터페이스 상태 확인 중...") self.logger.info("네트워크 인터페이스 상태 확인 중...")
@@ -640,6 +760,21 @@ class StartupPolicyBasedRoutingManager:
def setup_main_routing(self, current_nics): def setup_main_routing(self, current_nics):
self.logger.info("메인 라우팅 테이블 설정 중...") self.logger.info("메인 라우팅 테이블 설정 중...")
self.run_command("ip route del default", ignore_error=True) self.run_command("ip route del default", ignore_error=True)
# DNS 서버 목록 (널리 사용되는 공용 DNS)
dns_servers = [
"8.8.8.8", # Google DNS
"8.8.4.4", # Google DNS
"1.1.1.1", # Cloudflare DNS
"1.0.0.1", # Cloudflare DNS
"208.67.222.222", # OpenDNS
"208.67.220.220", # OpenDNS
]
# 기존 DNS 서버 라우트 제거
for dns in dns_servers:
self.run_command(f"ip route del {{dns}}", ignore_error=True)
sorted_nics = sorted(current_nics.items(), key=lambda x: x[1]["metric"]) sorted_nics = sorted(current_nics.items(), key=lambda x: x[1]["metric"])
for nic_name, nic_config in sorted_nics: for nic_name, nic_config in sorted_nics:
interface = nic_config["interface"] interface = nic_config["interface"]
@@ -647,6 +782,21 @@ class StartupPolicyBasedRoutingManager:
metric = nic_config["metric"] metric = nic_config["metric"]
self.run_command(f"ip route add default via {{gateway}} dev {{interface}} metric {{metric}}") self.run_command(f"ip route add default via {{gateway}} dev {{interface}} metric {{metric}}")
self.logger.info(f"Default 라우트 추가: {{gateway}} via {{interface}} (metric: {{metric}})") self.logger.info(f"Default 라우트 추가: {{gateway}} via {{interface}} (metric: {{metric}})")
# DNS 서버들을 NIC별로 분산하여 라우팅 설정
self.logger.info("DNS 서버 라우팅 설정 중...")
for i, dns in enumerate(dns_servers):
# DNS 서버를 NIC 개수만큼 순환하여 분산
nic_index = i % len(sorted_nics)
nic_name, nic_config = sorted_nics[nic_index]
interface = nic_config["interface"]
gateway = nic_config["gateway"]
metric = nic_config["metric"]
self.run_command(f"ip route add {{dns}} via {{gateway}} dev {{interface}} metric {{metric}}")
self.logger.info(f"DNS 라우트 추가: {{dns}} via {{gateway}} (interface: {{interface}}, metric: {{metric}})")
def main_startup(): def main_startup():
manager = StartupPolicyBasedRoutingManager() manager = StartupPolicyBasedRoutingManager()
@@ -836,6 +986,91 @@ if __name__ == "__main__":
self.logger.info("설정 제거 완료") self.logger.info("설정 제거 완료")
def install_auto_nic_setup(self):
"""자동 NIC 감지 스크립트 및 udev 규칙 설치"""
self.logger.info("자동 NIC 감지 설정 설치 중...")
auto_nic_setup_sh_content = """#!/bin/bash
# Auto NIC Setup Script
# This script will be called by udev when a network interface event occurs
INTERFACE="$1"
ACTION="$2"
LOG_FILE="/var/log/auto-nic-setup.log"
PBR_SCRIPT_PATH="/home/pieroot/policy-routing/policy_routing.py"
# Set PATH for udev execution
export PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Logging function
log_message() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}
log_message "=== Auto NIC Setup Started for interface: $INTERFACE (Action: $ACTION) ==="
# Always apply policy routing changes
log_message "Applying policy routing changes..."
if [ -f "$PBR_SCRIPT_PATH" ]; then
# It's better to run the python script in its directory
cd "$(dirname "$PBR_SCRIPT_PATH")"
if python3 "$PBR_SCRIPT_PATH" apply_changes >> "$LOG_FILE" 2>&1; then
log_message "Policy routing changes applied successfully."
else
log_message "ERROR: Failed to apply policy routing changes."
fi
else
log_message "ERROR: policy_routing.py script not found at $PBR_SCRIPT_PATH"
fi
# The rest of the script can be for additional logic if needed,
# but for now, the main goal is to trigger apply_changes.
# The original logic for DHCP and bringing interfaces up can be kept if necessary.
log_message "=== Auto NIC Setup Completed for interface: $INTERFACE ==="
"""
udev_rules_content = """# Auto NIC Setup udev rules
# This rule triggers when a network interface is added, changed, or removed.
# Rule for network interface addition
SUBSYSTEM=="net", ACTION=="add", KERNEL=="eth*|ens*|enp*", RUN+="/usr/local/bin/auto-nic-setup.sh $name $action"
# Rule for network interface changes
SUBSYSTEM=="net", ACTION=="change", KERNEL=="eth*|ens*|enp*", RUN+="/usr/local/bin/auto-nic-setup.sh $name $action"
# Rule for network interface removal
SUBSYSTEM=="net", ACTION=="remove", KERNEL=="eth*|ens*|enp*", RUN+="/usr/local/bin/auto-nic-setup.sh $name $action"
"""
try:
# Create auto-nic-setup.sh
auto_nic_setup_path = Path("/usr/local/bin/auto-nic-setup.sh")
auto_nic_setup_path.write_text(auto_nic_setup_sh_content)
auto_nic_setup_path.chmod(0o755)
self.logger.info(f"스크립트 생성 완료: {auto_nic_setup_path}")
# Create udev rule
udev_rule_path = Path("/etc/udev/rules.d/99-auto-nic-setup.rules")
udev_rule_path.write_text(udev_rules_content)
self.logger.info(f"udev 규칙 생성 완료: {udev_rule_path}")
# Reload udev rules
self.logger.info("udev 규칙 다시 로드 중...")
result = self.run_command("udevadm control --reload-rules && udevadm trigger")
if result and result.returncode == 0:
self.logger.info("udev 규칙이 성공적으로 다시 로드되었습니다.")
else:
self.logger.error("udev 규칙을 다시 로드하는 데 실패했습니다.")
return False
self.logger.info("자동 NIC 감지 설정 설치가 완료되었습니다.")
return True
except Exception as e:
self.logger.error(f"설치 중 오류 발생: {e}")
return False
def main(): def main():
import argparse import argparse
@@ -845,7 +1080,7 @@ def main():
) )
parser.add_argument( parser.add_argument(
"action", "action",
choices=["setup", "remove", "verify", "detect", "apply_changes"], choices=["setup", "remove", "verify", "detect", "apply_changes", "install"],
help="수행할 작업", help="수행할 작업",
) )
parser.add_argument( parser.add_argument(
@@ -858,6 +1093,11 @@ def main():
manager = PolicyBasedRoutingManager() manager = PolicyBasedRoutingManager()
# 스크립트 시작 시 업데이트 확인
if manager.check_for_updates():
manager.perform_update()
# perform_update는 성공 시 sys.exit(0)을 호출하므로, 이 아래 코드는 실행되지 않음
if args.action == "setup": if args.action == "setup":
manager.setup(force=args.force) manager.setup(force=args.force)
elif args.action == "remove": elif args.action == "remove":
@@ -868,6 +1108,8 @@ def main():
manager.print_detected_config() manager.print_detected_config()
elif args.action == "apply_changes": elif args.action == "apply_changes":
manager.apply_dynamic_rules() manager.apply_dynamic_rules()
elif args.action == "install":
manager.install_auto_nic_setup()
if __name__ == "__main__": if __name__ == "__main__":

2
sonar-project.properties Normal file
View File

@@ -0,0 +1,2 @@
sonar.projectKey=dmslab_policy-routing_56aaf3b2-bfac-465c-8417-8c99edccf1c2
sonar.qualitygate.wait=true