示例#1
0
文件: main.py 项目: yherve/smc-script
def main():
    """entry point"""
    smcscript_dir = get_config_dir()

    logfile_path = os.path.join(smcscript_dir, "smcscript.log")
    # os.remove(logfile_path)

    logging.basicConfig(filename=logfile_path, level=logging.DEBUG)
    os.chmod(logfile_path, 0o600)

    logger.info('-' * 60)

    # if first argument is a file, we assume apply command
    if len(sys.argv) > 1 and os.path.isfile(sys.argv[1]):
        sys.argv.insert(1, 'apply')

    logger.info("Command: %s", ' '.join(sys.argv[1:]))

    parser = argh.ArghParser()
    parser.add_commands(cmd_list)
    try:
        parser.dispatch()

    # pylint: disable=broad-except
    except (CommandError, InvalidSessionError) as err:
        print_err("Error: {}", unicode(err))
        sys.exit(1)
    except Exception as e:
        print_err("Unexpected error '{}': {}\n(see {})",
                  type(e).__name__, e, logfile_path)
        logger.debug("Got unexpected exception: %s", type(e))
        logger.exception(e)
        sys.exit(1)
示例#2
0
文件: api.py 项目: yherve/smc-script
 def _merge_change():
     if xpath_expr:
         matching_nodes = elt.xpath(xpath_expr)
         if len(matching_nodes) != 1:
             print_err("error set: {}, number of nodes match: {} "\
                       "(should be exactly 1)", xpath_expr,
                       len(matching_nodes))
             return
         et_utils.elt_merge(update_elt, matching_nodes[0])
     else:
         et_utils.elt_merge(update_elt, elt)
示例#3
0
文件: api.py 项目: yherve/smc-script
        def _add_change():
            if xpath_expr is None:
                matching_nodes = [elt]
            else:
                matching_nodes = elt.xpath(xpath_expr)

            if len(matching_nodes) != 1:
                print_err("error adding: {}, number of nodes match: {} "\
                          "(should be exactly 1)", xpath_expr, len(matching_nodes))
                return
            for elt_to_add in elements:
                matching_nodes[0].append(elt_to_add)
示例#4
0
文件: api.py 项目: yherve/smc-script
        def _remove_change():
            matching_nodes = elt.xpath(xpath_expr)

            if not matching_nodes:
                print_err("error deleting {}: element not found", xpath_expr)
                return

            if len(matching_nodes) != 1:
                print_err("error deleting {}, number of elements found: {} "\
                          "(should be exactly 1)", xpath_expr, len(matching_nodes))
                return
            matching_nodes[0].getparent().remove(matching_nodes[0])
示例#5
0
def cmd_login(server, secure=False, port=None, api_key=None,
              version=None, ca_cert=None, smcrc=None, auto=False):
    """
    login to the smc (rest api)

    If a file is specified using '-f' or --file, it must have the following format:

    [smc]
    smc_address=192.168.100.7
    smc_apikey=xxxx
    api_version=6.4
    smc_port=8082
    smc_ssl=False
    verify_ssl=False
    ssl_cert_file=''

    """
    #todo tls

    if not server and not smcrc and not auto:
        raise CommandError("Must have either --file or <server> or --auto")

    if int(server is not None)+int(smcrc is not None)+int(auto) > 1:
        raise CommandError("Cannot have both <server> and/or --file and/or --auto")

    if server and not api_key:
        raise CommandError("missing --api-key")

    proto = "https" if secure else "http"
    url = "{proto}://{host}:{port}".format(host=server, port=port, proto=proto) \
                                                 if server else None

    verify = ca_cert or False
    sess = SMCSession()

    try:
        sess.login(url=url, api_key=api_key, verify=verify,
                   api_version = version,
                   alt_filepath=smcrc)
        #todo save to another place (env var)
        if not save_session(sess):
            print_err("Failed to save session")
        return "login successful"
    except SMCConnectionError as conn_error:
        logger.exception(conn_error)
        raise CommandError(
            "connection to '{}:{}' failed\n({})".format(server, port, conn_error))
示例#6
0
def do_update_elt(smc_client, target_hname, update_elt, print_only=False):
    """update a resource element in the smc

    :param SMCClient smc_client: client to send requests to smc
    :param etree.Element cmd_elt: element tree, example:

     update "#single_fw/myfw1" {
        add "//domain_server_addresses" {
            domain_server_address { value=8.8.4.4 rank=1.0 }
        }
    }

    :returns: None
    """

    try:
        smc_elt = smc_client.get(target_hname)
    except Exception as exc:
        logger.error(exc)
        return

    for operation in update_elt:

        if operation.tag == "set":
            xpath_expr = operation.text
            smc_elt.merge(xpath_expr, operation)

        elif operation.tag == "del":
            xpath_expr = operation.text
            smc_elt.remove(xpath_expr)

        elif operation.tag == "add":
            xpath_expr = operation.text
            smc_elt.add(xpath_expr, *list(operation))
        else:
            print_err("invalid update {}", operation.tag)
            return

    smc_client.update(smc_elt, print_only)
示例#7
0
def run_script(smc_client,
               filename,
               print_only=False,
               preprocess_only=False,
               user_variables=None,
               variable_files=None,
               ignore_errors=False,
               delete_mode=False,
               cleanup_mode=False):
    """execute a script

    :param SMCClient smc_client: client to send requests to smc
    :param str filename: name of the file containing the script
    :param bool print_only: does not execute the script. only print
    :param bool preprocess_only: show the script after the template preprocessing
    :param dict user_variables: dict of name/value used as variables for
    template preprocessing

    :returns: None

    :raises IOError: if filename could not be read
    :raises TemplateLookupException: failed to include a file
    :raises NameError: if a variable cannot be resolved
    :raises SyntaxException: syntax error during preprocessing
    :raises ElementConfError: failed to parse the filename (after processing)
    :raises InvalidSessionError: not logged in or session expired
    :raises SMCOperationFailure: is smc server responds with status_code error

    """

    api_version = smc_client.api_version
    variables = {'API_VERSION': api_version, 'SCRIPT': smc_client}

    lookup_dir = os.path.dirname(os.path.abspath(filename))
    var_config_file_name = lookup_dir + "/variables.cnf"
    logger.debug("var_config_file_name=%s", var_config_file_name)

    # default values from variables.cnf

    if os.path.isfile(var_config_file_name):
        logger.debug("opening =%s", var_config_file_name)
        var_elts = load_config_file(var_config_file_name)
        logger.debug("var_elts=%s", var_elts)
        for var_elt in var_elts:
            name = var_elt.get("name")
            value = var_elt.get("default")
            variables[name] = value
            logger.debug("VAR: %s=%s", name, value)

    # variables obtained from conf implicit file
    files = glob('*.cnfvars')
    for f in files:
        file_variables = read_variables_from_conf(f)
        variables.update(file_variables)

    # variables obtained from conf explicit file (--var-file)
    for f in variable_files:
        if not os.path.isfile(f):
            raise RunScriptError(
                "variable config file '{}' not found ".format(f))
        file_variables = read_variables_from_conf(f)
        variables.update(file_variables)

    # variables obtained from env.variables (take precedence from file)
    for name, value in os.environ.items():
        prefix = 'CNF_VAR_'
        if name.startswith(prefix):
            var_name = name[len(prefix):]
            variables[var_name] = value

    # variables obtained from command-line (take precedence from both
    # file and env.var)
    if user_variables:
        variables.update(user_variables)

    if preprocess_only:
        rendered = preprocess_config_file(filename, variables)
        print(rendered)
        return

    conf = load_config_file(filename, variables)

    if delete_mode or cleanup_mode:
        print("Cleaning up...")
        delete_all_resources(smc_client, conf)
        if delete_mode:
            return

    operations = dict(login=do_login,
                      logout=do_logout,
                      resource=do_create_elt,
                      delete=do_delete_elt,
                      update=do_update_elt,
                      command=do_execute,
                      get=do_execute)

    print("Applying config...")

    for elt in conf:
        operation = elt.tag
        target_hname = _get_target_hname(elt)

        if operation == 'resource':
            name = elt[0].attrib.get("name", "")
            op_text = "{} {}/{}...".format(operation, target_hname, name)
        else:
            op_text = "{} {}...".format(operation, target_hname)

        logging.info("script command: %s", op_text)
        print_fmt("- {}", op_text)
        if operation not in operations:
            raise RunScriptError("invalid operation: " + operation)
        fun = operations.get(operation)

        try:
            fun(smc_client, target_hname, elt, print_only)
        except (SMCOperationFailure, ResolveError) as exc:
            if ignore_errors:
                print_err(" => Ignoring error: {}", unicode(exc))
                continue
            raise SMCOperationFailure(unicode(exc))
    return