Example #1
0
def must_read_config(config_file):
    "Load config or die"
    try:
        config = yaml.load(open(config_file))
        return config
    except Exception as e:
        report.die("Cannot load config: %s" % e)
Example #2
0
def show_info(args, config, c):
    if not args.name:
        report.die("Cannot stat container without name (supply -n with name)")

    # FIXME: error handling
    result = c.get_container(args.name)
    print result
Example #3
0
def must_read_config(config_file):
    "Load config or die"
    try:
        config = yaml.load(open(config_file))
        return config
    except Exception as e:
        report.die("Cannot load config: %s" % e)
Example #4
0
def show_info(args, config, c):
    if not args.name:
        report.die("Cannot stat container without name (supply -n with name)")

    # FIXME: error handling
    result = c.get_container(args.name)
    print result
Example #5
0
File: main.py Project: ngsru/heaver
def must_load_net_config(networks_config, used_ranges):
    "Read and parse network config or die"
    networks = dict()
    uranges = list()
    if len(networks_config) == 0:
        return dict()

    try:
        for config in networks_config:
            net = dict(type=config["type"], pool=addrpool.AddressPool(uranges),
                       gateway=config.get("gateway", "auto"))
            for r in config["ranges"]:
                net["pool"].add_range(r)

            if net["type"] == "bridge":
                net["bridge"] = config["bridge"]

            networks[config["name"]] = net
    except Exception as e:
        report.die("Invalid address range '%s' in config: %s" % (r, e))
    try:
        # all networks share same storage for used ranges, so any pool suffice
        pool = networks.values()[0]["pool"]
        for r in used_ranges:
            pool.add_used_range(r)
    except Exception as e:
        report.die("Invalid address range '%s' in used ranges: %s" % (r, e))

    return networks
Example #6
0
File: main.py Project: ngsru/heaver
def list_(args, config):
    if args.name:
        all_boxes = ops.ls()
        if args.name not in all_boxes:
            report.die("No such container: '%s'" % args.name)
        boxes = {args.name: all_boxes[args.name]}
    else:
        boxes = ops.ls()
    print report.format(dict(status="OK", action="list", data=boxes, message=format_list(boxes)))
Example #7
0
def create(operator, args):
    if not args.image:
        report.die("Image id must be specified")

    try:
        instance = operator.create_instance(args.image, args.clone)
        print report.format(dict(action="create", status="OK", data=[args.image, instance],
            message="Created instance of image %s: %s" % (args.image, instance)))
    except Exception as e:
        report.die("Failed to create instance for image %s: %s" % (args.image, e))
Example #8
0
def destroy(operator, args):
    if not args.clone:
        report.die("Clone id must be specified")

    try:
        instance = operator.destroy_instance(args.clone)
        print report.format(dict(action="destroy", status="OK", data=[args.clone],
            message="Destroyed instance %s" % (args.clone,)))
    except Exception as e:
        report.die("Failed to destroy instance %s: %s" % (args.clone, e))
Example #9
0
def remove(operator, args):
    if not args.image:
        report.die("Image id must be specified")

    try:
        instance = operator.delete_image(args.image)
        print report.format(dict(action="remove", status="OK", data=[args.image],
            message="Removed image %s" % (args.image,)))
    except Exception as e:
        report.die("Failed to remove image %s: %s" % (args.image, e))
Example #10
0
def must_validate_config(config, args):
    "Validate config or die"
    try:
        if args.net and len(args.net):
            networks = [net["name"] for net in config["net"]["networks"]]
            bad_network = set(args.net) - set(networks)
            if len(bad_network):
                raise Exception ("Error network configuration: %s" % ", ".join(list(bad_network)))
        return True
    except Exception as e:
        report.die("Cannot validate config: %s" % e)
Example #11
0
def start(args, config, c):
    if not args.name:
        report.die("Cannot start container without name (supply -n with name)")

    try:
        result = c.start_container(args.name, args.host)
    except client.RequestError as e:
        print "Failed to start container!"
        print e
    else:
        print result
Example #12
0
def start(args, config, c):
    if not args.name:
        report.die("Cannot start container without name (supply -n with name)")

    try:
        result = c.start_container(args.name, args.host)
    except client.RequestError as e:
        print "Failed to start container!"
        print e
    else:
        print result
Example #13
0
def must_validate_config(config, args):
    "Validate config or die"
    try:
        if args.net and len(args.net):
            networks = [net["name"] for net in config["net"]["networks"]]
            bad_network = set(args.net) - set(networks)
            if len(bad_network):
                raise Exception("Error network configuration: %s" %
                                ", ".join(list(bad_network)))
        return True
    except Exception as e:
        report.die("Cannot validate config: %s" % e)
Example #14
0
def destroy(operator, args):
    if not args.clone:
        report.die("Clone id must be specified")

    try:
        instance = operator.destroy_instance(args.clone)
        print report.format(
            dict(action="destroy",
                 status="OK",
                 data=[args.clone],
                 message="Destroyed instance %s" % (args.clone, )))
    except Exception as e:
        report.die("Failed to destroy instance %s: %s" % (args.clone, e))
Example #15
0
File: main.py Project: ngsru/heaver
def must_gen_net(net, count):
    "Generate addresses and hwaddr for network"

    raw_addresses = net["pool"].alloc_addresses(count)
    if raw_addresses is None:
            report.die("Not enough free addresses")

    # FIXME: ip address datatype - string or tuple or smth else?
    raw_mac = (02, random.randint(1, 255)) + addrpool.parse_address(raw_addresses[0])

    mac = ":".join("%x" % digit for digit in raw_mac)
    addresses = [(addr, "24") for addr in raw_addresses] # FIXME: hardcoded netmask!
    return mac, addresses
Example #16
0
def remove(operator, args):
    if not args.image:
        report.die("Image id must be specified")

    try:
        instance = operator.delete_image(args.image)
        print report.format(
            dict(action="remove",
                 status="OK",
                 data=[args.image],
                 message="Removed image %s" % (args.image, )))
    except Exception as e:
        report.die("Failed to remove image %s: %s" % (args.image, e))
Example #17
0
def must_set_up_logging(config, format):
    "Set up logging or die"
    root_logger = logging.getLogger("heaver")
    root_logger.propagate = False

    # set up logging
    if "logging" not in config:
        # logging disabled
        root_logger.addHandler(NullHandler())
    elif not isinstance(config, dict) or not isinstance(
            config["logging"], dict):
        report.die("Logging config must be dictionary")
    else:
        log_config = config["logging"]

        try:
            log_file = log_config["filename"]
            log_format = log_config["format"]
            if not hasattr(logging, log_config["level"].upper()):
                report.die("Invalid log level for logging: %s" %
                           log_config["level"])
            log_level = getattr(logging, log_config["level"].upper())
        except Exception as e:
            report.die("Malformed logging config: %s" % e)

        try:
            file_stream = open(log_file, "a")
        except Exception:
            report.die("Cannot open log-file '%s' for writing" % log_file)

        file_handler = logging.StreamHandler(file_stream)
        file_handler.setFormatter(
            logging.Formatter(log_format))  # TODO: check for errors in format?
        file_handler.setLevel(log_level)

        root_logger.addHandler(file_handler)

        if "console_level" in log_config and "console_format" in log_config:
            if not hasattr(logging, log_config["console_level"].upper()):
                report.die("Invalid log level for console logging: %s" %
                           log_config["console_level"])
            log_level = getattr(logging, log_config["console_level"].upper())

            console_handler = logging.StreamHandler(sys.stdout)
            if format == "pretty":
                console_handler.setFormatter(
                    logging.Formatter(log_config["console_format"]))
            elif format == "json":
                console_handler.setFormatter(report.JsonFormatter())

            root_logger.addHandler(console_handler)
Example #18
0
def main(args, config):

    actions = [
        args.start, args.stop, args.create, args.destroy, args.list,
        args.list_hosts, args.info, args.tarball, args.sync_images
    ]

    if not any(actions):
        report.die("No action given")

    if args.start and args.stop:  #TODO: can act as restart
        report.die(
            "Cannot start and stop container simultaneously (-ST given)")

    if args.create and args.destroy:
        report.die(
            "Cannot create and destroy container simultaneously (-CD given)")

    if "server" not in config:
        report.die("No 'server' in config")

    if not isinstance(config["server"], basestring):
        report.die("'server' parameter must be string")

    c = client.Client(config["server"])
    if args.create:
        create(args, config, c)

    if args.start:
        start(args, config, c)

    if args.stop:
        stop(args, config, c)

    if args.destroy:
        destroy(args, config, c)

    if args.list:
        list_containers(args, config, c)

    if args.list_hosts:
        list_hosts(args, config, c)

    if args.info:
        show_info(args, config, c)

    if args.tarball:
        make_tarball(args, config, c)

    if args.sync_images:
        sync_images(args, config, c)
Example #19
0
File: main.py Project: ngsru/heaver
def must_get_names(args):
    "Helper for retrieving container names"
    if args.all:
        try:
            names = ops.ls().keys()
        except ops.InvocationError as e:
            report.die("LXC is broken: %s" % e)
    else:
        if not ops.exists(args.name):
            report.die("No such container: %s" % args.name)

        names = [args.name]

    return names
Example #20
0
def sync(operator, args):
    if (args.image and args.all) or (not args.image and not args.all):
        report.die("Either all or one concrete image may be syncronized")

    if args.image:
        images = [args.image]

    if args.all:
        images = operator.list_images()

    result = operator.sync_images(images)
    for image, status in result:
        print report.format(dict(action="sync", status=("FAIL" if status == "error" else "OK"),
                                 data=[image, status], message="%s\t%s" % (image, status)))
Example #21
0
def main(args, config):

    if not (args.create or args.destroy or args.add or args.remove or args.list or args.sync):
        report.die("No action given")

    if args.list and (args.create or args.destroy or args.add or args.remove):
        report.die("Cannot show list and perform actions!")

    if args.create and args.destroy:
        report.die("Cannot create and destroy clone simultaneously (-CD given)")

    if args.add and args.remove:
        report.die("Cannot add and remove image simultaneously (-AR given)")

    operator = image.get_image_operator(config["image"])

    if args.sync:
        sync(operator, args)

    if args.list:
        list_images(operator, args)

    if args.add:
        add(operator, args)

    if args.create:
        create(operator, args)

    if args.destroy:
        destroy(operator, args)

    if args.remove:
        remove(operator, args)
Example #22
0
def main(args, config):

    if not (args.create or args.destroy or args.add or args.remove or args.list
            or args.sync):
        report.die("No action given")

    if args.list and (args.create or args.destroy or args.add or args.remove):
        report.die("Cannot show list and perform actions!")

    if args.create and args.destroy:
        report.die(
            "Cannot create and destroy clone simultaneously (-CD given)")

    if args.add and args.remove:
        report.die("Cannot add and remove image simultaneously (-AR given)")

    operator = image.get_image_operator(config["image"])

    if args.sync:
        sync(operator, args)

    if args.list:
        list_images(operator, args)

    if args.add:
        add(operator, args)

    if args.create:
        create(operator, args)

    if args.destroy:
        destroy(operator, args)

    if args.remove:
        remove(operator, args)
Example #23
0
File: main.py Project: ngsru/heaver
def must_be_correct_limits_config(config):
    "Check overall limits settings and die if they are broken"
    if not isinstance(config, dict):
        report.die("\"limits\" config not a dict")
    if "cpu" in config:
        cpu = config["cpu"]
        try:
            isinstance(cpu, float)
        except:
            report.die("\"limits.cpu\" setting is malformed")

    if "memory" in config:
        memory = config["memory"]
        if memory[-1] == "K" or memory[-1] == "M" or memory[-1] == "G":
            memory = memory[:-1]
        try:
            isinstance(memory, int)
        except:
            report.die("\"limits.memory\" setting is malformed")

    if "reserve_cpu" in config:
	reserve_cpu = config["reserve_cpu"]
        try:
            isinstance(reserve_cpu, int)
        except:
            report.die("\"limits.reserve_cpu\" setting is malformed")
Example #24
0
def create(operator, args):
    if not args.image:
        report.die("Image id must be specified")

    try:
        instance = operator.create_instance(args.image, args.clone)
        print report.format(
            dict(action="create",
                 status="OK",
                 data=[args.image, instance],
                 message="Created instance of image %s: %s" %
                 (args.image, instance)))
    except Exception as e:
        report.die("Failed to create instance for image %s: %s" %
                   (args.image, e))
Example #25
0
File: main.py Project: ngsru/heaver
def send_status(args, config):
    if "upstream" not in config:
        report.die("Cannot send status to upstream - upstream isnt configured")

    c = client.Client(config["upstream"])
    status = get_status(config)

    answer = c.update_host(status["hostname"], status)
    # update authorized_keys file
    if "public_key" in answer:
        key = answer["public_key"]
        key_path = config.get("authorized_keys", os.path.expanduser("~/.ssh/authorized_keys"))
        update_authorized_keys(key, key_path)

    print report.format(dict(status="OK", action="send-status",
        message="Host status sent to daemon"))
Example #26
0
def main(args, config):

    actions = [args.start, args.stop, args.create, args.destroy, args.list, args.list_hosts,
               args.info, args.tarball, args.sync_images]

    if not any(actions):
        report.die("No action given")

    if args.start and args.stop: #TODO: can act as restart
        report.die("Cannot start and stop container simultaneously (-ST given)")

    if args.create and args.destroy:
        report.die("Cannot create and destroy container simultaneously (-CD given)")

    if "server" not in config:
        report.die("No 'server' in config")

    if not isinstance(config["server"], basestring):
        report.die("'server' parameter must be string")

    c = client.Client(config["server"])
    if args.create:
        create(args, config, c)

    if args.start:
        start(args, config, c)

    if args.stop:
        stop(args, config, c)

    if args.destroy:
        destroy(args, config, c)

    if args.list:
        list_containers(args, config, c)

    if args.list_hosts:
        list_hosts(args, config, c)

    if args.info:
        show_info(args, config, c)

    if args.tarball:
        make_tarball(args, config, c)

    if args.sync_images:
        sync_images(args, config, c)
Example #27
0
def must_set_up_logging(config, format):
    "Set up logging or die"
    root_logger = logging.getLogger("heaver")
    root_logger.propagate = False

    # set up logging
    if "logging" not in config:
        # logging disabled
        root_logger.addHandler(NullHandler())
    elif not isinstance(config, dict) or not isinstance(config["logging"], dict):
        report.die("Logging config must be dictionary")
    else:
        log_config = config["logging"]

        try:
            log_file = log_config["filename"]
            log_format = log_config["format"]
            if not hasattr(logging, log_config["level"].upper()):
                report.die("Invalid log level for logging: %s" % log_config["level"])
            log_level = getattr(logging, log_config["level"].upper())
        except Exception as e:
            report.die("Malformed logging config: %s" % e)

        try:
            file_stream = open(log_file, "a")
        except Exception:
            report.die("Cannot open log-file '%s' for writing" % log_file)

        file_handler = logging.StreamHandler(file_stream)
        file_handler.setFormatter(logging.Formatter(log_format)) # TODO: check for errors in format?
        file_handler.setLevel(log_level)

        root_logger.addHandler(file_handler)

        if "console_level" in log_config and "console_format" in log_config:
            if not hasattr(logging, log_config["console_level"].upper()):
                report.die("Invalid log level for console logging: %s" %
                    log_config["console_level"])
            log_level = getattr(logging, log_config["console_level"].upper())

            console_handler = logging.StreamHandler(sys.stdout)
            if format == "pretty":
                console_handler.setFormatter(logging.Formatter(log_config["console_format"]))
            elif format == "json":
                console_handler.setFormatter(report.JsonFormatter())

            root_logger.addHandler(console_handler)
Example #28
0
def sync(operator, args):
    if (args.image and args.all) or (not args.image and not args.all):
        report.die("Either all or one concrete image may be syncronized")

    if args.image:
        images = [args.image]

    if args.all:
        images = operator.list_images()

    result = operator.sync_images(images)
    for image, status in result:
        print report.format(
            dict(action="sync",
                 status=("FAIL" if status == "error" else "OK"),
                 data=[image, status],
                 message="%s\t%s" % (image, status)))
Example #29
0
def create(args, config, c):
    if not args.image:
        report.die("Cannot create container without image (supply -i with image id)")

    if not args.name:
        report.die("Cannot create container without name (supply -n with name)")

    if args.host:
        host = args.host
    else:
        host = None

    key = None
    if args.key:
        try:
            with open(args.key) as key_file:
                key = key_file.read()
        except Exception as e:
            report.die("Cannot read given key file: %s" % e)
    elif args.raw_key:
        key = args.raw_key

    net = args.net or []
    options = dict(net=net)
    if key is not None:
        options["key"] = key
    if args.limit is not None and len(args.limit) > 0:
        options["limit"] = args.limit
    try:
        container = c.create_container(args.name, args.image, host, options)
    except client.RequestError as e:
        print "Failed to create container!"
        print e
    else:
        print container
Example #30
0
File: main.py Project: ngsru/heaver
def stop(args, config):
    must_be_root()
    names = must_get_names(args)
    for name in names:
        try:
            ops.stop(name)
            try:
                box_config = ops.get_box_config(name)
            except Exception as e:
                report.die("Cannot load '%s' config, is it broken? %s" % (name, e))
            if os.path.exists(ops.get_box_home(name, "heaver_root_generated")):
                imager = image.get_image_operator(config["image"])
                if box_config["datamounts"]:
                    for mountpoint, source in box_config["datamounts"]:
                        imager.disassemble_instance(source)
                imager.disassemble_instance(box_config["root"])
        except ops.InvocationError as e:
            report.die("LXC is broken, cannot stop container %s: %s" % (name, e))
        except ops.ContainerNotFound as e:
            report.die("Container %s just disappeared, panic!" % name)
        try:
            running_flag = ops.get_box_home(name, "heaver_box_running")
            if os.path.exists(running_flag):
                os.unlink(running_flag)
        except Exception as e:
            pass # FIXME: should not happen, warn user/log?
	send_status_soft(args, config)
        print report.format(dict(status="OK", action="stop", id=name,
            message="Container %s stopped" % name))
Example #31
0
File: main.py Project: ngsru/heaver
def shutdown(args, config):
    must_be_root()
    names = ops.ls()

    for name in names:
        if ops.is_running(name):
            try:
                ops.stop(name)
                try:
                    box_config = ops.get_box_config(name)
                except Exception as e:
                    report.die("Cannot load '%s' config, is it broken? %s" % (name, e))
                if os.path.exists(ops.get_box_home(name, "heaver_root_generated")):
                    imager = image.get_image_operator(config["image"])
                    if box_config["datamounts"]:
                        for mountpoint, source in box_config["datamounts"]:
                            imager.disassemble_instance(source)
                    imager.disassemble_instance(box_config["root"])
            except ops.InvocationError as e:
                report.die("LXC is broken, cannot stop container %s: %s" % (name, e))
            except ops.ContainerNotFound as e:
                # WTF? Should not happen (containers in ops.ls() already exists)
                report.die("Container %s just disappeared, panic!" % name)

            send_status_soft(args, config)
            print report.format(dict(status="OK", action="shutdown", id=name,
                message="Container %s stopped at shutdown" % name))
Example #32
0
File: main.py Project: ngsru/heaver
def main(args, config):

    actions = [args.start, args.create, args.stop, args.destroy, args.list, args.tarball,
               args.send_status, args.status, args.startup, args.shutdown]
    if not any(actions):
        report.die("No action given")

    if args.start and args.stop: #TODO: can act as restart
        report.die("Cannot start and stop container simultaneously (-ST given)")

    if args.create and args.destroy:
        report.die("Cannot create and destroy container simultaneously (-CD given)")

    if (not args.name and not args.all and not args.send_status and not args.status
        and not args.list and not args.startup and not args.shutdown):
        report.die("No container chosen (no -n or --all options)")

    if args.create:
        create(args, config)

    if args.start:
        start(args, config)

    if args.stop:
        stop(args, config)

    if args.destroy:
        destroy(args, config)

    if args.list:
        list_(args, config)

    if args.tarball:
        make_tarball(args, config)

    if args.send_status:
        send_status(args, config)

    if args.status:
        status(args, config)

    if args.startup:
        startup(args, config)

    if args.shutdown:
        shutdown(args, config)
Example #33
0
def add(operator, args):
    if not args.image:
        report.die("Image id must be specified")
    if not args.tarball:
        report.die("Tarball with image must be specified")

    try:
        operator.add_image(args.tarball, args.image)
        print report.format(dict(action="add", status="OK", data=args.image,
            message="Added image %s from '%s'" % (args.image, args.tarball)))
    except Exception as e:
        report.die("Failed to add image %s from '%s': %s" % (args.image, args.tarball, e))
Example #34
0
def main(args, config):
    t = tracker.Tracker()
    user = config.get("user", "root")
    if "key_path" not in config:
        report.die("'key_path' config option must be set")
    key_path = config["key_path"]
    listen = config.get("listen", "127.0.0.1:8086")
    host, _semicolon, port = listen.partition(":")
    if not port:
        report.die("missing port in listen config item")

    try:
        ops_pool = ops.Pool(user, key_path, t)
    except Exception as e:
        report.die("failed to create operations pool: %s" % e)

    try:
        port = int(port)
        restapi.start(ops_pool, t, host, port)
    except Exception as e:
        report.die("restapi dead: %s" % e)
Example #35
0
def add(operator, args):
    if not args.image:
        report.die("Image id must be specified")
    if not args.tarball:
        report.die("Tarball with image must be specified")

    try:
        operator.add_image(args.tarball, args.image)
        print report.format(
            dict(action="add",
                 status="OK",
                 data=args.image,
                 message="Added image %s from '%s'" %
                 (args.image, args.tarball)))
    except Exception as e:
        report.die("Failed to add image %s from '%s': %s" %
                   (args.image, args.tarball, e))
Example #36
0
def make_tarball(args, config, c):
    if not args.name:
        report.die("Specify container to make tarball from (supply -n with name)")

    tar_path = args.tarball
    try:
        tar_file = open(tar_path, "wb")
    except Exception as e:
        report.die("Cannot open file '%s' for writing: %s" % (tar_path, e))

    try:
        result = c.make_tarball(args.name, tar_file)
    except Exception as e:
        os.unlink(tar_path)
        report.die("Cannot write tarball: %s" % e)
    finally:
        tar_file.close()

    print "tarball saved on: %s" % tar_path
Example #37
0
def make_tarball(args, config, c):
    if not args.name:
        report.die(
            "Specify container to make tarball from (supply -n with name)")

    tar_path = args.tarball
    try:
        tar_file = open(tar_path, "wb")
    except Exception as e:
        report.die("Cannot open file '%s' for writing: %s" % (tar_path, e))

    try:
        result = c.make_tarball(args.name, tar_file)
    except Exception as e:
        os.unlink(tar_path)
        report.die("Cannot write tarball: %s" % e)
    finally:
        tar_file.close()

    print "tarball saved on: %s" % tar_path
Example #38
0
File: main.py Project: ngsru/heaver
def start(args, config):
    must_be_root()
    names = must_get_names(args)

    # start
    for name in names:
        try:
            try:
                box_config = ops.get_box_config(name)
            except Exception as e:
                report.die("Cannot load '%s' config, is it broken? %s" % (name, e))
            if os.path.exists(ops.get_box_home(name, "heaver_root_generated")):
                imager = image.get_image_operator(config["image"])
                imager.assemble_instance(box_config["root"])

                if box_config["datamounts"]:
                    root = box_config["root"]
                    for mountpoint, source in box_config["datamounts"]:
                        imager.assemble_instance(source)
                        # since 'mountpoint' starts with / we need to remove it
                        mountpoint = mountpoint.lstrip("/")
                        mount_path = os.path.join(root, mountpoint)
                        if not os.path.exists(mount_path):
                            os.makedirs(mount_path)

            ops.start(name)
        except ops.InvocationError as e:
            report.die("LXC is broken, cannot start container %s: %s" % (name, e))
        except ops.ContainerNotFound as e:
            report.die("Container %s just disappeared, panic!" % name)
        try:
            running_flag = ops.get_box_home(name, "heaver_box_running")
            open(running_flag, "w").close()
        except Exception as e:
            pass # FIXME: should not happen, warn user/log?

	send_status_soft(args, config)
        print report.format(dict(status="OK", action="start", id=name,
            message="Container %s started" % name))
Example #39
0
def create(args, config, c):
    if not args.image:
        report.die(
            "Cannot create container without image (supply -i with image id)")

    if not args.name:
        report.die(
            "Cannot create container without name (supply -n with name)")

    if args.host:
        host = args.host
    else:
        host = None

    key = None
    if args.key:
        try:
            with open(args.key) as key_file:
                key = key_file.read()
        except Exception as e:
            report.die("Cannot read given key file: %s" % e)
    elif args.raw_key:
        key = args.raw_key

    net = args.net or []
    options = dict(net=net)
    if key is not None:
        options["key"] = key
    if args.limit is not None and len(args.limit) > 0:
        options["limit"] = args.limit
    try:
        container = c.create_container(args.name, args.image, host, options)
    except client.RequestError as e:
        print "Failed to create container!"
        print e
    else:
        print container
Example #40
0
File: main.py Project: ngsru/heaver
def must_be_root():
    "Be superuser or die"
    if os.geteuid() != 0:
        report.die("Must be root")
Example #41
0
File: main.py Project: ngsru/heaver
def must_parse_net_arg(arg):
    "Helper for parsing net args"
    if ":" not in arg:
        report.die("No bridge interface supplied")
    br_conf, _colon, addrs_str = arg.partition(":")
    if "/" in br_conf:
        br_dev, _slash, hwaddr = br_conf.partition("/")
        hwaddr = hwaddr.replace(".", "").lower()
        if len(hwaddr) > 12:
            report.die("Hardware address is too long (must be 12 hex digits)")
        elif len(hwaddr) < 12:
            report.die("Hardware address is too short (must be 12 hex digits)")
        else:
            for idx, char in enumerate(hwaddr):
                if not ("0" <= char <= "9" or "a" <= char <= "f"):
                    report.die(("Invalid character in hardware address "
                        "at position %d (only hex digits allowed)") % idx)

    else:
        br_dev = br_conf
        hwaddr = None

    if not os.path.exists(os.path.join("/sys/class/net/", br_dev)):
        report.die("No such device: %s" % br_dev)

    addrs = addrs_str.split(",")
    if not addrs:
        report.die("At least one address should be used (bridge %s)" % br_dev)

    ips = []
    for addr in addrs:
        if "/" not in addr:
            report.die("No netmask supplied for address %s" % addr)

        ip, mask = addr.split("/")
        try:
            addrpool.parse_address(ip)
        except:
            report.die("Invalid ip address: %s" % ip)

        try:
            int(mask)
        except:
            report.die("Invalid mask: %s" % mask)

        if not (32 >= int(mask) > 0):
            report.die("Mask is out of range: %s" % mask)

        ips.append((ip, mask))

    return br_dev, hwaddr, ips
Example #42
0
File: main.py Project: ngsru/heaver
def must_have_bridge(idx, config):
    "Die if haven't bridge for next network"
    if len(config["bridges"]) <= idx:
        report.die("Not enough bridges in config")
    return config["bridges"][idx]
Example #43
0
File: main.py Project: ngsru/heaver
def must_be_correct_net_config(config):
    "Check overall network setting and die if they are broken"
    # check that we can store used ranges
    if "used_ranges_path" not in config:
        report.die("\"used_ranges_path\" config value is missing in \"net\"")
    used_ranges_path = config["used_ranges_path"]
    if not isinstance(used_ranges_path, basestring):
        report.die("\"used_ranges_path\" must be string")
    if os.path.exists(used_ranges_path):
        if not os.access(used_ranges_path, os.W_OK):
            report.die("Used ranges file (%s) is not writeable" % used_ranges_path)
    elif not os.path.exists(os.path.dirname(used_ranges_path)):
        report.die(("Directory for used ranges file (%s) "
            "does not exist" % used_ranges_path))
    elif not os.access(os.path.dirname(used_ranges_path), os.W_OK):
            report.die(("Directory for used ranges file (%s) "
                "is not writeable" % used_ranges_path))

    networks = config.get("networks")
    if networks is None or not isinstance(networks, list):
        report.die("\"networks\" config value is missing in \"net\"")
    if len(networks) == 0:
        report.die("\"networks\" is empty. Configure at least one network")

    for idx, config in enumerate(networks):
        try:
            check_network_config(config)
        except Exception as e:
            report.die("malformed network config at index %d: %s" % (idx, e))
Example #44
0
File: main.py Project: ngsru/heaver
def create(args, config):
    must_be_root()
    if not args.name:
        report.die("No container chosen (create cannot be feed with --all)")
    if ops.exists(args.name):
        report.die("Container %s already exists" % args.name)

    if not args.root and not args.image:
        report.die("Either image or root must be given (-i or -r)")

    if "limits" not in config:
        report.die("No \"limits\" section in config")

    must_be_correct_limits_config(config["limits"])
    if args.limit is not None and len(args.limit) > 0:
        for limit in args.limit:
            name, _delim, value = limit.partition("=")
            config["limits"][name] = value
        # recheck config
        must_be_correct_limits_config(config["limits"])

    key = None
    if args.key:
        try:
            with open(args.key) as key_file:
                key = key_file.read()
        except Exception as e:
            report.die("Cannot read given key file: %s" % e)
    elif args.raw_key:
        key = args.raw_key

    root_generated = False
    data_mounts = []
    if args.root:
        root = args.root
    else:
        imager = image.get_image_operator(config["image"])
        try:
            images = []
            for img_arg in args.image:
                images.append(img_arg.split(":")[0])
            status = imager.sync_images(images)
            for img_name, img_status in status:
                if img_status == "error":
                    report.die("Cannot sync image '%s'" % img_name)
            # find root image (it's without additional path)
            root_images = filter(lambda img: not ":" in img or img.endswith(":/"), args.image)
            if len(root_images) == 0:
                report.die("No root image specified")

            if len(root_images) > 1:
                report.die("Only one root image may be used")
            root_image = root_images[0].split(":")[0]
            root = imager.create_instance(root_image, args.name)

            data_images = list(args.image)
            data_images.remove(root_images[0])

            for data_image in data_images:
                image_name, _semicolon, mountpoint = data_image.partition(":")
                data_root = imager.create_instance(image_name, args.name)
                data_mounts.append((mountpoint, data_root))

        except Exception as e:
            import traceback
            tb = traceback.format_exc()
            report.die("Cannot acquire root with image id '%s': %s\n%s" % (args.image, e, tb))
        root_generated = True

    if root[0] != "/":
        root = os.path.join(os.getcwd(), root)

    box_config = dict(root=root, networks=dict(), key=key, datamounts=data_mounts)
    # set up limits

    box_config["limits"] = config["limits"]
    box_config["raw"] = dict()
    if "cgroup" in config:
        for name, value in config["cgroup"].items():
            if name == "cpuset.cpus" and value == "auto":
                value = get_balanced_cpu()
            box_config["raw"]["cgroup." + name] = value

    # set up network
    all_ips = []
    if args.net is None:
        must_be_correct_net_config(config["net"])
        used_ranges = utils.sync_open(config["net"]["used_ranges_path"], "a+")
        networks = must_load_net_config(config["net"]["networks"],
                                        used_ranges.read().strip().split())
        args.net = [networks.items()[0][1]["bridge"]]
        used_ranges.close()

    if args.net or args.raw_net:
        must_be_correct_net_config(config["net"])
        used_ranges = utils.sync_open(config["net"]["used_ranges_path"], "a+")
        networks = must_load_net_config(config["net"]["networks"],
                                        used_ranges.read().strip().split())
        bridge_count = 0
        if args.raw_net is not None:
            bridge_count = len(args.raw_net)
            for idx, net in enumerate(args.raw_net):
                bridge, hwaddr, ips = must_parse_net_arg(net)
                for ip, mask in ips:
                    all_ips.append(ip)
                net_config = dict(type="veth", ips=ips, link=bridge, flags="up")
                if hwaddr:
                    net_config["hwaddr"] = hwaddr
                if idx == 0:
                    net_config["gateway"] = "auto"
                box_config["networks"]["eth%d" % idx] = net_config
        if args.net is not None:
            for idx, net in enumerate(args.net):
                net_idx = idx + bridge_count
                name, _semicolon, ip_count_str = net.partition(":")
                if name not in networks:
                    report.die("No such network: %s" % name)
                if ip_count_str != "":
                    try:
                        ip_count = int(ip_count_str)
                    except:
                        report.die("Ip count for network '%s' is not an int" % name)
                else:
                    ip_count = 1

                network = networks[name]
                hwaddr, ips = must_gen_net(network, ip_count)
                for ip, mask in ips:
                    all_ips.append(ip)
                bridge = network["bridge"]
                if net_idx == 0:
                    gateway = network.get("gateway")
                else:
                    gateway = None
                net_config = dict(type="veth", ips=ips, link=bridge, flags="up", gateway=gateway,
                                  hwaddr=hwaddr)
                box_config["networks"]["eth%d" % net_idx] = net_config

        # overwrite config
        used_ranges.truncate(0)
        used_ranges.write("\n".join(networks.values()[0]["pool"].dump_used_ranges()))
        used_ranges.write("\n") # trailing newline
        used_ranges.close()
    try:
        ops.create(args.name, box_config)
    except ops.InvalidConfig as e:
        report.die("Internal error, invalid config: %r" % e)

        import traceback
        print traceback.format_exc()

        if all_ips:
            try:
                free_addresses(config["net"]["used_ranges_path"], all_ips)
            except e:
                report.die("Failed to free addresses, do it yourself: %s" % e)
    except ops.CreationError as e:
        report.die("Cannot create container: %r" % e)

    except Exception as e:
        import traceback
        report.die("!!! Unhandled exception !!!\n%s\n%s" % (traceback.format_exc(), e))

    # if root was generated, remember it
    if root_generated:
        root_gen_path = ops.get_box_home(args.name, "heaver_root_generated")
        try:
            open(root_gen_path, "w").close()
        except Exception as e:
            pass #FIXME: warn user about it

    msg = dict(status="OK", action="create", id=args.name)
    if all_ips:
        msg["message"] = "Created container %s with addresses: %s" % (args.name,
            ", ".join(all_ips))
        msg["data"] = dict(ips=all_ips)
    else:
        msg["message"] = "Created container %s" % args.name
    
    # send status to upstream if possible
    send_status_soft(args, config)

    print report.format(msg)