Cobbler: 是一个 Linux服务器快速网络安装的工具,由python 开发
本人开源代码: I夏/CMDB
cobbler 提供了命令行和api进行管理
- cobbler check 核对当前设置是否有问题
- cobbler list 列出所有的cobbler元素
- cobbler report 列出元素的详细信息
- cobbler sync 同步配置到数据目录,更改配置最好都要执行下
- cobbler reposync 同步yum仓库
- cobbler distro 查看导入的发行版系统信息
- cobbler system 查看添加的系统信息
- cobbler profile 查看配置信息
环境:centos7.2 mini x64
ip: 192.168.5.50
需要确保epel源已经安装成功
安装
yum -y install httpd dhcp tftp python-ctypes cobbler xinetd cobbler-web
2.启动服务
- systemctl start httpd
- systemctl enable httpd
- systemctl start cobblerd
- systemctl enable cobblerd
3.检查cobbler 配置是否正常
- [root@cobbler ~]# cobbler check
- The following are potential configuration items that you may want to fix:
-
- 1 : The 'server' field in /etc/cobbler/settings must be set to something other than localhost, or kickstarting features will not work. This should be a resolvable hostname or IP for the boot server as reachable by all machines that will use it.
- 2 : For PXE to be functional, the 'next_server' field in /etc/cobbler/settings must be set to something other than 127.0.0.1, and should match the IP of the boot server on the PXE network.
- 3 : change 'disable' to 'no' in /etc/xinetd.d/tftp
- 4 : Some network boot-loaders are missing from /var/lib/cobbler/loaders, you may run 'cobbler get-loaders' to download them, or, if you only want to handle x86/x86_64 netbooting, you may ensure that you have installed a *recent* version of the syslinux package installed and can ignore this message entirely. Files in this directory, should you want to support all architectures, should include pxelinux.0, menu.c32, elilo.efi, and yaboot. The 'cobbler get-loaders' command is the easiest way to resolve these requirements.
- 5 : enable and start rsyncd.service with systemctl
- 6 : debmirror package is not installed, it will be required to manage debian deployments and repositories
- 7 : ksvalidator was not found, install pykickstart
- 8 : The default password used by the sample templates for newly installed machines (default_password_crypted in /etc/cobbler/settings) is still set to 'cobbler' and should be changed, try: "openssl passwd -1 -salt 'random-phrase-here' 'your-password-here'" to generate new one
- 9 : fencing tools were not found, and are required to use the (optional) power management features. install cman or fence-agents to use them
-
- Restart cobblerd and then run 'cobbler sync' to apply changes.
我们需要解决这些警告
问题1,告诉我们 server 这个字段的值应该是一个地址不要写本地地址,因为我们是对外访问的,最后将这个字段修改为服务的ip
sed -i 's/^server: 127.0.0.1/server: 192.168.5.50/' /etc/cobbler/settings
问题2,next_server 该字段为pxe服务器的字段,不要设置为127.0.0.1,最好设置为自己服务器的ip
sed -i 's/^next_server: 127.0.0.1/next_server: 192.168.5.50/' /etc/cobbler/settings # pxe服务器 即 TFTP Server 的IP地址
问题3,cobbler服务需要tftp 服务启动,需要将 tftp 的disable 的值修改为no
- [root@cobbler ~]# cat /etc/xinetd.d/tftp
- # default: off
- # description: The tftp server serves files using the trivial file transfer \
- # protocol. The tftp protocol is often used to boot diskless \
- # workstations, download configuration files to network-aware printers, \
- # and to start the installation process for some operating systems.
- service tftp
- {
- socket_type = dgram
- protocol = udp
- wait = yes
- user = root
- server = /usr/sbin/in.tftpd
- server_args = -s /var/lib/tftpboot
- disable = no #默认是yes,需要修改为no
- per_source = 11
- cps = 100 2
- flags = IPv4
- }
问题4,boot-loaders 在本地或许不存在,需要通过 命令 cobbler get-loaders 下载
- [root@cobbler ~]# cobbler get-loaders
- task started: 2018-12-04_095358_get_loaders
- task started (id=Download Bootloader Content, time=Tue Dec 4 09:53:58 2018)
- downloading https://cobbler.github.io/loaders/README to /var/lib/cobbler/loaders/README
- downloading https://cobbler.github.io/loaders/COPYING.elilo to /var/lib/cobbler/loaders/COPYING.elilo
- downloading https://cobbler.github.io/loaders/COPYING.yaboot to /var/lib/cobbler/loaders/COPYING.yaboot
- downloading https://cobbler.github.io/loaders/COPYING.syslinux to /var/lib/cobbler/loaders/COPYING.syslinux
- downloading https://cobbler.github.io/loaders/elilo-3.8-ia64.efi to /var/lib/cobbler/loaders/elilo-ia64.efi
- downloading https://cobbler.github.io/loaders/yaboot-1.3.17 to /var/lib/cobbler/loaders/yaboot
- downloading https://cobbler.github.io/loaders/pxelinux.0-3.86 to /var/lib/cobbler/loaders/pxelinux.0
- downloading https://cobbler.github.io/loaders/menu.c32-3.86 to /var/lib/cobbler/loaders/menu.c32
- downloading https://cobbler.github.io/loaders/grub-0.97-x86.efi to /var/lib/cobbler/loaders/grub-x86.efi
- downloading https://cobbler.github.io/loaders/grub-0.97-x86_64.efi to /var/lib/cobbler/loaders/grub-x86_64.efi
- *** TASK COMPLETE ***
问题5,是 rsyncd 服务开机自动启动
- [root@cobbler ~]# systemctl enable rsyncd
- Created symlink from /etc/systemd/system/multi-user.target.wants/rsyncd.service to /usr/lib/systemd/system/rsyncd.service.
问题6,这个和debian 有关系,目测用不到,一些企业大部分用redhat 或者centos系统
问题7,ksvalidator没有找到,让安装 pykickstart
[root@cobbler ~]# yum install -y pykickstart
问题8,模板的默认密码是 cobbler,最好重新设置一些,要不要安装系统的默认密码就是cobbler,可以 通过 openssl passwd 进行设置
- [root@cobbler ~]# [root@cobbler ~]# openssl passwd -1 -salt 'ilove' 'nineven' # ilove 是随机盐 nineven 是密码
- $1$ilove$A0hokoomR0W702oHUi1OT0
-
- #这个字段 default_password_crypted 将生成的密码替换
- [root@cobbler ~]# grep '^default_password_crypted' /etc/cobbler/settings
- default_password_crypted: "$1$ilove$A0hokoomR0W702oHUi1OT0"
重新检查错误
- [root@cobbler ~]# systemctl restart cobblerd
- [root@cobbler ~]# cobbler check
- The following are potential configuration items that you may want to fix:
-
- 1 : debmirror package is not installed, it will be required to manage debian deployments and repositories
- 2 : fencing tools were not found, and are required to use the (optional) power management features. install cman or fence-agents to use them
-
- Restart cobblerd and then run 'cobbler sync' to apply changes
这两个错误可以忽略
4.配置cobbler 直接接管dhcp服务
- [root@cobbler ~]# vim /etc/cobbler/settings
- [root@cobbler ~]# grep '^manage_dhcp' /etc/cobbler/settings
- manage_dhcp: 1
配置dhcp模板
- [root@cobbler ~]# vim /etc/cobbler/dhcp.template
- ddns-update-style interim;
-
- allow booting;
- allow bootp;
-
- deny unknown-clients; # 开启白名单默认,拒绝其他客户端,默认没有,需要单独添加
-
- ignore client-updates;
- set vendorclass = option vendor-class-identifier;
-
- option pxe-system-type code 93 = unsigned integer 16;
-
- subnet 192.168.5.0 netmask 255.255.255.0 {
- option routers 192.168.5.1;
- option domain-name-servers 192.168.5.1;
- option subnet-mask 255.255.255.0;
- range dynamic-bootp 192.168.5.10 192.168.5.50;
-
- #仅列出部分
5.配置只安装一次,要不然,会出现重复安装系统
- [root@cobbler ~]# vim /etc/cobbler/settings
- [root@cobbler ~]# grep '^pxe_just_once' /etc/cobbler/settings
- pxe_just_once: 1
修改settings 配置文件之后,需要重启cobblerd 服务,使之生效
- [root@cobbler ~]# systemctl restart cobblerd
- [root@cobbler ~]# cobbler sync
6,导入系统:
可以发现现在,所有都是空的,
- [root@cobbler ~]# cobbler list
- distros:
-
- profiles:
-
- systems:
-
- repos:
-
- images:
-
- mgmtclasses:
-
- packages:
-
- files:
通过 cobbler import 导入系统
a,先挂载系统,可以通过光驱挂载,也可以将镜像传到本地,然后进行挂载,我是通过上传镜像进行挂载的
- [root@cobbler ~]# mount /root/CentOS-7-x86_64-Minimal-1511.iso /mnt/
- mount: /dev/loop0 is write-protected, mounting read-only
- [root@cobbler ~]# cobbler import --path=/mnt/ --name=CentOS-7-x86_64-Minimal-1511 --arch=x86_64
- task started: 2018-12-04_102336_import
- task started (id=Media import, time=Tue Dec 4 10:23:36 2018)
- Found a candidate signature: breed=redhat, version=rhel6
- Found a candidate signature: breed=redhat, version=rhel7
- Found a matching signature: breed=redhat, version=rhel7
- Adding distros from path /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64:
- creating new distro: CentOS-7-Minimal-1511-x86_64
- trying symlink: /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64 -> /var/www/cobbler/links/CentOS-7-Minimal-1511-x86_64
- creating new profile: CentOS-7-Minimal-1511-x86_64
- associating repos
- checking for rsync repo(s)
- checking for rhn repo(s)
- checking for yum repo(s)
- starting descent into /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64 for CentOS-7-Minimal-1511-x86_64
- processing repo at : /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64
- need to process repo/comps: /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64
- looking for /var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64/repodata/*comps*.xml
- Keeping repodata as-is :/var/www/cobbler/ks_mirror/CentOS-7-x86_64-Minimal-1511-x86_64/repodata
- *** TASK COMPLETE ***
通过cobbler list 查询信息
- [root@cobbler ~]# cobbler list
- distros:
- CentOS-7-Minimal-1511-x86_64
-
- profiles:
- CentOS-7-Minimal-1511-x86_64
-
- systems:
-
- repos:
-
- images:
-
- mgmtclasses:
-
- packages:
-
- files:
Cobbler 服务已经搭建好了
关于api的一些方法,可以查看
/usr/lib/python2.7/site-packages/cobbler
该目录下的remote.py 文件
需要在cobbler 服务端的 /usr/bin/cobblerd 文件的 import 下一行增加
- reload(sys)
- sys.setdefaultencoding('utf8')
解决ks内容出现中文的bug
既然有API了,那么我们就可以通过web页面调用这个api ,通过页面添加安装系统任务
具体代码请看 https://gitee.com/nineven/CMDB
需要先安装好cobbler服务
- #!/usr/bin/env python
- # -*- coding:utf-8 -*-
- # author : liuyu
- # date : 2018/11/19 0019
-
- import xmlrpc.client,time,os
-
-
- '''
- 需要在cobbler 服务端的 /usr/bin/cobblerd 文件的 import 下一行增加
- reload(sys)
- sys.setdefaultencoding('utf8')
- 解决ks内容出现中文的bug
- '''
- class CobblerApi(object):
- def __init__(self,server,user,passwd):
- self.server = server
- self.user = user
- self.passwd = passwd
- self.token = ''
- self.__get_token()
-
- def __call__(self, *args, **kwargs):
- self.__sync_cobbler()
- print("1223333333333333333")
- self.remote_server.logout(self.token)
-
- def end(self):
- self.remote_server.logout(self.token)
-
- def is_kickstart_in_use(self,name):
- return self.remote_server.is_kickstart_in_use(name)
-
- def is_snippets_in_use(self,name,kickstart_templates):
- snsname = os.path.basename(name)
- snsname="$SNIPPET('{}')".format(snsname)
- for ks in kickstart_templates:
- # print(ks.get("kickstart"))
- context = self.read_or_write_kickstart_template(ks.get("kickstart"),"",True)
- if snsname in context:
- return True,kickstart_templates
- return False,kickstart_templates
-
- '''
- 通过list 的格式返回每个类别的名称
- '''
- def __check_token(self):
- return self.remote_server.token_check(self.token)
-
- def __get_token(self):
- try:
- self.remote_server = xmlrpc.client.Server("http://{}/cobbler_api".format(self.server))
- self.token = self.remote_server.login(self.user, self.passwd)
- except Exception as e:
- print(e)
- return ('URL:%s no access' % self.server)
-
- def find_distros(self):
- return self.remote_server.find_distro()
-
- def find_profiles(self):
- return self.remote_server.find_profile()
-
- def find_system(self):
- return self.remote_server.find_system()
-
- '''
- 通过list 的格式返回每个名称的详细信息
- '''
- def get_distros(self,name):
- return self.remote_server.get_distro(name)
-
- def get_profiles(self,name):
- return self.remote_server.get_profile(name)
-
- def get_system(self,name):
- return self.remote_server.get_system(name)
-
- '''
- 删除
- '''
-
- # prof_id = remote_server.new_profile(token) # 创建一个新的profile 并保存
- def remove_profile(self,name):
- self.remote_server.remove_profile(name,self.token)
- self.__sync_cobbler()
-
- def remove_distros(self,name):
- self.remote_server.remove_distro(name,self.token)
- self.__sync_cobbler()
-
- def remove_system(self,name):
- print(name)
- self.remote_server.remove_system(name,self.token)
- self.__sync_cobbler()
-
- '''
- 修改
- '''
- def modify_profile(self,name,key,value):
- object_id = self.remote_server.get_profile_handle(name, self.token)
- # remote_server.modify_profile(prof_id,'name','vm_test1',token) # 修改prof_id指定的profile 名称
- # remote_server.modify_profile(prof_id,'distro','centos6.8-x86_64',token) # 也是修改prof_id的信息
- # remote_server.modify_profile(object_id, 'kickstart', '/var/lib/cobbler/kickstarts/sample_end.ks', token)
- try:
- self.remote_server.modify_profile(object_id, key, value, self.token)
- self.remote_server.save_profile(object_id, self.token) # 保存
- self.__sync_cobbler()
-
- except Exception as e:
- return e
-
- def modify_system(self,name,key,value):
- object_id = self.remote_server.get_system_handle(name, self.token)
- try:
- self.remote_server.modify_system(object_id, key, value, self.token)
- self.remote_server.save_system(object_id, self.token) # 保存
- self.__sync_cobbler()
-
- except Exception as e:
- return e
-
- def modify_distros(self,name,key,value):
- object_id = self.remote_server.get_distros_handle(name, self.token)
- try:
- self.remote_server.modify_distros(object_id, key, value, self.token)
- self.remote_server.save_distros(object_id, self.token) # 保存
- self.__sync_cobbler()
-
- except Exception as e:
- return e
-
- '''
- 获取ks和sns 的文件列表
- '''
- def get_kickstart_templates(self):
-
- kickstartlist =[]
- for ks in self.remote_server.get_kickstart_templates():
- if ks.startswith('/'):
- if self.is_kickstart_in_use(ks):
- status="in-use"
- else:
- status = "not-in-use"
- kickstartlist.append({"kickstart":ks,"status":status})
-
- return kickstartlist
-
-
- def get_snippets(self):
- snippetslist =[]
- kickstart_templates=self.get_kickstart_templates()
- for sns in self.remote_server.get_snippets():
- if sns.startswith('/'):
- status,kickstart_templates=self.is_snippets_in_use(sns,kickstart_templates)
- if status:
- status="in-use"
- else:
- status = "not-in-use"
- snippetslist.append({"snippets":sns,"status":status})
-
- return snippetslist
-
- # 同步cobbler修改后的信息,这个做任何操作后,都要必须有
- def __sync_cobbler(self):
- return self.remote_server.sync(self.token) # 同步cobbler修改后的信息,这个做任何操作后,都要必须有
-
- '''
- 填写ks模板
- # print(remote_server.read_or_write_kickstart_template('/var/lib/cobbler/kickstarts/1234.ks',False,'123\ndead\tdd\nda',token))
- 替换KS字符串如果为-1,将删除此Ks文件,条件是此ks文件已不在引用
- '''
- def read_or_write_kickstart_template(self,filename,context,read=False):
- fullfilepath = os.path.join('/var/lib/cobbler/kickstarts/',filename)
- #not self.remote_server.is_kickstart_in_use(fullfilepath) and
- if not os.path.exists(fullfilepath):
- return self.remote_server.read_or_write_kickstart_template(fullfilepath,read,context,self.token)
- else:
- return "The kickstart is exists"
-
- '''
- 填写sns模板
- # print(remote_server.read_or_write_snippet('/var/lib/cobbler/snippets/test1',False,'zhaoyong_test',token)) # 在snippgets下建立脚本文件
- '''
- def read_or_write_snippet(self,filename,context,read=False):
- fullfilepath = os.path.join('/var/lib/cobbler/snippets/',filename)
- if not os.path.exists(fullfilepath):
- return self.remote_server.read_or_write_snippet(fullfilepath,read,context,self.token)
- else:
- return "The snippet is exists"
-
- '''
- 增加新的system
- '''
- def create_or_update_system(self,name,mac,ip,profile,subnet,gateway,interface,hostname,dns,netboot_enabled,
- kickstart='/var/lib/cobbler/kickstarts/sample_end.ks',
- kops='net.ifnames=0 biosdevname=0'):
- sid = self.remote_server.new_system(self.token)
- self.remote_server.modify_system(sid,'name',name,self.token)
- self.remote_server.modify_system(sid, 'hostname', hostname, self.token)
- self.remote_server.modify_system(sid, 'gateway', gateway, self.token)
- self.remote_server.modify_system(sid, 'profile', profile, self.token)
- self.remote_server.modify_system(sid, 'name_servers', dns, self.token)
- self.remote_server.modify_system(sid, 'modify_interface', {
- "macaddress-{}".format(interface): mac.upper(),
- "ipaddress-{}".format(interface): ip,
- "gateway-{}".format(interface): gateway,
- "subnet-{}".format(interface):subnet,
- "dnsname-{}".format(interface): ip,
- "static-{}".format(interface): True,
- }, self.token)
- self.remote_server.modify_system(sid,'kickstart',kickstart,self.token)
- self.remote_server.modify_system(sid,'kopts',kops,self.token)
- self.remote_server.modify_system(sid,'netboot_enabled',netboot_enabled,self.token)
- self.remote_server.save_system(sid,self.token)
- self.__sync_cobbler()
-
- '''
- 获取system ks 定义文件
- '''
- def get_system_generate_kickstart(self,system):
- return self.remote_server.generate_kickstart('',system)
-
- '''
- 获取profile ks 定义文件
- '''
- def get_profile_generate_kickstart(self,profile):
- return self.remote_server.generate_kickstart(profile)
-
- def get_status(self):
- # print(self.remote_server.get_status('text',self.token))
- # print(self.remote_server.get_status("normal",self.token))
- return self.remote_server.get_status('json',self.token)
-
- def get_system_status(self,name):
- for ip,v in self.remote_server.get_status('json',self.token).items():
- if v[2].split(":")[1] == name:
- start = totime(v[0])
- end = ""
- if v[1] != -1:
- end = totime(v[1])
- system_name = v[2].split(":")[1]
- status = v[5]
- initcount = v[3]
- successcount = v[4]
- infos= {"starttime":start,"endtime":end,"ip":ip,
- "systemname":system_name,"status":status,
- "initcount":initcount,"successcount":successcount}
- return infos
- return False
-
-
- class init_system_api(CobblerApi):
-
- @staticmethod
- def run():
- server = '10.1.41.100'
- user = 'cobbler'
- passwd = 'cobbler'
- return CobblerApi(server,user,passwd)
-
-
- def totime(timeStamp):
- timeArray = time.localtime(timeStamp)
- otherStyleTime = time.strftime("%Y-%m-%d %H:%M:%S", timeArray)
- return otherStyleTime
-
- if __name__ == '__main__':
- time_str = time.time()
- server = '10.1.41.100'
- user = 'cobbler'
- passwd = 'cobbler'
- cobbler = CobblerApi(server,user,passwd)
- # print(cobbler.find_system())
- # print(cobbler.find_distros())
- # print(cobbler.find_profiles())
- # print(cobbler.get_system('kvm-centos7-test'))
- # cobbler.remove_system('centos-nineven')
- info=cobbler.get_system('kvm-123')
- if info == "~":
- print("不存在")
- else:
- print(info)
- # print(cobbler.remove_system('111'))
- #
- # infos = cobbler.get_system('centos-nineven')
- # print(infos.get("name"))
- # print(infos.get("profile"))
- # print(infos.get("kickstart"))
- # print(infos.get("kernel_options"))
- # for k,v in infos.get("interfaces").items():
- # print(k)
- # print(v.get("gateway"))
- # print(v.get("hostname"))
- # print(v.get("mac_address"))
- # print(v.get("netmask"))
- # print(v.get("ip_address"))
- exit()
- # print(cobbler.get_status())
- system_status = cobbler.get_status()
- for ip,v in system_status.items():
- start = totime(v[0])
- end=""
- if v[1] !=-1:
- end = totime(v[1])
- system_name = v[2]
- status = v[5]
- # v[4] 安装系统成功的次数 ,v[3] 安装次数
- print(ip,v)
- print('''
- ip: %s
- start: %s
- end: %s
- system_name: %s
- status: %s
- '''%(ip,start,end,system_name,status))
-
-
- # print(cobbler.get_system_generate_kickstart('Centos-7.2-mini-x86_64'))
- # print(cobbler.get_profiles(cobbler.get_system('centos-nineven').get("profile")))
- # print(cobbler.modify_profile('Centos-7.2-mini-x86_64','kopts','net.ifnames=0 biosdevname=0'))
- # print(cobbler.create_or_update_system("centos-nineven","00:50:56:39:E6:FE","192.168.5.82","Centos-7.2-mini-x86_64",
- # "255.255.255.0","192.168.5.1","eth0","nineven-test","114.114.114.114"))
- # print(cobbler.remove_system("centos-nineven"))