Blog

  • 做新旧命令兼容的一种方式

    将无法解析的命令
    1. catch parse异常.
    2. 错误输出直接重定向/dev/null.避免干扰output

    #!/usr/bin/env python
    
    import sys
    import os
    import subprocess
    from optparse import OptionParser
    
    class redirect_stdout_stderr(object):
        def __init__(self, stream):
            # Save the old std streams
            self.old_stream = sys.stdout
            self.old_error_stream = sys.stderr
            self.fstream = stream
    
        def __enter__(self):
            # Change the std streams to your streams when entering
            sys.stdout = self.fstream
            sys.stderr = self.fstream
    
        def __exit__(self, exc_type, exc_value, exc_traceback):
            # Change the std streams back to the original streams while exiting
            sys.stdout = self.old_stream
            sys.stderr = self.old_error_stream
    
    if __name__ == "__main__":
        usage = "mdfscli [options]"
        parser = OptionParser(usage)
        #需要兼容的旧命令
        parser.add_option("--build-info", action="store_true", dest="cmd_build_info", \
                          default=False, help="Show build information")
        newappcli = ""
        try:
            # parse command line arguments
            with redirect_stdout_stderr(open(os.devnull, 'w')):
                (options, args) = parser.parse_args()
        except:
            newappcli = "/usr/share/yourapp/newappcli %s" % (" ".join(sys.argv[1:]))
        else:
            if options.cmd_build_info:
                newappcli = "/usr/share/yourapp/newappcli --build-info"
            else:
              newappcli = "/usr/share/yourapp/newappcli %s" % (" ".join(sys.argv[1:]))
    
        cmd = subprocess.Popen(newappcli, shell=True, stdout=sys.stdout, stderr=sys.stderr, close_fds=True)
        sys.exit(cmd.wait())
    
  • virsh 虚拟机xml信息,留个记录

    virsh dumpxml domain
    
    虚拟机dumpxml例,可以参考格式

    xml
    <domain type='kvm' id='12'>
    <name>ceph-node3</name>
    <uuid>4f52f828-f538-45cb-9f02-eeb555e96020</uuid>
    <memory unit='KiB'>8388608</memory>
    <currentMemory unit='KiB'>8388608</currentMemory>
    <vcpu placement='static'>2</vcpu>
    <resource>
    <partition>/machine</partition>
    </resource>
    <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.0.0'>hvm</type>
    <boot dev='hd'/>
    </os>
    <features>
    <acpi/>
    <apic/>
    </features>
    <cpu mode='custom' match='exact' check='full'>
    <model fallback='forbid'>Haswell-IBRS</model>
    <feature policy='disable' name='hle'/>
    <feature policy='disable' name='rtm'/>
    <feature policy='require' name='hypervisor'/>
    <feature policy='require' name='xsaveopt'/>
    </cpu>
    <clock offset='utc'>
    <timer name='rtc' tickpolicy='catchup'/>
    <timer name='pit' tickpolicy='delay'/>
    <timer name='hpet' present='no'/>
    </clock>
    <on_poweroff>destroy</on_poweroff>
    <on_reboot>restart</on_reboot>
    <on_crash>destroy</on_crash>
    <pm>
    <suspend-to-mem enabled='no'/>
    <suspend-to-disk enabled='no'/>
    </pm>
    <devices>
    <emulator>/usr/libexec/qemu-kvm</emulator>
    <disk type='file' device='disk'>
    <driver name='qemu' type='qcow2'/>
    <source file='/ceph2/images/ceph_node3.qcow2'/>
    <backingStore/>
    <target dev='vda' bus='virtio'/>
    <alias name='virtio-disk0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
    </disk>
    <disk type='file' device='disk'>
    <driver name='qemu' type='qcow2' cache='none'/>
    <source file='/ceph2/images/ceph_node3_storage.qcow2'/>
    <backingStore/>
    <target dev='vdb' bus='virtio'/>
    <alias name='virtio-disk1'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
    </disk>
    <disk type='file' device='cdrom'>
    <driver name='qemu'/>
    <target dev='hda' bus='ide'/>
    <readonly/>
    <alias name='ide0-0-0'/>
    <address type='drive' controller='0' bus='0' target='0' unit='0'/>
    </disk>
    <controller type='usb' index='0' model='ich9-ehci1'>
    <alias name='usb'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x7'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci1'>
    <alias name='usb'/>
    <master startport='0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0' multifunction='on'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci2'>
    <alias name='usb'/>
    <master startport='2'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x1'/>
    </controller>
    <controller type='usb' index='0' model='ich9-uhci3'>
    <alias name='usb'/>
    <master startport='4'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x2'/>
    </controller>
    <controller type='pci' index='0' model='pci-root'>
    <alias name='pci.0'/>
    </controller>
    <controller type='ide' index='0'>
    <alias name='ide'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
    </controller>
    <controller type='virtio-serial' index='0'>
    <alias name='virtio-serial0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
    </controller>
    <interface type='bridge'>
    <mac address='52:54:00:94:b4:fe'/>
    <source bridge='br0'/>
    <target dev='vnet2'/>
    <model type='virtio'/>
    <alias name='net0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>
    <serial type='pty'>
    <source path='/dev/pts/5'/>
    <target type='isa-serial' port='0'>
    <model name='isa-serial'/>
    </target>
    <alias name='serial0'/>
    </serial>
    <console type='pty' tty='/dev/pts/5'>
    <source path='/dev/pts/5'/>
    <target type='serial' port='0'/>
    <alias name='serial0'/>
    </console>
    <channel type='unix'>
    <source mode='bind' path='/var/lib/libvirt/qemu/channel/target/domain-12-ceph-node3/org.qemu.guest_agent.0'/>
    <target type='virtio' name='org.qemu.guest_agent.0' state='connected'/>
    <alias name='channel0'/>
    <address type='virtio-serial' controller='0' bus='0' port='1'/>
    </channel>
    <input type='tablet' bus='usb'>
    <alias name='input0'/>
    <address type='usb' bus='0' port='1'/>
    </input>
    <input type='mouse' bus='ps2'>
    <alias name='input1'/>
    </input>
    <input type='keyboard' bus='ps2'>
    <alias name='input2'/>
    </input>
    <graphics type='vnc' port='5902' autoport='yes' listen='0.0.0.0'>
    <listen type='address' address='0.0.0.0'/>
    </graphics>
    <video>
    <model type='cirrus' vram='16384' heads='1' primary='yes'/>
    <alias name='video0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
    </video>
    <memballoon model='virtio'>
    <alias name='balloon0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
    </memballoon>
    <rng model='virtio'>
    <backend model='random'>/dev/urandom</backend>
    <alias name='rng0'/>
    <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'/>
    </rng>
    </devices>
    <seclabel type='dynamic' model='selinux' relabel='yes'>
    <label>system_u:system_r:svirt_t:s0:c21,c647</label>
    <imagelabel>system_u:object_r:svirt_image_t:s0:c21,c647</imagelabel>
    </seclabel>
    <seclabel type='dynamic' model='dac' relabel='yes'>
    <label>+107:+107</label>
    <imagelabel>+107:+107</imagelabel>
    </seclabel>
    </domain>

  • 使用docker安装ceph

    使用docker安装ceph

    #划分子网
    docker network create --driver bridge --subnet 172.20.0.0/16 ceph-network
    docker network ls
    docker network inspect ceph-network
    
    #用于存放ceph配置
    mkdir -p  /myceph/etc/ceph
    #创建目录代表osd
    mkdir -p  /myceph/osd/0  /myceph/osd/1  /myceph/osd/2
    
    # monitor node
    docker run -itd --name monnode --network ceph-network --ip 172.20.0.10 -e MON_NAME=monnode -e MON_IP=172.20.0.10 -v /myceph/etc/ceph:/etc/ceph ceph/mon
    
    #
    docker exec monnode ceph osd create
    docker exec monnode ceph osd create
    docker exec monnode ceph osd create
    
    #osd
    docker run -itd --name osdnode0 --network ceph-network -e CLUSTER=ceph -e WEIGHT=1.0 -e MON_NAME=monnode -e MON_IP=172.20.0.10 -v /myceph/etc/ceph:/etc/ceph -v /myceph/osd/0:/var/lib/ceph/osd/ceph-0 ceph/osd
    docker run -itd --name osdnode1 --network ceph-network -e CLUSTER=ceph -e WEIGHT=1.0 -e MON_NAME=monnode -e MON_IP=172.20.0.10 -v /myceph/etc/ceph:/etc/ceph -v /myceph/osd/1:/var/lib/ceph/osd/ceph-1 ceph/osd
    docker run -itd --name osdnode2 --network ceph-network -e CLUSTER=ceph -e WEIGHT=1.0 -e MON_NAME=monnode -e MON_IP=172.20.0.10 -v /myceph/etc/ceph:/etc/ceph -v /myceph/osd/2:/var/lib/ceph/osd/ceph-2 ceph/osd
    
    #object storage gateway
    docker run -itd --name gwnode --network ceph-network --ip 172.20.0.9 -p 9080:80 -e RGW_NAME=gwnode -v /myceph/etc/ceph:/etc/ceph ceph/radosgw
    
    docker exec monnode ceph -s
    

    基于Docker部署ceph分布式文件系统(Luminous版本)

  • 快照与备份的区别

    定义

    SNIA对快照的描述:

    A point in time copy of a defined collection of data.
    

    快照有全量快照和增量快照.我们常用的基本是增量快照(delta snapshot)

    A type of point in time copy that preserves the state of data at an instant in time,
    by storing only those blocks that are different from an already existing full copy of the data.
    

    主要特点是,快照是虚拟的拷贝而不是物理的拷贝,只有发生过修改的block才会被重写.因此如果完全没有被修改过的块遭遇破坏而导致的存储错误.快照回滚也无法修复.

    目的

    做快照,通常有2个目的:
    + 一是为了将来对于删除或损坏的文件能够进行恢复
    + 二是作为副本或备份的源端(防止快照发生物理介质性质的损坏)

    (more…)

  • 结合vmstat分析iostat输出结果

    man vmstat

    FIELD DESCRIPTION FOR VM MODE

    Procs

    • r: The number of processes waiting for run time.

      r 表示运行队列 (就是说多少个进程真的分配到CPU). 当这个值超过了CPU数目, 就会出现CPU瓶颈.

    • b: The number of processes in uninterruptible sleep.

    Memory

    • swpd: the amount of virtual memory used.
    • free: the amount of idle memory.
    • buff: the amount of memory used as buffers.
    • cache: the amount of memory used as cache.
    • inact: the amount of inactive memory. (-a option)
    • active: the amount of active memory. (-a option)

    Swap

    • si: Amount of memory swapped in from disk (/s).
    • so: Amount of memory swapped to disk (/s).

    IO

    • bi: Blocks received from a block device (blocks/s).
    • bo: Blocks sent to a block device (blocks/s).

    System

    • in: The number of interrupts per second, including the clock.
    • cs: The number of context switches per second.

    CPU

    • These are percentages of total CPU time.
    • us: Time spent running non-kernel code. (user time, including nice time)
    • sy: Time spent running kernel code. (system time)
    • id: Time spent idle. Prior to Linux 2.5.41, this includes IO-wait time.
    • wa: Time spent waiting for IO. Prior to Linux 2.5.41, included in idle.

      wa 列显示了IO等待所占用的CPU时间的百分比。这里wa的参考值为30%,如果wa超过30%,说明IO等待严重,这可能是磁盘大量随机访问造成的,也可能磁盘或者磁盘访问控制器的带宽瓶颈造成的(主要是块操作)

    • st: Time stolen from a virtual machine. Prior to Linux 2.6.11, unknown.