コード例 #1
0
def check_cinder_volume_driver(config):
    version = get_latest_driver_version(TAGS)
    need_version = version.strip("v")
    loc = detect_cinder_install()
    dfile = os.path.join(loc, "volume/drivers/datera/datera_iscsi.py")
    if not os.path.exists(dfile):
        errloc = os.path.join(loc, "volume/drivers")
        return ff(
            "Couldn't detect Datera Cinder driver install at "
            "{}".format(errloc), "680E61DB")
    version = None
    with io.open(dfile, 'r') as f:
        for line in f:
            version = VERSION_RE.match(line)
            if version:
                version = version.group(1)
                break
    if not version:
        return ff(
            "No version detected for Datera Cinder driver at "
            "{}".format(dfile), "A37FD778")
    if version != need_version:
        return ff(
            "Cinder Driver version mismatch, have: {}, want: "
            "{}".format(version, need_version), "5B6EFC71")
コード例 #2
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_sysctl(config):
    vprint("Checking various sysctl settings")
    settings = sorted([
        ("net.ipv4.tcp_timestamps", "0", "F0D7A1AD"),
        ("net.ipv4.tcp_sack", "1", "7A9AB850"),
        ("net.core.netdev_max_backlog", "250000", "7656C46C"),
        ("net.core.somaxconn", "1024", "34A7B822"),
        ("net.core.rmem_max", "16777216", "4C4B3F0B"),
        ("net.core.wmem_max", "16777216", "7F8479C2"),
        ("net.core.rmem_default", "8388608", "FBCA17D5"),
        ("net.core.wmem_default", "8388608", "68191DE5"),
        ("net.core.optmem_max", "8388608", "8FA26A66"),
        ("net.ipv4.tcp_rmem", "\"4096 87380 16777216\"", "2A6057BD"),
        ("net.ipv4.tcp_wmem", "\"4096 65536 16777216\"", "CD37F436"),
        ("net.ipv4.tcp_low_latency", "1", "6BE2899E"),
        ("net.ipv4.tcp_fin_timeout", "15", "59FD5DF7"),
        ("net.ipv4.tcp_syncookies", "1", "01C594E7"),
        ("net.ipv4.tcp_adv_win_scale", "1", "1F523B04"),
        ("net.ipv4.tcp_window_scaling", "1", "A8A6F381"),
        ("net.ipv4.tcp_max_syn_backlog", "8192", "2862CB28"),
        ("net.ipv4.tcp_tw_reuse", "1", "989229FC"),
        ("net.ipv4.tcp_synack_retries", "2", "55EF997B")
    ])
    for setting, value, code in settings:
        found = exe("sysctl --values {}".format(setting)).strip()
        found = found.strip().strip("\"").split()
        value = value.strip().strip("\"").split()
        if len(found) == 1:
            found = found[0]
        if len(value) == 1:
            value = value[0]
        if found != value:
            ff("{}={} is not set. Found: {}".format(setting, value, found),
               code)
コード例 #3
0
def generate_silkscreen_female(
    lines: List[str],
    category: str,
    kind: str,
    variant: str,
    pin_count: int,
    top_offset: float,
) -> None:
    uuid_polygon = uuid(category, kind, variant, 'polygon-contour')

    lines.append('  (polygon {} (layer top_placement)'.format(uuid_polygon))
    lines.append(
        '   (width {}) (fill false) (grab_area true)'.format(line_width))
    y_max, y_min = get_rectangle_bounds(pin_count, spacing, top_offset, False)
    lines.append('   (vertex (position -1.27 {}) (angle 0.0))'.format(
        ff(y_max)))
    lines.append('   (vertex (position 1.27 {}) (angle 0.0))'.format(
        ff(y_max)))
    lines.append('   (vertex (position 1.27 {}) (angle 0.0))'.format(
        ff(y_min)))
    lines.append('   (vertex (position -1.27 {}) (angle 0.0))'.format(
        ff(y_min)))
    lines.append('   (vertex (position -1.27 {}) (angle 0.0))'.format(
        ff(y_max)))
    lines.append('  )')
コード例 #4
0
def check_cinder_image_cache_conf(config):
    with io.open(ETC, 'r') as f:
        section = None
        for line in f:
            section = ETC_SECTION_RE.match(line)
            if section:
                break
        if not section:
            return ff(
                "[datera] section missing from "
                "/etc/cinder/cinder.conf", "525BAAB0")
        cache_check = False
        vtype_check = False
        for line in f:
            if 'datera_enable_image_cache' in line and 'True' in line:
                cache_check = True
            if ('datera_image_cache_volume_type_id' in line
                    and UUID4_STR_RE.search(line)):
                vtype_check = True
        if not cache_check:
            ff("datera_enable_image_cache not set in cinder.conf", "C5B86514")
        if not vtype_check:
            ff(
                "datera_image_cache_volume_type_id is not set to a valid volume"
                " type id in cinder.conf", "B845D5B1")
コード例 #5
0
ファイル: check_glance.py プロジェクト: sscargal/ddct
def check_glance_driver(config):
    version = get_latest_driver_version(TAGS)
    need_version = version.strip("v")
    loc = detect_glance_install()
    if not loc:
        return ff("Could not detect Glance install location", "6515ADB8")
    dfile = os.path.join(loc, "_drivers/datera.py")
    if not os.path.exists(dfile):
        errloc = os.path.join(loc, "_drivers")
        return ff(
            "Couldn't detect Datera Glance driver install at "
            "{}".format(errloc), "DD51CEC9")
    version = None
    with io.open(dfile, 'r') as f:
        for line in f:
            version = VERSION_RE.match(line)
            if version:
                version = version.group(1)
                break
    if not version:
        return ff(
            "No version detected for Datera Glance driver at "
            "{}".format(dfile), "75A8A315")
    if version != need_version:
        return ff(
            "Glance Driver version mismatch, have: {}, want: "
            "{}".format(version, need_version), "B65FD598")
    entry = find_entry_points_file()
    if not entry:
        return ff("Could not find entry_points.txt file for glance_store",
                  "842A4DB1")
    efound = None
    with io.open(entry) as f:
        for line in f:
            if 'datera' in line:
                efound = line
                break
    if not efound:
        return ff("Could not find 'datera' entry in {}".format(entry),
                  "22DC6275")
    k, v = efound.split("=")
    if k.strip() != 'datera':
        return ff("entry_points.txt entry malformed", "3F9F67BF")
    if v.strip() != 'glance_store._drivers.datera:Store':
        return ff("entry_points.txt entry malformed", "3F9F67BF")

    backend = os.path.join(loc, "backend.py")
    bfound = False
    with io.open(backend) as f:
        for line in f:
            if 'datera' in line:
                bfound = True
                break
            if 'class Indexable' in line:
                break
    if not bfound:
        ff(
            "'datera' has not been added to the 'default_store' StrOpt's "
            "'choices' parameter", "C521E039")
コード例 #6
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def vip1_check(config):
    vip1 = config["vip1_ip"]
    if not exe_check("ping -c 2 -W 1 {}".format(vip1), err=False):
        ff("Could not ping vip1 ip {}".format(vip1), "1827147B", fix=NET_FIX)
    timeout = 5
    while not exe_check(
            "ip neigh show | grep {} | grep REACHABLE".format(vip1)):
        timeout -= 1
        time.sleep(1)
        if timeout < 0:
            wf("Arp state for vip1 [{}] is not 'REACHABLE'".format(vip1),
               "3C33D70D")
            break
コード例 #7
0
ファイル: check_docker.py プロジェクト: sscargal/ddct
def check_docker_config(config):
    if not os.path.exists(CONFIG_FILE):
        return ff("Missing Datera config file at '/root/.datera-config-file'",
                  "A433E6C6")
    dconfig = None
    with io.open(CONFIG_FILE) as f:
        try:
            dconfig = json.loads(f.read())
        except json.JSONDecodeError:
            return ff("Malformed config file, not valid JSON", "AA27965F")
    for key in ("datera-cluster", "username", "password", "debug", "os-user",
                "tenant"):
        if key not in dconfig:
            ff("Config missing {} key".format(key), "945148B0")
コード例 #8
0
ファイル: check_docker.py プロジェクト: sscargal/ddct
def check_docker_volume(config):
    vprint("Checking docker volume driver")
    if not exe_check("docker ps >/dev/null 2>&1"):
        return ff("Docker is not installed", "42BAAC76")
    if exe_check("docker plugin ls | grep {}".format(PLUGIN)):
        return ff("Datera Docker plugin is not installed", "6C531C5D")
    plugin = exe("docker plugin ls | grev -v DESCRIPTION | "
                 "grep {}".format(PLUGIN))
    if len(plugin.strip().split('\n')) > 1:
        wf("More than one version of Datera docker driver installed",
           "B3BF691D")
    if 'enabled' not in plugin or 'disabled' in plugin:
        ff("Datera docker plugin is not enabled")
    test_name = "ddct-test1"
    if not exe_check(
            "docker volume create -d {} --name {} --opt replica=1 --opt "
            "size=1".format(PLUGIN, test_name)):
        return ff("Could not create a volume with the Datera Docker plugin",
                  "621A6F51")
    api = config['api']
    try:
        api.app_instances.get(test_name)
    except ApiNotFoundError:
        return ff("Docker volume {} did not create on the Datera backend"
                  "".format(test_name), "B106D1CD")
    if not exe_check("docker volume rm {}".format(test_name)):
        ff("Could not delete Docker volume {}".format(test_name), "AF3DB8B3")
コード例 #9
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_irq(config):
    vprint("Checking irqbalance settings, (should be turned off)")
    if not exe_check("which systemctl"):
        if not exe_check(
                "service irqbalance status | "
                "grep 'Active: active'", err=True):
            fix = "service irqbalance stop"
            return ff("irqbalance is active", "B19D9FF1", fix=fix)
    else:
        if not exe_check(
                "systemctl status irqbalance | "
                "grep 'Active: active'", err=True):
            fix = "systemctl stop irqbalance && systemctl disable irqbalance"
            return ff("irqbalance is active", "B19D9FF1", fix=fix)
コード例 #10
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_udev(config):
    vprint("Checking udev rules config")
    frules = "/etc/udev/rules.d/99-iscsi-luns.rules"
    if not os.path.exists(frules):
        fix = "A copy of the udev rules are available from: {}".format(
            UDEV_URL)
        ff("Datera udev rules are not installed", "1C8F2E07", fix=fix)
    snum = "/sbin/fetch_device_serial_no.sh"
    if not os.path.exists(snum):
        fix = ("A copy of fetch_device_serial_no.sh is available at: "
               "{}".format(FETCH_SO_URL))
        ff("fetch_device_serial_no.sh is missing from /sbin",
           "6D03F50B",
           fix=fix)
コード例 #11
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def vip2_check(config):
    vip2 = config.get("vip2_ip")
    if not vip2:
        wf("No vip2_ip found", "16EB208B")
        return
    if vip2 and not exe_check("ping -c 2 -W 1 {}".format(vip2), err=False):
        ff("Could not ping vip2 ip {}".format(vip2), "3D76CE5A", fix=NET_FIX)
    timeout = 5
    while not exe_check(
            "ip neigh show | grep {} | grep REACHABLE".format(vip2)):
        timeout -= 1
        time.sleep(1)
        if timeout < 0:
            wf("Arp state for vip2 [{}] is not 'REACHABLE'".format(vip2),
               "4F6B8D91")
            break
コード例 #12
0
 def _draw(config: DfnConfig, uuid: Callable[[str], str],
           lines: List[str]) -> None:
     lines.append('  (circle {} (layer top_documentation)'.format(
         uuid('hole-circle-doc')))
     lines.append(
         '   (width 0.1) (fill false) (grab_area false) (diameter {}) (position 0.0 0.0)'
         .format(ff(diameter)))
     lines.append('  )')
コード例 #13
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def mgmt_check(config):
    mgmt = config["mgmt_ip"]
    if not exe_check("ping -c 2 -W 1 {}".format(mgmt), err=False):
        ff("Could not ping management ip {}".format(mgmt),
           "65FC68BB",
           fix=NET_FIX)
    timeout = 5
    while not exe_check(
            "ip neigh show | grep {} | grep REACHABLE".format(mgmt)):
        timeout -= 1
        time.sleep(1)
        if timeout < 0:
            fix = "Check the connection to {}".format(mgmt)
            wf("Arp state for mgmt [{}] is not 'REACHABLE'".format(mgmt),
               "BF6A912A",
               fix=fix)
            break
コード例 #14
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_cpufreq(config):
    vprint("Checking cpufreq settings")
    if not exe_check("which cpupower"):
        if get_os() == UBUNTU:
            version = exe("uname -r").strip()
            fix = "apt-get install linux-tools-{}".format(version)
        else:
            # RHEL puts this stuff in kernel-tools
            fix = "yum install kernel-tools"
        return ff("cpupower is not installed", "20CEE732", fix=fix)
    if not exe_check(
            "cpupower frequency-info --governors | "
            "grep performance", err=False):
        fix = ("No-fix -- if this system is a VM governors might not be "
               "available and this check can be ignored")
        return ff("No 'performance' governor found for system",
                  "333FBD45",
                  fix=fix)
コード例 #15
0
ファイル: mtu.py プロジェクト: sscargal/ddct
def check_mtu_l3(ip, config):
    """
    We just care that the packet gets there.  Fragmentation is gonna happen
    with L3 routing.
    """
    vprint("Performing L3 MTU check")
    sif = get_interface_for_ip(ip)
    if not sif:
        return ff(
            "Couldn't find interface with network matching ip {}"
            "".format(ip), "710BFC7E")
    # Ping check
    if not exe_check("ping -s 32000 -c 2 -W 1 {}".format(ip)):
        if not exe_check("ping -c 2 -W 1 {}".format(ip)):
            return ff("Could not ping interface [{}]".format(ip), "EC2D3621")
        ff(
            "Could not ping interface [{}] with large (32k) packet size, packet"
            "fragmentation may not be working correctly.".format(ip),
            "A4CA0D72")
コード例 #16
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_block_devices(config):
    vprint("Checking block device settings")
    grub = "/etc/default/grub"
    if not os.path.exists(grub):
        return ff("Could not find default grub file at {}".format(grub),
                  "6F7B6A25")
    with io.open(grub, "r") as f:
        data = f.readlines()
        line = filter(lambda x: x.startswith("GRUB_CMDLINE_LINUX_DEFAULT="),
                      data)
        line2 = filter(lambda x: x.startswith("GRUB_CMDLINE_LINUX="), data)
        if len(line) != 1 and len(line2) != 1:
            return ff(
                "GRUB_CMDLINE_LINUX_DEFAULT and GRUB_CMDLINE_LINUX are"
                " missing from GRUB file", "A65B6D97")
        if ((len(line) > 0 and "elevator=noop" not in line[0])
                and (len(line2) > 0 and "elevator=noop" not in line2[0])):
            fix = ("Add 'elevator=noop' to /etc/default/grub in the "
                   "'GRUB_CMDLINE_LINUX_DEFAULT' line")
            return ff("Scheduler is not set to noop", "47BB5083", fix=fix)
コード例 #17
0
ファイル: check_k8s_csi.py プロジェクト: sscargal/ddct
def check_csi_yaml(config):
    yml = config.get('csi-yaml')
    if not yml:
        ff(
            "In order to perform the CSI yaml check you must provide the yaml"
            " file location with the '--csi-yaml' argument", "1C84788A")
        return
    entries = get_k8s_yaml(yml)
    nodes = entries['nodes']
    controller = entries['controller']

    for k1, k2, fc1, fc2 in (('DAT_MGMT', 'mgmt_ip', "A4CEE995", "D520EF2E"),
                             ('DAT_USER', 'username', "4FAC9E6F", "FA4AD639"),
                             ('DAT_PASS', 'password', "3F37E06E", "F6B7A8FE")):

        if nodes[k1] != config[k2]:
            ff(
                "CSI 'node' service environment variable {} does not match "
                "UDC config.  [{} != {}]".format(k1, nodes[k1], config[k2]),
                fc1)
        if controller[k1] != config[k2]:
            ff(
                "CSI 'controller' service environment variable DAT_MGMT does "
                "not match UDC config.  [{} != {}]".format(
                    k1, controller[k1], config[k2]), fc2)
コード例 #18
0
def generate_silkscreen_male(
    lines: List[str],
    category: str,
    kind: str,
    variant: str,
    pin_count: int,
    top_offset: float,
) -> None:
    uuid_polygon = uuid(category, kind, variant, 'polygon-contour')

    # Start in top right corner, go around the pads clockwise
    lines.append('  (polygon {} (layer top_placement)'.format(uuid_polygon))
    lines.append(
        '   (width {}) (fill false) (grab_area true)'.format(line_width))
    # Down on the right
    for pin in range(1, pin_count + 1):
        y = get_y(pin, pin_count, spacing, False)
        lines.append('   (vertex (position 1.27 {}) (angle 0.0))'.format(
            ff(y + 1)))
        lines.append('   (vertex (position 1.27 {}) (angle 0.0))'.format(
            ff(y - 1)))
        lines.append('   (vertex (position 1.0 {}) (angle 0.0))'.format(
            ff(y - 1.27)))
    # Up on the left
    for pin in range(pin_count, 0, -1):
        y = get_y(pin, pin_count, spacing, False)
        lines.append('   (vertex (position -1.0 {}) (angle 0.0))'.format(
            ff(y - 1.27)))
        lines.append('   (vertex (position -1.27 {}) (angle 0.0))'.format(
            ff(y - 1)))
        lines.append('   (vertex (position -1.27 {}) (angle 0.0))'.format(
            ff(y + 1)))
    # Back to start
    top_y = get_y(1, pin_count, spacing, False) + spacing / 2
    lines.append('   (vertex (position -1.0 {}) (angle 0.0))'.format(
        ff(top_y)))
    lines.append('   (vertex (position 1.0 {}) (angle 0.0))'.format(ff(top_y)))
    lines.append('   (vertex (position 1.27 {}) (angle 0.0))'.format(
        ff(top_y - 0.27)))
    lines.append('  )')
コード例 #19
0
ファイル: mtu.py プロジェクト: sscargal/ddct
def check_mtu_normal(name, ip, config):
    vprint("Performing MTU check")
    cname = iface_dict[name]
    sif = get_interface_for_ip(ip)
    if not sif:
        return ff(
            "Couldn't find interface with network matching ip {}"
            "".format(ip), "710BFC7E")
    try:
        match = MTU_RE.match(exe("ip ad show {} | grep mtu".format(sif)))
    except subprocess.CalledProcessError:
        return ff("Couldn't find client {} interface MTU".format(name),
                  "CBF8CC4C")
    if not match:
        return ff("Couldn't find client {} interface MTU".format(name),
                  "CBF8CC4C")
    local_mtu = match.groups(1)[0]

    cluster_mtu = None
    api = config['api']
    if name == "MGMT":
        cluster_mtu = api.system.network.mgmt_vip.get(
        )['network_paths'][0]['mtu']
    elif name == "VIP1":
        cluster_mtu = api.system.network.get(
        )['access_vip']['network_paths'][0]['mtu']
    elif name == "VIP2":
        cluster_mtu = api.system.network.get(
        )['access_vip']['network_paths'][0]['mtu']
    if not cluster_mtu:
        return ff("Couldn't find cluster {} interface MTU".format(cname),
                  "057AF23D")
    if str(local_mtu) != str(cluster_mtu):
        ff(
            "Local interface {} MTU does not match cluster {} interface MTU "
            "[{} != {}]".format(sif, cname, local_mtu, cluster_mtu),
            "D7F667BC")
    # Ping check
    if not exe_check("ping -s 32000 -c 2 -W 1 {}".format(ip)):
        ff(
            "Could not ping interface with large (32k) packet size, packet "
            "fragmentation may not be working correctly", "A4CA0D72")
コード例 #20
0
def check_multipath(config):
    vprint("Checking multipath settings")
    if not exe_check("which multipath", err=False):
        ff("Multipath binary could not be found, is it installed?", "2D18685C")
    if not exe_check("which systemctl"):
        if not exe_check("service multipathd status | grep 'Active: active'",
                         err=False):
            fix = "service multipathd start"
            ff("multipathd not enabled", "541C10BF", fix=fix)
    else:
        if not exe_check("systemctl status multipathd | grep 'Active: active'",
                         err=False):
            fix = "systemctl start multipathd"
            ff("multipathd not enabled", "541C10BF", fix=fix)
コード例 #21
0
ファイル: checkers.py プロジェクト: sscargal/ddct
def check_arp(config):
    vprint("Checking ARP settings")
    if not exe_check(
            "sysctl --all 2>/dev/null | "
            "grep 'net.ipv4.conf.all.arp_announce = 2'",
            err=False):
        fix = "sysctl net.ipv4.conf.all.arp_announce=2"
        ff("net.ipv4.conf.all.arp_announce != 2 in sysctl",
           "9000C3B6",
           fix=fix)
    if not exe_check(
            "sysctl --all 2>/dev/null | "
            "grep 'net.ipv4.conf.all.arp_ignore = 1'",
            err=False):
        fix = "sysctl net.ipv4.conf.all.arp_ignore=1"
        ff("net.ipv4.conf.all.arp_ignore != 1 in sysctl", "BDB4D5D8", fix=fix)
    gcf = "/proc/sys/net/ipv4/route/gc_interval"
    gc = int(exe("cat {}".format(gcf)))
    if gc != 5:
        fix = "echo 5 > {}".format(gcf)
        ff("{} is currently set to {}".format(gcf, gc), "A06CD19F", fix=fix)
コード例 #22
0
        def add_footprint_variant(key: str, name: str, pad_size: Tuple[float,
                                                                       float]):
            uuid_footprint = _uuid('footprint-{}'.format(key))
            uuid_silkscreen = _uuid('polygon-silkscreen-{}'.format(key))
            uuid_pin1_dot = _uuid('pin1-dot-silkscreen-{}'.format(key))
            uuid_outline = _uuid('polygon-outline-{}'.format(key))
            uuid_text_name = _uuid('text-name-{}'.format(key))
            uuid_text_value = _uuid('text-value-{}'.format(key))

            lines.append(' (footprint {}'.format(uuid_footprint))
            lines.append('  (name "{}")'.format(name))
            lines.append('  (description "")')

            # Pads
            pad_x_offset = float(width) / 2
            for p in range(1, pin_count // 2 + 1):
                # Down on the left
                y = get_y(p, pin_count // 2, spacing, False)
                shape = 'rect' if p == 1 else 'round'
                pad_uuid = uuid_pads[p - 1]
                lines.append('  (pad {} (side tht) (shape {})'.format(
                    pad_uuid, shape))
                lines.append(
                    '   (position {} {}) (rotation 0.0) (size {} {}) (drill {})'
                    .format(
                        ff(-pad_x_offset),
                        ff(y),
                        pad_size[0],
                        pad_size[1],
                        drill_diameter,
                    ))
                lines.append('  )')
            for p in range(1, pin_count // 2 + 1):
                # Up on the right
                y = -get_y(p, pin_count // 2, spacing, False)
                shape = 'round'
                pad_uuid = uuid_pads[p + pin_count // 2 - 1]
                lines.append('  (pad {} (side tht) (shape {})'.format(
                    pad_uuid, shape))
                lines.append(
                    '   (position {} {}) (rotation 0.0) (size {} {}) (drill {})'
                    .format(
                        ff(pad_x_offset),
                        ff(y),
                        pad_size[0],
                        pad_size[1],
                        drill_diameter,
                    ))
                lines.append('  )')

            # Silkscreen: Rectangle
            lines.append(
                '  (polygon {} (layer top_placement)'.format(uuid_silkscreen))
            lines.append('   (width {}) (fill false) (grab_area false)'.format(
                line_width))
            y_max, y_min = get_rectangle_bounds(pin_count // 2, spacing,
                                                top_offset, False)
            silkscreen_x_offset = pad_x_offset - pad_size[0] / 2 \
                                - silkscreen_offset - line_width / 2
            sxo = ff(silkscreen_x_offset)  # Used for shorter lines below :)
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                sxo, ff(y_max)))  # NW
            lines.append('   (vertex (position -{} {}) (angle 180.0))'.format(
                ff(silkscreen_x_offset / 3),
                ff(y_max),
            ))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                ff(silkscreen_x_offset / 3),
                ff(y_max),
            ))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                sxo, ff(y_max)))  # NE
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                sxo, ff(y_min)))  # SE
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                sxo, ff(y_min)))  # SW
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                sxo, ff(y_max)))  # NW
            lines.append('  )')

            # Documentation
            # TODO: The code below is almost identical to the silkscreen, code could be reused
            lines.append(
                '  (polygon {} (layer top_documentation)'.format(uuid_outline))
            lines.append('   (width {}) (fill false) (grab_area true)'.format(
                line_width))
            y_max, y_min = get_rectangle_bounds(pin_count // 2, spacing,
                                                top_offset, False)
            outline_x_offset = pad_x_offset - pin_package_offset
            oxo = ff(outline_x_offset)  # Used for shorter lines below :)
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                oxo, ff(y_max)))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                oxo, ff(y_max)))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                oxo, ff(y_min)))
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                oxo, ff(y_min)))
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                oxo, ff(y_max)))
            lines.append('  )')

            # Silkscreen: Pin 1 dot
            pin1_dot_diameter = float(width) / 7.62
            lines.append(
                '  (circle {} (layer top_placement)'.format(uuid_pin1_dot))
            lines.append('   (width 0.0) (fill true) (grab_area false) '
                         '(diameter {}) (position -{} {})'.format(
                             ff(pin1_dot_diameter),
                             ff(silkscreen_x_offset - pin1_dot_diameter),
                             ff(y_max - pin1_dot_diameter),
                         ))
            lines.append('  )')

            # Labels
            y_max, y_min = get_rectangle_bounds(pin_count // 2, spacing,
                                                top_offset + 1.27, False)
            text_attrs = '(height {}) (stroke_width 0.2) ' \
                         '(letter_spacing auto) (line_spacing auto)'.format(pkg_text_height)
            lines.append(
                '  (stroke_text {} (layer top_names)'.format(uuid_text_name))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center bottom) (position 0.0 {}) (rotation 0.0)'.
                format(ff(y_max), ))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{NAME}}")')
            lines.append('  )')
            lines.append(
                '  (stroke_text {} (layer top_values)'.format(uuid_text_value))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center top) (position 0.0 {}) (rotation 0.0)'.
                format(ff(y_min), ))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{VALUE}}")')
            lines.append('  )')

            lines.append(' )')
コード例 #23
0
ファイル: check_glance.py プロジェクト: sscargal/ddct
def check_glance_conf(config):
    pass
    section = None
    with io.open(ETC, 'r') as f:
        for line in f:
            default = ETC_DEFAULT_RE.match(line)
            if default:
                break
        if not default:
            ff("[DEFAULT] section missing from {}".format(ETC), "228241A8")
        for line in f:
            section = ETC_SECTION_RE.match(line)
            if section:
                break
        if not section:
            return ff("[glance_store] section missing from {}".format(ETC),
                      "AFCBBDD7")
        dsection = []
        section_match = re.compile(r"^\[.*\]")
        for line in f:
            if section_match.match(line):
                break
            dsection.append(line)

        ip = config['mgmt_ip']
        user = config['username']
        passwd = config['password']

        san_check = False
        user_check = False
        pass_check = False
        stores_check = False
        default_check = False

        for line in dsection:
            if line.startswith("stores"):
                stores_check = True
                if "datera" not in line:
                    ff("datera is not set under 'stores' in {}".format(ETC),
                       "0D862946")
            if line.startswith("default_store"):
                default_check = True
                if "datera" not in line:
                    wf("datera is not set as default_store in {}".format(ETC),
                       "B74CEBC3")
            if line.startswith("datera_san_ip"):
                san_check = True
                if line.split("=")[-1].strip() != ip:
                    ff("datera_san_ip doesn't match mgmt ip", "2330CACB")
            if line.startswith("datera_san_login"):
                user_check = True
                if line.split("=")[-1].strip() != user:
                    ff("datera_san_login doesn't match username", "E9F02293")
            if line.startswith("datera_san_password"):
                pass_check = True
                if line.split("=")[-1].strip() != passwd:
                    ff("datera_san_password doesn't match password",
                       "4B16C4F7")

        if not stores_check:
            ff("'stores' entry not found under [glance_store]", "11F30DCF")
        if not default_check:
            ff("'default_store' entry not found under [glance_store]",
               "540C3008")
        if not san_check:
            ff("'datera_san_ip' entry not found under [glance_store]",
               "42481C71")
        if not user_check:
            ff("'datera_san_login' entry not found under [glance_store]",
               "6E281004")
        if not pass_check:
            ff("'datera_san_password' entry not found under [glance_store]",
               "F5DEC8B1")
コード例 #24
0
def generate_pkg(
    dirpath: str,
    author: str,
    name: str,
    name_lower: str,
    kind: str,
    pkgcat: str,
    keywords: str,
    min_pads: int,
    max_pads: int,
    top_offset: float,
    pad_drills: Iterable[float],
    generate_silkscreen: Callable[[List[str], str, str, str, int, float],
                                  None],
    create_date: Optional[str],
):
    category = 'pkg'
    for i in range(min_pads, max_pads + 1):
        for drill in pad_drills:
            lines = []

            variant = '1x{}-D{:.1f}'.format(i, drill)

            def _uuid(identifier):
                return uuid(category, kind, variant, identifier)

            uuid_pkg = _uuid('pkg')
            uuid_pads = [_uuid('pad-{}'.format(p)) for p in range(i)]
            uuid_footprint = _uuid('footprint-default')
            uuid_text_name = _uuid('text-name')
            uuid_text_value = _uuid('text-value')

            # General info
            lines.append('(librepcb_package {}'.format(uuid_pkg))
            lines.append(' (name "{} 1x{} ⌀{:.1f}mm")'.format(name, i, drill))
            lines.append(' (description "A 1x{} {} with {}mm pin spacing '
                         'and {:.1f}mm drill holes.\\n\\n'
                         'Generated with {}")'.format(i, name_lower, spacing,
                                                      drill, generator))
            lines.append(' (keywords "connector, 1x{}, d{:.1f}, {}")'.format(
                i, drill, keywords))
            lines.append(' (author "{}")'.format(author))
            lines.append(' (version "0.1")')
            lines.append(' (created {})'.format(create_date or now()))
            lines.append(' (deprecated false)')
            lines.append(' (category {})'.format(pkgcat))
            for j in range(1, i + 1):
                lines.append(' (pad {} (name "{}"))'.format(
                    uuid_pads[j - 1], j))
            lines.append(' (footprint {}'.format(uuid_footprint))
            lines.append('  (name "default")')
            lines.append('  (description "")')

            # Pads
            for j in range(1, i + 1):
                y = get_y(j, i, spacing, False)
                shape = 'rect' if j == 1 else 'round'
                lines.append('  (pad {} (side tht) (shape {})'.format(
                    uuid_pads[j - 1], shape))
                lines.append(
                    '   (position 0.0 {}) (rotation 0.0) (size {} {}) (drill {})'
                    .format(
                        y,
                        pad_size[0],
                        pad_size[1],
                        drill,
                    ))
                lines.append('  )')

            # Silkscreen
            generate_silkscreen(lines, category, kind, variant, i, top_offset)

            # Labels
            y_max, y_min = get_rectangle_bounds(i, spacing, top_offset + 1.27,
                                                False)
            text_attrs = '(height {}) (stroke_width 0.2) ' \
                         '(letter_spacing auto) (line_spacing auto)'.format(pkg_text_height)
            lines.append(
                '  (stroke_text {} (layer top_names)'.format(uuid_text_name))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center bottom) (position 0.0 {}) (rotation 0.0)'.
                format(ff(y_max), ))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{NAME}}")')
            lines.append('  )')
            lines.append(
                '  (stroke_text {} (layer top_values)'.format(uuid_text_value))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center top) (position 0.0 {}) (rotation 0.0)'.
                format(ff(y_min), ))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{VALUE}}")')
            lines.append('  )')

            lines.append(' )')
            lines.append(')')

            pkg_dir_path = path.join(dirpath, uuid_pkg)
            if not (path.exists(pkg_dir_path) and path.isdir(pkg_dir_path)):
                makedirs(pkg_dir_path)
            with open(path.join(pkg_dir_path, '.librepcb-pkg'), 'w') as f:
                f.write('0.1\n')
            with open(path.join(pkg_dir_path, 'package.lp'), 'w') as f:
                f.write('\n'.join(lines))
                f.write('\n')

            print('1x{} {} ⌀{:.1f}mm: Wrote package {}'.format(
                i, kind, drill, uuid_pkg))
コード例 #25
0
def generate_sym(
    dirpath: str,
    author: str,
    name: str,
    name_lower: str,
    kind: str,
    cmpcat: str,
    keywords: str,
    min_pads: int,
    max_pads: int,
    create_date: Optional[str],
):
    category = 'sym'
    for i in range(min_pads, max_pads + 1):
        lines = []

        variant = '1x{}'.format(i)

        def _uuid(identifier):
            return uuid(category, kind, variant, identifier)

        uuid_sym = _uuid('sym')
        uuid_pins = [_uuid('pin-{}'.format(p)) for p in range(i)]
        uuid_polygon = _uuid('polygon-contour')
        uuid_decoration = _uuid('polygon-decoration')
        uuid_text_name = _uuid('text-name')
        uuid_text_value = _uuid('text-value')

        # General info
        lines.append('(librepcb_symbol {}'.format(uuid_sym))
        lines.append(' (name "{} 1x{}")'.format(name, i))
        lines.append(' (description "A 1x{} {}.\\n\\n'
                     'Generated with {}")'.format(i, name_lower, generator))
        lines.append(' (keywords "connector, 1x{}, {}")'.format(i, keywords))
        lines.append(' (author "{}")'.format(author))
        lines.append(' (version "0.1")')
        lines.append(' (created {})'.format(create_date or now()))
        lines.append(' (deprecated false)')
        lines.append(' (category {})'.format(cmpcat))
        for j in range(1, i + 1):
            lines.append(' (pin {} (name "{}")'.format(uuid_pins[j - 1], j))
            lines.append(
                '  (position 5.08 {}) (rotation 180.0) (length 3.81)'.format(
                    get_y(j, i, spacing, True)))
            lines.append(' )')

        # Polygons
        y_max, y_min = get_rectangle_bounds(i, spacing, spacing, True)
        lines.append(' (polygon {} (layer sym_outlines)'.format(uuid_polygon))
        lines.append(
            '  (width {}) (fill false) (grab_area true)'.format(line_width))
        lines.append('  (vertex (position -{} {}) (angle 0.0))'.format(
            spacing, ff(y_max)))
        lines.append('  (vertex (position {} {}) (angle 0.0))'.format(
            spacing, ff(y_max)))
        lines.append('  (vertex (position {} {}) (angle 0.0))'.format(
            spacing, ff(y_min)))
        lines.append('  (vertex (position -{} {}) (angle 0.0))'.format(
            spacing, ff(y_min)))
        lines.append('  (vertex (position -{} {}) (angle 0.0))'.format(
            spacing, ff(y_max)))
        lines.append(' )')

        # Decorations
        if kind == KIND_HEADER:
            # Headers: Small rectangle
            for j in range(1, i + 1):
                y = get_y(j, i, spacing, True)
                dx = spacing / 8 * 1.5
                dy = spacing / 8 / 1.5
                lines.append(' (polygon {} (layer sym_outlines)'.format(
                    uuid_decoration))
                lines.append(
                    '  (width {}) (fill true) (grab_area true)'.format(
                        line_width))
                vertex = '  (vertex (position {} {}) (angle 0.0))'
                lines.append(vertex.format(ff(spacing / 2 - dx), ff(y + dy)))
                lines.append(vertex.format(ff(spacing / 2 + dx), ff(y + dy)))
                lines.append(vertex.format(ff(spacing / 2 + dx), ff(y - dy)))
                lines.append(vertex.format(ff(spacing / 2 - dx), ff(y - dy)))
                lines.append(vertex.format(ff(spacing / 2 - dx), ff(y + dy)))
                lines.append(' )')
        elif kind == KIND_SOCKET:
            # Sockets: Small semicircle
            for j in range(1, i + 1):
                y = get_y(j, i, spacing, True)
                d = spacing / 4 * 0.75
                w = line_width * 0.75
                lines.append(' (polygon {} (layer sym_outlines)'.format(
                    uuid_decoration))
                lines.append(
                    '  (width {}) (fill false) (grab_area false)'.format(w))
                lines.append(
                    '  (vertex (position {} {}) (angle 135.0))'.format(
                        ff(spacing / 2 + d * 0.5 - d - w), ff(y - d)), )
                lines.append('  (vertex (position {} {}) (angle 0.0))'.format(
                    ff(spacing / 2 + d * 0.5 - d - w), ff(y + d)))
                lines.append(' )')

        # Text
        y_max, y_min = get_rectangle_bounds(i, spacing, spacing, True)
        lines.append(
            ' (text {} (layer sym_names) (value "{{{{NAME}}}}")'.format(
                uuid_text_name))
        lines.append(
            '  (align center bottom) (height {}) (position 0.0 {}) (rotation 0.0)'
            .format(
                ff(sym_text_height),
                ff(y_max),
            ))
        lines.append(' )')
        lines.append(
            ' (text {} (layer sym_names) (value "{{{{VALUE}}}}")'.format(
                uuid_text_value))
        lines.append(
            '  (align center top) (height {}) (position 0.0 {}) (rotation 0.0)'
            .format(
                ff(sym_text_height),
                ff(y_min),
            ))
        lines.append(' )')

        lines.append(')')

        sym_dir_path = path.join(dirpath, uuid_sym)
        if not (path.exists(sym_dir_path) and path.isdir(sym_dir_path)):
            makedirs(sym_dir_path)
        with open(path.join(sym_dir_path, '.librepcb-sym'), 'w') as f:
            f.write('0.1\n')
        with open(path.join(sym_dir_path, 'symbol.lp'), 'w') as f:
            f.write('\n'.join(lines))
            f.write('\n')

        print('1x{} {}: Wrote symbol {}'.format(i, kind, uuid_sym))
コード例 #26
0
ファイル: check_performance.py プロジェクト: sscargal/ddct
def check_single_volume_performance_fio_4k(config):
    vprint("Checking FIO performance, single volume")
    if not exe_check("which fio"):
        ff("FIO is not installed", "0BB2848F")
    api = config['api']
コード例 #27
0
def test_format_float(inval: float, outval: str):
    assert ff(inval) == outval
コード例 #28
0
    def _generate_footprint(key: str, name: str, pad_extension: float) -> None:
        # Create Meta-data
        uuid_footprint = _uuid('footprint-{}'.format(key))
        lines.append(' (footprint {}'.format(uuid_footprint))
        lines.append('  (name "{}")'.format(name))
        lines.append('  (description "")')

        pad_length = config.lead_length + config.toe_heel + pad_extension
        exposed_length = config.exposed_length
        abs_pad_pos_x = (config.width / 2) - (config.lead_length / 2) + (config.toe_heel / 2) + (pad_extension / 2)

        # Check clearance and make pads smaller if required
        if make_exposed:
            clearance = (config.width / 2) - config.lead_length - (exposed_length / 2)
            if clearance < MIN_CLEARANCE:
                print("Increasing clearance from {:.2f} to {:.2f}".format(clearance, MIN_CLEARANCE))
                d_clearance = (MIN_CLEARANCE - clearance) / 2
                pad_length = pad_length - d_clearance
                exposed_length = exposed_length - 2 * d_clearance
                abs_pad_pos_x = abs_pad_pos_x + (d_clearance / 2)

            if exposed_length < MIN_TRACE:
                print("Increasing exposed path width from {:.2f} to {:.2f}".format(exposed_length, MIN_TRACE))
                d_exp = MIN_TRACE - exposed_length
                exposed_length = exposed_length + d_exp
                pad_length = pad_length - (d_exp / 2)
                abs_pad_pos_x = abs_pad_pos_x + (d_exp / 4)

        # Place pads
        for pad_idx, pad_nr in enumerate(range(1, config.pin_count + 1)):
            half_n_pads = config.pin_count // 2
            pad_pos_y = get_y(pad_idx % half_n_pads + 1, half_n_pads, config.pitch, False)

            if pad_idx < (config.pin_count / 2):
                pad_pos_x = - abs_pad_pos_x
            else:
                pad_pos_x = abs_pad_pos_x
                pad_pos_y = - pad_pos_y

            lines.append('  (pad {} (side top) (shape rect)'.format(uuid_pads[pad_idx]))
            lines.append('   (position {} {}) (rotation 0.0) (size {} {}) (drill 0.0)'.format(
                         ff(pad_pos_x), ff(pad_pos_y),
                         ff(pad_length), ff(config.lead_width)))
            lines.append('  )')

        # Make exposed pad, if required
        # TODO: Handle pin1_corner_dx_dy in config once custom pad shapes are possible
        if make_exposed:
            lines.append('  (pad {} (side top) (shape rect)'.format(uuid_exp))
            lines.append('   (position 0.0 0.0) (rotation 0.0) (size {} {}) (drill 0.0)'.format(
                         ff(exposed_length), ff(config.exposed_width)))
            lines.append('  )')

            # Measure clearance pad-exposed pad
            clearance = abs(pad_pos_x) - (pad_length / 2) - (exposed_length / 2)
            if np.around(clearance, decimals=2) < MIN_CLEARANCE:
                print("Warning: minimal clearance violated in {}: {:.4f} < {:.2f}".format(full_name, clearance, MIN_CLEARANCE))

        # Create Silk Screen (lines and dot only)
        silk_down = (config.length / 2 - SILKSCREEN_OFFSET -
                     get_y(1, half_n_pads, config.pitch, False) -
                     config.lead_width / 2 -
                     SILKSCREEN_LINE_WIDTH / 2)    # required for round ending of line

        # Measure clearance silkscreen to exposed pad
        silk_top_line_height = config.length / 2
        if make_exposed:
            silk_clearance = silk_top_line_height - (SILKSCREEN_LINE_WIDTH / 2) - (config.exposed_width / 2)
            if np.around(silk_clearance, decimals=2) < SILKSCREEN_OFFSET:
                silk_top_line_height = silk_top_line_height + (SILKSCREEN_OFFSET - silk_clearance)
                silk_down = silk_down + (SILKSCREEN_OFFSET - silk_clearance)
                print("Increasing exp-silk clearance from {:.4f} to {:.2f}".format(silk_clearance, SILKSCREEN_OFFSET))

        for idx, silkscreen_pos in enumerate([-1, 1]):
            uuid_silkscreen_poly = _uuid('polygon-silkscreen-{}-{}'.format(key, idx))
            lines.append('  (polygon {} (layer top_placement)'.format(uuid_silkscreen_poly))
            lines.append('   (width {}) (fill false) (grab_area false)'.format(
                SILKSCREEN_LINE_WIDTH))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                         ff(-config.width / 2),
                         ff(silkscreen_pos * (silk_top_line_height - silk_down))))
            # If this is negative, the silkscreen line has to be moved away from
            # the real position, in order to keep the required distance to the
            # pad. We then only draw a single line, so we can omit the parts below.
            if silk_down > 0:
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                             ff(-config.width / 2),
                             ff(silkscreen_pos * silk_top_line_height)))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                             ff(config.width / 2),
                             ff(silkscreen_pos * silk_top_line_height)))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                         ff(config.width / 2),
                         ff(silkscreen_pos * (silk_top_line_height - silk_down))))

            lines.append('  )')

        # Create leads on docu
        uuid_leads = [_uuid('lead-{}'.format(p)) for p in range(1, config.pin_count + 1)]
        for pad_idx, pad_nr in enumerate(range(1, config.pin_count + 1)):
            lead_uuid = uuid_leads[pad_idx]

            # Make silkscreen lead exact pad width and length
            half_n_pads = config.pin_count // 2
            pad_pos_y = get_y(pad_idx % half_n_pads + 1, half_n_pads, config.pitch, False)
            if pad_idx >= (config.pin_count / 2):
                pad_pos_y = - pad_pos_y
            y_min = pad_pos_y - config.lead_width / 2
            y_max = pad_pos_y + config.lead_width / 2

            x_max = config.width / 2
            x_min = x_max - config.lead_length
            if pad_idx < (config.pin_count / 2):
                x_min, x_max = - x_min, - x_max

            # Convert numbers to librepcb format
            x_min_str, x_max_str = ff(x_min), ff(x_max)
            y_min_str, y_max_str = ff(y_min), ff(y_max)

            lines.append('  (polygon {} (layer top_documentation)'.format(lead_uuid))
            lines.append('   (width 0.0) (fill true) (grab_area false)')
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min_str, y_max_str))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_max_str, y_max_str))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_max_str, y_min_str))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min_str, y_min_str))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min_str, y_max_str))
            lines.append('  )')

        # Create exposed pad on docu
        if make_exposed:
            uuid_docu_exposed = _uuid('lead-exposed')

            x_min, x_max = - config.exposed_length / 2, config.exposed_length / 2
            y_min, y_max = - config.exposed_width / 2, config.exposed_width / 2

            lines.append('  (polygon {} (layer top_documentation)'.format(uuid_docu_exposed))
            lines.append('   (width 0.0) (fill true) (grab_area false)')
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min, y_max))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_max, y_max))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_max, y_min))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min, y_min))
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(x_min, y_max))
            lines.append('  )')

        # Create body outline on docu
        uuid_body_outline = _uuid('body-outline')
        outline_line_width = 0.2
        dx = config.width / 2 - outline_line_width / 2
        dy = config.length / 2 - outline_line_width / 2
        lines.append('  (polygon {} (layer top_documentation)'.format(uuid_body_outline))
        lines.append('   (width {}) (fill false) (grab_area false)'.format(outline_line_width))
        lines.append('   (vertex (position {} {}) (angle 0.0))'.format(-dx, dy))
        lines.append('   (vertex (position {} {}) (angle 0.0))'.format(dx, dy))
        lines.append('   (vertex (position {} {}) (angle 0.0))'.format(dx, -dy))
        lines.append('   (vertex (position {} {}) (angle 0.0))'.format(-dx, -dy))
        lines.append('   (vertex (position {} {}) (angle 0.0))'.format(-dx, dy))
        lines.append('  )')

        if config.extended_doc_fn:
            config.extended_doc_fn(config, _uuid, lines)

        # As discussed in https://github.com/LibrePCB-Libraries/LibrePCB_Base.lplib/pull/16
        # the silkscreen circle should have size SILKSCREEN_LINE_WIDTH for small packages,
        # and twice the size for larger packages. We define small to be either W or L <3.0mm
        # and large if both W and L >= 3.0mm
        if config.width >= 3.0 and config.length >= 3.0:
            silkscreen_circ_dia = 2.0 * SILKSCREEN_LINE_WIDTH
        else:
            silkscreen_circ_dia = SILKSCREEN_LINE_WIDTH

        if silkscreen_circ_dia == SILKSCREEN_LINE_WIDTH:
            silk_circ_y = config.length / 2 + silkscreen_circ_dia
            silk_circ_x = -config.width / 2 - SILKSCREEN_LINE_WIDTH
        else:
            silk_circ_y = config.length / 2 + SILKSCREEN_LINE_WIDTH / 2
            silk_circ_x = -config.width / 2 - silkscreen_circ_dia

        # Move silkscreen circle upwards if the line is moved too
        if silk_down < 0:
            silk_circ_y = silk_circ_y - silk_down

        uuid_silkscreen_circ = _uuid('circle-silkscreen-{}'.format(key))
        lines.append('  (circle {} (layer top_placement)'.format(uuid_silkscreen_circ))
        lines.append('   (width 0.0) (fill true) (grab_area false) '
                     '(diameter {}) (position {} {})'.format(
                         ff(silkscreen_circ_dia),
                         ff(silk_circ_x),
                         ff(silk_circ_y)
                     ))
        lines.append('  )')

        # Add name and value labels
        uuid_text_name = _uuid('text-name-{}'.format(key))
        uuid_text_value = _uuid('text-value-{}'.format(key))

        lines.append('  (stroke_text {} (layer top_names)'.format(uuid_text_name))
        lines.append('   {}'.format(TEXT_ATTRS))
        lines.append('   (align center bottom) (position 0.0 {}) (rotation 0.0)'.format(
            config.length / 2 + LABEL_OFFSET))
        lines.append('   (auto_rotate true) (mirror false) (value "{{NAME}}")')
        lines.append('  )')
        lines.append('  (stroke_text {} (layer top_values)'.format(uuid_text_value))
        lines.append('   {}'.format(TEXT_ATTRS))
        lines.append('   (align center top) (position 0.0 {}) (rotation 0.0)'.format(
            -config.length / 2 - LABEL_OFFSET))
        lines.append('   (auto_rotate true) (mirror false) (value "{{VALUE}}")')
        lines.append('  )')

        # Closing parenthese for footprint
        lines.append(' )')
コード例 #29
0
def check_multipath_conf(config):
    dist = get_os()
    vfile = CONFS.get(dist)
    if not vfile:
        wf("No supported multipath.conf file for: {}".format(dist), "381CE248")
    mfile = "/etc/multipath.conf"
    if not os.path.exists(mfile):
        if not vfile:
            fix = "copy a multipath.conf file from the Datera Deployment Guide"
        else:
            fix = "copy {} to /etc/multipath.conf".format(vfile)
        return ff("/etc/multipath.conf file not found", "1D506D89", fix=fix)
    with io.open(mfile, 'r') as f:
        mconf = parse_mconf(f.read())

    # Check defaults section
    defaults = filter(lambda x: x[0] == 'defaults', mconf)
    fix = ("check the example multipath.conf file from Datera deployment"
           "guide")
    if not defaults:
        ff("Missing defaults section", "1D8C438C", fix=fix)

    else:
        defaults = defaults[0]
        ct = False
        for d in defaults[1]:
            if 'checker_timeout' in d:
                ct = True
        if not ct:
            ff("defaults section missing 'checker_timeout'",
               "70191A9A",
               fix=fix)

    # Check devices section
    devices = filter(lambda x: x[0] == 'devices', mconf)
    if not devices:
        ff("Missing devices section", "797A6031", fix=fix)
    else:
        devices = devices[0][1]
        dat_block = None
        for _, device in devices:
            ddict = {}
            for entry in device:
                ddict[entry[0]] = entry[1]
            if ddict['vendor'] == 'DATERA':
                dat_block = ddict
        if not dat_block:
            return ff("No DATERA device section found", "99B9D136", fix=fix)

        if not dat_block['product'] == "IBLOCK":
            ff("Datera 'product' entry should be \"IBLOCK\"",
               "A9DF3F8C",
               fix=fix)

    # Blacklist exceptions
    be = filter(lambda x: x[0] == 'blacklist_exceptions', mconf)
    if not be:
        ff("Missing blacklist_exceptions section", "B8C8A19C")
    else:
        be = be[0][1]
        dat_block = None
        for _, device in be:
            bdict = {}
            for entry in device:
                bdict[entry[0]] = entry[1]
            if bdict['vendor'] == 'DATERA.*':
                dat_block = bdict
        if not dat_block:
            ff("No Datera blacklist_exceptions section found",
               "09E37E51",
               fix=fix)
        if dat_block['vendor'] != 'DATERA.*':
            ff("Datera blacklist_exceptions vendor entry malformed",
               "9990F32F",
               fix=fix)
        if dat_block['product'] != 'IBLOCK.*':
            ff("Datera blacklist_exceptions product entry malformed",
               "642753A0",
               fix=fix)
コード例 #30
0
        def add_footprint_variant(
            key: str,
            name: str,
            density_level: str,
        ) -> None:
            # UUIDs
            uuid_footprint = _uuid('footprint-{}'.format(key))
            uuid_silkscreen = [
                _uuid('polygon-silkscreen-{}-{}'.format(quadrant, key))
                for quadrant in [1, 2, 3, 4]
            ]
            uuid_outline = _uuid('polygon-outline-{}'.format(key))
            uuid_courtyard = _uuid('polygon-courtyard-{}'.format(key))
            uuid_text_name = _uuid('text-name-{}'.format(key))
            uuid_text_value = _uuid('text-value-{}'.format(key))

            # Pad excess according to IPC density levels
            excess = config.excess_by_density(density_level)

            # Lead contact offsets
            lead_contact_x_offset = config.lead_span_x / 2 - config.lead_contact_length  # this is the inner side of the contact area

            # Position of the first and last pad
            pos_first = get_pad_coords(1, config.lead_count, config.pitch,
                                       lead_contact_x_offset)
            pos_last = get_pad_coords(config.lead_count, config.lead_count,
                                      config.pitch, lead_contact_x_offset)

            lines.append(' (footprint {}'.format(uuid_footprint))
            lines.append('  (name "{}")'.format(name))
            lines.append('  (description "")')

            # Pads
            pad_width = config.lead_width + excess.side * 2
            pad_length = config.lead_contact_length + excess.heel + excess.toe
            for p in range(1, config.lead_count + 1):
                pad_uuid = uuid_pads[p - 1]
                pad_center_offset_x = config.lead_span_x / 2 - pad_length / 2 + excess.toe
                pos = get_pad_coords(p, config.lead_count, config.pitch,
                                     pad_center_offset_x)
                pad_rotation = 90.0 if pos.orientation == 'horizontal' else 0.0
                lines.append(
                    '  (pad {} (side top) (shape rect)'.format(pad_uuid))
                lines.append(
                    '   (position {} {}) (rotation {}) (size {} {}) (drill 0.0)'
                    .format(
                        ff(pos.x),
                        ff(pos.y),
                        ff(pad_rotation),
                        ff(pad_width),
                        ff(pad_length),
                    ))
                lines.append('  )')

            # Documentation: Leads
            for p in range(1, config.lead_count + 1):
                pad_center_offset_x = config.lead_span_x / 2 - pad_length / 2
                pos = get_pad_coords(p, config.lead_count, config.pitch,
                                     lead_contact_x_offset)
                lead_uuid_ctct = uuid_leads1[p - 1]  # Contact area
                lead_uuid_proj = uuid_leads2[p - 1]  # Vertical projection

                # Contact area
                if pos.orientation == 'horizontal':
                    x1 = ff(pos.x)
                    x2 = ff(pos.x + sign(pos.x) * config.lead_contact_length)
                    y1 = ff(pos.y - config.lead_width / 2)
                    y2 = ff(pos.y + config.lead_width / 2)
                elif pos.orientation == 'vertical':
                    x1 = ff(pos.x - config.lead_width / 2)
                    x2 = ff(pos.x + config.lead_width / 2)
                    y1 = ff(pos.y)
                    y2 = ff(pos.y + sign(pos.y) * config.lead_contact_length)
                lines.append('  (polygon {} (layer top_documentation)'.format(
                    lead_uuid_ctct))
                lines.append('   (width 0.0) (fill true) (grab_area false)')
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y1))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x2, y1))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x2, y2))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y2))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y1))
                lines.append('  )')
                # Vertical projection, between contact area and body
                if pos.orientation == 'horizontal':
                    x1 = ff(sign(pos.x) * config.body_size_x / 2)
                    x2 = ff(pos.x)
                    y1 = ff(pos.y - config.lead_width / 2)
                    y2 = ff(pos.y + config.lead_width / 2)
                elif pos.orientation == 'vertical':
                    x1 = x2 = y1 = y2 = ff(0)
                    x1 = ff(pos.x - config.lead_width / 2)
                    x2 = ff(pos.x + config.lead_width / 2)
                    y1 = ff(sign(pos.y) * config.body_size_y / 2)
                    y2 = ff(pos.y)
                lines.append('  (polygon {} (layer top_documentation)'.format(
                    lead_uuid_proj))
                lines.append('   (width 0.0) (fill true) (grab_area false)')
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y1))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x2, y1))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x2, y2))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y2))
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    x1, y1))
                lines.append('  )')

            # Silkscreen: 1 per quadrant
            # (Quadrant 1 is at the top right, the rest follows CCW)
            for quadrant in [1, 2, 3, 4]:
                uuid = uuid_silkscreen[quadrant - 1]

                x_min = abs(
                    pos_last.x
                ) + config.lead_width / 2 + excess.side + silkscreen_offset + line_width / 2
                x_max = config.body_size_x / 2 + line_width / 2
                y_min = abs(
                    pos_first.y
                ) + config.lead_width / 2 + excess.side + silkscreen_offset + line_width / 2
                y_max = config.body_size_y / 2 + line_width / 2
                vertices = [(x_min, y_max), (x_max, y_max), (x_max, y_min)]

                # Pin 1 marking line
                if quadrant == 2:
                    vertices.append((
                        config.lead_span_x / 2 + excess.toe - line_width / 2,
                        y_min,
                    ))

                lines.append(
                    '  (polygon {} (layer top_placement)'.format(uuid))
                lines.append(
                    '   (width {}) (fill false) (grab_area false)'.format(
                        line_width))
                sign_x = 1 if quadrant in [1, 4] else -1
                sign_y = 1 if quadrant in [1, 2] else -1
                for (x, y) in vertices:
                    xx = ff(sign_x * x)
                    yy = ff(sign_y * y)
                    lines.append(
                        '   (vertex (position {} {}) (angle 0.0))'.format(
                            xx, yy))
                lines.append('  )')

            # Documentation outline (fully inside body)
            outline_x_offset = config.body_size_x / 2 - line_width / 2
            outline_y_offset = config.body_size_y / 2 - line_width / 2
            lines.append(
                '  (polygon {} (layer top_documentation)'.format(uuid_outline))
            lines.append('   (width {}) (fill false) (grab_area false)'.format(
                line_width))
            oxo = ff(outline_x_offset)  # Used for shorter code lines below :)
            oyo = ff(outline_y_offset)  # Used for shorter code lines below :)
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                oxo, oyo))  # NE
            lines.append('   (vertex (position {} -{}) (angle 0.0))'.format(
                oxo, oyo))  # SE
            lines.append('   (vertex (position -{} -{}) (angle 0.0))'.format(
                oxo, oyo))  # SW
            lines.append('   (vertex (position -{} {}) (angle 0.0))'.format(
                oxo, oyo))  # NW
            lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                oxo, oyo))  # NE
            lines.append('  )')

            # Courtyard
            x_max = config.lead_span_x / 2 + excess.toe
            x_mid = config.body_size_x / 2
            x_min = abs(pos_last.x) + config.lead_width / 2 + excess.side
            y_max = config.lead_span_y / 2 + excess.toe
            y_mid = config.body_size_y / 2
            y_min = abs(pos_first.y) + config.lead_width / 2 + excess.side
            vertices = [  # Starting at top left
                # Top
                (-x_min, y_max),
                (x_min, y_max),
                (x_min, y_mid),
                (x_mid, y_mid),
                (x_mid, y_min),
                # Right
                (x_max, y_min),
                (x_max, -y_min),
                (x_mid, -y_min),
                (x_mid, -y_mid),
                (x_min, -y_mid),
                # Bottom
                (x_min, -y_max),
                (-x_min, -y_max),
                (-x_min, -y_mid),
                (-x_mid, -y_mid),
                (-x_mid, -y_min),
                # Left
                (-x_max, -y_min),
                (-x_max, y_min),
                (-x_mid, y_min),
                (-x_mid, y_mid),
                (-x_min, y_mid),
                # Back to top
                (-x_min, y_max),
            ]
            lines.append('  (polygon {} (layer {})'.format(
                uuid_courtyard, 'top_courtyard'))
            lines.append('   (width {}) (fill false) (grab_area false)'.format(
                COURTYARD_LINE_WIDTH))
            for (x, y) in vertices:
                xx = ff(x + sign(x) * excess.courtyard)
                yy = ff(y + sign(y) * excess.courtyard)
                lines.append('   (vertex (position {} {}) (angle 0.0))'.format(
                    xx, yy))
            lines.append('  )')

            # Labels
            y_offset = ff(config.lead_span_y / 2 + text_y_offset)
            text_attrs = '(height {}) (stroke_width 0.2) ' \
                         '(letter_spacing auto) (line_spacing auto)'.format(pkg_text_height)
            lines.append(
                '  (stroke_text {} (layer top_names)'.format(uuid_text_name))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center bottom) (position 0.0 {}) (rotation 0.0)'.
                format(y_offset))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{NAME}}")')
            lines.append('  )')
            lines.append(
                '  (stroke_text {} (layer top_values)'.format(uuid_text_value))
            lines.append('   {}'.format(text_attrs))
            lines.append(
                '   (align center top) (position 0.0 -{}) (rotation 0.0)'.
                format(y_offset))
            lines.append(
                '   (auto_rotate true) (mirror false) (value "{{VALUE}}")')
            lines.append('  )')

            lines.append(' )')