本文目录导读:

我来详细说明如何用Python脚本生成SaltStack配置。
基础配置模板
#!/usr/bin/env python3
"""
生成SaltStack配置文件的Python脚本
"""
import os
import json
import yaml
from typing import Dict, List, Any
class SaltConfigGenerator:
def __init__(self, output_dir: str = "./salt_config"):
self.output_dir = output_dir
self.config = {}
def generate_master_config(self, master_ip: str = "127.0.0.1") -> Dict:
"""生成Salt Master配置"""
config = {
"interface": master_ip,
"publish_port": 4505,
"ret_port": 4506,
"auto_accept": True,
"file_roots": {
"base": ["/srv/salt"]
},
"pillar_roots": {
"base": ["/srv/pillar"]
},
"log_level": "info",
"log_file": "/var/log/salt/master",
"worker_threads": 5,
"max_open_files": 100000,
"timeout": 5,
"loop_interval": 60,
"output": "nested",
"color": True,
"sock_dir": "/var/run/salt/master",
"pidfile": "/var/run/salt-master.pid",
"root_dir": "/",
"conf_file": "/etc/salt/master",
"cachedir": "/var/cache/salt/master",
"keep_jobs": 24,
"gather_job_timeout": 10,
"syndic_wait": 5,
"preserve_minion_cache": False,
"win_repo_cachefile": "salt://win/repo/winrepo.p",
"ext_pillar": [],
"ext_job_cache": "",
"master_stats": False,
"master_job_cache": "local_cache",
"enforce_mine_cache": False,
"mine_enabled": True,
"mine_return_job": False,
"mine_interval": 60,
"cli_summary": False,
"max_minions": 0,
"consecutive_errors": 0,
"rotate_aes_key": True,
"req_server_niceness": None,
"pub_server_niceness": None,
"preserve_minion_cache": False
}
return config
def generate_minion_config(self,
minion_id: str,
master_ip: str,
environment: str = "production") -> Dict:
"""生成Salt Minion配置"""
config = {
"master": master_ip,
"master_port": 4506,
"id": minion_id,
"environment": environment,
"log_level": "info",
"log_file": f"/var/log/salt/minion-{minion_id}",
"log_level_logfile": "info",
"log_datefmt": "%H:%M:%S",
"log_fmt_console": "[%(levelname)-8s] %(message)s",
"log_fmt_logfile": "%(asctime)s,%(msecs)03d [%(name)-17s:%(lineno)-4d][%(levelname)-8s][%(process)d] %(message)s",
"log_granular_levels": {},
"file_client": "remote",
"use_master_when_local": False,
"state_verbose": True,
"state_output": "full",
"state_aggregate": False,
"acceptance_wait_time": 10,
"acceptance_wait_time_max": 0,
"rejected_retry": False,
"random_reauth_delay": 60,
"reauth_delay": 60,
"loop_interval": 1,
"verify_env": True,
"cache_jobs": False,
"grains": {
"roles": [],
"environment": environment,
"deployment": "standard"
},
"pillar_opts": True,
"minion_sign_messages": False,
"zmq_monitor": False,
"master_type": "str",
"master_uri": "",
"local": False,
"ipc_mode": "ipc",
"tcp_pub_port": 4510,
"tcp_pull_port": 4511,
"tcp_master_pub_port": 4512,
"tcp_master_pull_port": 4513
}
return config
def generate_pillar_config(self, pillar_data: Dict) -> Dict:
"""生成Pillar配置文件"""
return {
"pillar": {
"base": pillar_data
}
}
def save_yaml_config(self, config: Dict, filename: str):
"""保存为YAML格式"""
filepath = os.path.join(self.output_dir, filename)
os.makedirs(os.path.dirname(filepath), exist_ok=True)
with open(filepath, 'w') as f:
yaml.dump(config, f, default_flow_style=False, indent=2)
print(f"配置已保存: {filepath}")
def save_json_config(self, config: Dict, filename: str):
"""保存为JSON格式"""
filepath = os.path.join(self.output_dir, filename)
os.makedirs(os.path.dirname(filepath), exist_ok=True)
with open(filepath, 'w') as f:
json.dump(config, f, indent=2)
print(f"配置已保存: {filepath}")
def generate_top_file(self, environments: List[str]):
"""生成top.sls文件"""
top_config = {
"base": {
"*": ["core", "security"],
"web*": ["nginx", "php", "node"],
"db*": ["mysql", "postgresql"],
"cache*": ["redis", "memcached"]
}
}
if environments:
for env in environments:
if env != "base":
top_config[env] = {"'*'": ["default"]}
return top_config
def generate_state_file(self, state_name: str, state_data: Dict):
"""生成状态文件"""
return {state_name: state_data}
def generate_schedule_config(self, jobs: List[Dict]) -> Dict:
"""生成计划任务配置"""
schedule = {}
for job in jobs:
schedule[job['name']] = {
"function": job.get('function', 'state.apply'),
"args": job.get('args', []),
"kwargs": job.get('kwargs', {}),
"seconds": job.get('interval', 3600),
"splay": job.get('splay', 10),
"run_on_start": job.get('run_on_start', False),
"returner": job.get('returner', '')
}
return {"schedule": schedule}
高级配置生成器
#!/usr/bin/env python3
"""
高级配置生成器,支持模板化和多环境
"""
import os
import sys
import jinja2
import yaml
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from pathlib import Path
@dataclass
class SaltConfigTemplate:
"""配置模板数据类"""
master_ip: str = "127.0.0.1"
minion_id: str = "minion01"
environment: str = "production"
roles: List[str] = None
log_level: str = "info"
def __post_init__(self):
if self.roles is None:
self.roles = ["base"]
class AdvancedConfigGenerator:
def __init__(self, template_dir: str = "templates"):
self.template_dir = template_dir
self.jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(template_dir),
keep_trailing_newline=True
)
def render_template(self, template_name: str, context: Dict) -> str:
"""渲染Jinja2模板"""
template = self.jinja_env.get_template(template_name)
return template.render(context)
def generate_master_config_template(self) -> str:
"""生成Master配置模板"""
return """# Salt Master Configuration
# Generated by Python Config Generator
# Date: {{ generation_date }}
interface: {{ master_ip }}
publish_port: {{ publish_port }}
ret_port: {{ ret_port }}
# File System
file_roots:
base:
- /srv/salt
{{ environment }}:
- /srv/salt/{{ environment }}
pillar_roots:
base:
- /srv/pillar
{{ environment }}:
- /srv/pillar/{{ environment }}
# Logging
log_level: {{ log_level }}
log_file: /var/log/salt/master
# Performance
worker_threads: {{ worker_threads }}
max_open_files: {{ max_open_files }}
# Security
auto_accept: {{ auto_accept }}
{% if auto_sign_master_sign_pubkey %}
autosign_file: /etc/salt/autosign.conf
{% endif %}
# External Pillar
{% if external_pillars %}
ext_pillar:
{% for pillar in external_pillars %}
- {{ pillar.type }}: {{ pillar.config }}
{% endfor %}
{% endif %}
# Reactor
{% if reactor_config %}
reactor:
{% for event, actions in reactor_config.items() %}
- '{{ event }}':
{% for action in actions %}
- /srv/reactor/{{ action }}
{% endfor %}
{% endfor %}
{% endif %}
"""
def generate_minion_config_template(self) -> str:
"""生成Minion配置模板"""
return """# Salt Minion Configuration
# Generated by Python Config Generator
# Minion ID: {{ minion_id }}
master: {{ master_ip }}
master_port: {{ master_port }}
id: {{ minion_id }}
environment: {{ environment }}
# Logging
log_level: {{ log_level }}
log_file: /var/log/salt/minion-{{ minion_id }}
# Grains
grains:
roles:
{% for role in roles %}
- {{ role }}
{% endfor %}
environment: {{ environment }}
datacenter: {{ datacenter }}
deployment: {{ deployment }}
# Features
features:
use_master_when_local: {{ use_master_when_local }}
cache_jobs: {{ cache_jobs }}
# Startup
startup_states: {{ startup_states }}
schedule:
{% for job in scheduled_jobs %}
{{ job.name }}:
function: {{ job.function }}
seconds: {{ job.interval }}
splay: {{ job.splay }}
run_on_start: {{ job.run_on_start }}
{% endfor %}
"""
def generate_complete_deployment(self,
template_data: SaltConfigTemplate,
output_dir: str = "./generated_config"):
"""生成完整的部署配置"""
os.makedirs(output_dir, exist_ok=True)
os.makedirs(f"{output_dir}/master", exist_ok=True)
os.makedirs(f"{output_dir}/minions", exist_ok=True)
os.makedirs(f"{output_dir}/states", exist_ok=True)
os.makedirs(f"{output_dir}/pillar", exist_ok=True)
context = {
"generation_date": __import__('datetime').datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"master_ip": template_data.master_ip,
"minion_id": template_data.minion_id,
"environment": template_data.environment,
"roles": template_data.roles,
"log_level": template_data.log_level,
"publish_port": 4505,
"ret_port": 4506,
"worker_threads": 5,
"max_open_files": 100000,
"auto_accept": True,
"auto_sign_master_sign_pubkey": False,
"external_pillars": [],
"reactor_config": {
"salt/minion/*/start": ["minion_start.sls"],
"salt/beacon/*/*/": ["beacon_alert.sls"]
},
"master_port": 4506,
"datacenter": "dc1",
"deployment": "standard",
"use_master_when_local": False,
"startup_states": "",
"cache_jobs": True,
"scheduled_jobs": [
{
"name": "highstate_check",
"function": "state.highstate",
"interval": 3600,
"splay": 300,
"run_on_start": True
},
{
"name": "package_update",
"function": "pkg.upgrade",
"interval": 86400,
"splay": 600,
"run_on_start": False
}
]
}
# 生成Master配置
master_config = self.jinja_env.from_string(
self.generate_master_config_template()
).render(context)
with open(f"{output_dir}/master/master.conf", 'w') as f:
f.write(master_config)
# 生成Minion配置
minion_config = self.jinja_env.from_string(
self.generate_minion_config_template()
).render(context)
with open(f"{output_dir}/minions/{context['minion_id']}.conf", 'w') as f:
f.write(minion_config)
return output_dir
# 使用示例
if __name__ == "__main__":
from datetime import datetime
# 基本配置生成
generator = SaltConfigGenerator()
# 生成Master配置
master_config = generator.generate_master_config("192.168.1.100")
generator.save_yaml_config(master_config, "master/master.conf")
# 生成Minion配置
minion_config = generator.generate_minion_config(
minion_id="web-server-01",
master_ip="192.168.1.100",
environment="production"
)
generator.save_yaml_config(minion_config, "minions/web-server-01.conf")
# 高级配置生成
advanced_gen = AdvancedConfigGenerator()
config = SaltConfigTemplate(
master_ip="192.168.1.100",
minion_id="web-server-01",
environment="production",
roles=["web", "app", "monitoring"],
log_level="info"
)
output_dir = advanced_gen.generate_complete_deployment(config)
print(f"配置已生成到: {output_dir}")
批量配置生成器
#!/usr/bin/env python3
"""
批量生成多台服务器的Salt配置
"""
import csv
import json
from typing import List, Dict
import concurrent.futures
class BatchConfigGenerator:
"""批量配置生成器"""
def __init__(self, master_ip: str = "192.168.1.100"):
self.master_ip = master_ip
self.generator = SaltConfigGenerator()
def generate_from_csv(self, csv_file: str):
"""从CSV文件批量生成配置"""
with open(csv_file, 'r') as f:
reader = csv.DictReader(f)
for row in reader:
self.generate_single_config(row)
def generate_from_json(self, json_file: str):
"""从JSON文件批量生成配置"""
with open(json_file, 'r') as f:
data = json.load(f)
for item in data:
self.generate_single_config(item)
def generate_single_config(self, config_data: Dict):
"""生成单个配置"""
minion_config = self.generator.generate_minion_config(
minion_id=config_data.get('hostname', 'minion'),
master_ip=self.master_ip,
environment=config_data.get('environment', 'production')
)
# 添加自定义grains
if 'grains' in config_data:
minion_config['grains'].update(config_data['grains'])
# 生成文件名
filename = f"{config_data['hostname']}.conf"
self.generator.save_yaml_config(minion_config, f"minions/{filename}")
def generate_parallel(self, configs: List[Dict]):
"""并行生成配置"""
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
futures = [
executor.submit(self.generate_single_config, config)
for config in configs
]
concurrent.futures.wait(futures)
# 使用示例
if __name__ == "__main__":
# 批量生成示例
batch_gen = BatchConfigGenerator(master_ip="192.168.1.100")
# 从JSON批量生成
servers = [
{
"hostname": "web-01",
"environment": "production",
"grains": {"roles": ["web"], "region": "us-east-1"}
},
{
"hostname": "db-01",
"environment": "production",
"grains": {"roles": ["database"], "region": "us-east-1"}
},
{
"hostname": "cache-01",
"environment": "staging",
"grains": {"roles": ["cache"], "region": "us-west-2"}
}
]
batch_gen.generate_parallel(servers)
print("批量配置生成完成!")
配置验证器
#!/usr/bin/env python3
"""
Salt配置验证器
"""
class ConfigValidator:
"""配置验证器"""
@staticmethod
def validate_master_config(config: Dict) -> List[str]:
"""验证Master配置"""
errors = []
required_fields = ['interface', 'publish_port', 'ret_port']
for field in required_fields:
if field not in config:
errors.append(f"缺少必要字段: {field}")
if 'publish_port' in config:
if not (1024 <= config['publish_port'] <= 65535):
errors.append("publish_port必须在1024-65535之间")
if config.get('interface') == '0.0.0.0':
errors.append("警告: interface设置为0.0.0.0可能不安全")
return errors
@staticmethod
def validate_minion_config(config: Dict) -> List[str]:
"""验证Minion配置"""
errors = []
if 'master' not in config and 'master' not in str(config):
errors.append("必须指定master地址")
if 'id' not in config:
errors.append("必须指定minion ID")
# 验证日志级别
valid_log_levels = ['debug', 'info', 'warning', 'error', 'critical']
if 'log_level' in config:
if config['log_level'] not in valid_log_levels:
errors.append(f"无效的日志级别: {config['log_level']}")
return errors
# 使用示例
validator = ConfigValidator()
errors = validator.validate_minion_config({'id': 'test-minion'})
if errors:
print("验证错误:", errors)
else:
print("配置验证通过")
这些脚本可以根据你的具体需求进行调整和扩展,主要功能包括:
- 基础配置生成 - 生成Master和Minion的基础配置
- 模板化配置 - 使用Jinja2模板生成动态配置
- 批量生成 - 从CSV/JSON批量生成多台服务器配置
- 配置验证 - 验证生成的配置是否正确
- 多环境支持 - 支持不同环境的配置生成
使用时只需修改配置参数并运行相应的脚本即可生成完整的SaltStack配置文件。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播