def single(install_list): """ 单台机器安装. """ idc = install_list["idc"] sn = install_list["sn"] _type = install_list["type"] version = install_list["version"] usage = install_list["usage"] device = install_list["device"] product = install_list["product"] cabinet = install_list["cabinet"] user_data = install_list["user_data"] message = "start to install %s." % sn logger.info(message) # 查询控制卡 ip. ip = ilo_info.ip(idc, sn) if not ip or not utils.is_valid_ip(ip): result = "failed" message = "get ilo ip failed" install_list["result"] = result install_list["message"] = message return install_list message = "get %s ilo ip: %s" % (sn, ip) logger.info(message) # 拿到密码. passwd = ilo_info.passwd(idc, ip, sn) if not passwd: result = "failed" message = "get ilo passwd failed" install_list["result"] = result install_list["message"] = message return install_list passwd = passwd.strip() message = "get %s ilo passwd: %s" % (sn, passwd) logger.info(message) # 获取 ilo 对象. oj = ilo_oper.generate(idc, ip, passwd) message = "get %s ilo object" % (sn) logger.info(message) # 检查 SN 是否一致. curr_sn = oj.get_sn() if sn != curr_sn: result = "failed" message = "check sn failed" install_list["result"] = result install_list["message"] = message return install_list message = "check %s sn consistency success" % (sn) logger.info(message) # 查询网卡名称. nic = oj.get_nic_name(device) if not nic: logger.error("cann't get nic name") result = "failed" message = "cann't get nic name" install_list["result"] = result install_list["message"] = message return install_list message = "get %s nic name: %s" % (sn, nic) logger.info(message) # 设置网卡支持 PXE 启动. if not oj.get_nic_pxeboot(nic): if not oj.setup_nic_pxeboot(nic): result = "failed" message = "setup network device to support pxe boot failed" install_list["result"] = result install_list["message"] = message return install_list message = "set %s nic pxe boot success" % sn logger.info(message) # 设置启动顺序. nic_seq = oj.get_boot_order(nic) if not oj.check_boot_order(nic_seq): if not oj.setup_boot_order(nic_seq): result = "failed" message = "can't setup right bootseq - %s" % nic_seq install_list["result"] = result install_list["message"] = message return install_list message = "set %s nic support pxe boot success" % sn logger.info(message) # 设置机器从 PXE 启动一次. if not oj.setup_pxeboot_once(): result = "failed" message = "setup pxe once boot failed" install_list["result"] = result install_list["message"] = message return install_list message = "set %s nic pxe boot once success" % sn logger.info(message) # 拷贝 pxelinux 配置文件. mac = oj.get_mac(nic) if not oj.constract_tftp(_type, version, mac): result = "failed" message = "copy pxelinux cfg failed" install_list["result"] = result install_list["message"] = message return install_list message = "copy %s pxelinux cfg success" % sn logger.info(message) # 重启. if not oj.reboot(): result = "failed" message = "restart server failed" install_list["result"] = result install_list["message"] = message return install_list message = "reboot %s success" % sn logger.info(message) # 安装信息进 redis. client.hset(sn, "idc", idc) client.hset(sn, "usage", usage) client.hset(sn, "hostname", "") client.hset(sn, "ip", "") message = "set %s's idc, usage, hostname, ip to redis success" % sn logger.info(message) # 设置 user_data, 装机之后机器会获取并执行 user_data 中的内容. if user_data is None: client_user_data.exists(sn) and client_user_data.delete(sn) else: client_user_data.set(sn, user_data) # 循环等待安装完成. timeout = 2700 interval = 30 timetotal = 0 installed = False inasset = False while timetotal < timeout: if not installed: hostname = client.hget(sn, "hostname") ip = client.hget(sn, "ip") if "" in [hostname, ip]: time.sleep(interval) timetotal += interval else: installed = True elif installed and not inasset: try: ret = server.get("sn", sn) if not isinstance(ret, dict): time.sleep(interval) timetotal += interval elif "hostname" not in ret: time.sleep(interval) timetotal += interval elif ret["hostname"] != hostname: time.sleep(interval) timetotal += interval else: inasset = True except Exception, e: message = traceback.format_exc() logger.error(message) time.sleep(interval) timetotal += interval else: break
def create_origin(name, uuid, version, vcpu, mem, os_size, data_size, ip, location, netmask, gateway, ks, bridge): """ 用传统方法创建 instance. """ # 确认 IP 是否合法. if not utils.is_valid_ip(ip): message = "ip:{ip} is illegal".format(ip=ip) logger.warning(message) raise Exception(message) # 如果没有 location, 则下载. if not os.path.isfile(location): cmd = ''' wget {url} -O {location}'''.format(url=ISO_URLS[version], location=location) utils.shell(cmd) # 创建系统盘. os_volume_path = volume.create(name, os_size) # 执行安装操作. cmd = """virt-install --name {name} --uuid {uuid} --vcpus={vcpu} --ram {mem} """\ """--disk path={os_volume_path} -localtime --accelerate """\ """--location={location} -x "ip={ip} netmask={netmask} gateway={gateway} """\ """dns={dns} dnsdomain={dnsdomain} ks={ks} console=tty0 console=ttyS0,115200n8" """\ """--nographics --network bridge={bridge} --noautoconsole &>/dev/null""".format( name=name, uuid=uuid, vcpu=vcpu, mem=mem, os_volume_path=os_volume_path, location=location, ip=ip, netmask=netmask, gateway=gateway, dns=NAMESERVER, dnsdomain=DOMAIN, ks=ks, bridge=bridge) utils.shell(cmd) # 设置自动启动. cmd = "virsh autostart {name}".format(name=name) utils.shell(cmd) # 创建数据盘, 盘的标识是 ${name}_data. data_volume = name + "_data" data_volume_path = volume.create(data_volume, data_size) # 默认也会自动增加第二块网卡. interface.add(name, "br1") # 删除一些无用配置, 不删的话起不来(第二种存储结构有问题, 第一种没问题). cmd = """sed -i '/<kernel>/d' /etc/libvirt/qemu/{name}.xml; sed -i '/<initrd>/d' /etc/libvirt/qemu/{name}.xml; sed -i '/<cmdline>/d' /etc/libvirt/qemu/{name}.xml; virsh define /etc/libvirt/qemu/{name}.xml """.format(name=name) utils.shell(cmd) # 这里是安装完成之后自动重启. check_cmd = "virsh list | grep -q {name} ".format(name=name) start_cmd = "sleep 1 && sh libs/guestfish_origin.sh {name} {uuid} && virsh start {name} && sleep 1 ".format( name=name, uuid=uuid) if utils.check_wait(check_cmd, start_cmd): logger.info("post start {name} success".format(name=name)) else: message = "post start {name} timeout".format(name=name) logger.warning(message) raise Exception(message) # 关联成 instance 的 vdb, 在装机完成之后 attach 的原因是: # 我发现在装机开始就 attach 的话, vdb 会被搞成 swap, # pvcreate 的时候就会失败. volume.attach(name, data_volume_path, "vdb")
def create_wmi(name, uuid, vcpu, mem, os_size, data_size, ip, hostname, wmi_id, netmask, gateway, bridge): """ 根据 wmi 创建 instance. 大概步骤是这样: 1. 根据 wmi_id 获取到 wmi 的信息, 数据结构类似. 2. 创建相应的系统盘和数据盘. 3. 下载对应的镜像, 覆盖掉上一步创建的盘. 4. 如果要求的 size 比 镜像中的大, 则增大空间. 5. 根据模板文件生成虚拟机配置文件, 需修改: 1). 硬盘信息; # 最麻烦 2). 网卡信息; 3). name; 4). uuid; 5). vcpu; 6). mem; 6. 定义配置文件, 修改系统镜像. 7. 启动系统. 8. 增加虚拟机机器的 DNS 记录. """ # 确认 IP 是否合法. if not utils.is_valid_ip(ip): message = "ip:{ip} is illegal".format(ip=ip) logger.warning(message) raise Exception(message) # 获取 wmi 数据. wmi_data = wmi.get(wmi_id) os_name = name os_volume_path = volume.create(os_name, os_size) data_name = name + "_data" data_volume_path = volume.create(data_name, data_size) os_url = wmi_data["os"]["url"] # 对于 qcow2 格式的系统盘, 直接 wget, 并重置大小. if volume.path_type(os_volume_path) == "qcow2": utils.wget(os_url, os_volume_path) if int(os_size.strip("G")) > int(wmi_data["os"]["size"].strip("G")): volume.resize(os_name, os_size) if int(data_size.strip("G")) > int( wmi_data["data"]["size"].strip("G")): volume.resize(data_name, data_size) # 对于 raw 格式的系统盘, 不能使用 wget. # 一种选择是使用 qemu-img convert -O raw 命令, # 但是会有系统盘大小的数据写入, 给 IO 造成很大压力. # 这里我使用 分区表 的方式来减少 IO. if volume.path_type(os_volume_path) == "raw": storage.restore_rawos_from_qcow2_image(os_volume_path, wmi_data) # 数据盘初始化. init_data_volume_cmd = """virt-format -a {data_volume_path} --lvm=/dev/datavg/home --filesystem=ext4""".format( data_volume_path=data_volume_path) try: utils.shell(init_data_volume_cmd) except Exception, e: utils.shell("yum -y update qemu-kvm") utils.shell(init_data_volume_cmd)
def single(check_list): """ 检查是否能够正常安装. """ idc = check_list["idc"] sn = check_list["sn"] device = check_list["device"] # 查询控制卡 ip. ip = ilo_info.ip(idc, sn) if ip == False or utils.is_valid_ip(ip) == False: result = "failed" message = "get ilo ip failed" check_list["result"] = result check_list["message"] = message return check_list # 拿到密码. passwd = ilo_info.passwd(idc, ip, sn) if passwd == False: result = "failed" message = "get ilo passwd failed" check_list["result"] = result check_list["message"] = message return check_list passwd = passwd.strip() # 获取 ilo 对象. oj = ilo_oper.generate(idc, ip, passwd) # 检查 SN 是否一致. curr_sn = oj.get_sn() if sn != curr_sn: result = "failed" message = "check sn failed" check_list["result"] = result check_list["message"] = message return check_list # 查询网卡名称. nic = oj.get_nic_name(device) if not nic: logger.error("cann't get nic name") result = "failed" message = "cann't get nic name" check_list["result"] = result check_list["message"] = message return check_list # 设置网卡支持 PXE 启动. if not oj.get_nic_pxeboot(nic): if not oj.setup_nic_pxeboot(nic): result = "failed" message = "setup network device to support pxe boot failed" check_list["result"] = result check_list["message"] = message return check_list # 设置启动顺序. nic_seq = oj.get_boot_order(nic) if not oj.check_boot_order(nic_seq): if not oj.setup_boot_order(nic_seq): result = "failed" message = "can't setup right bootseq - %s" % nic_seq check_list["result"] = result check_list["message"] = message return check_list logger.info("%s(%s) check install success ", sn, ip) result = "success" message = "check success" check_list["result"] = result check_list["message"] = message return check_list