[ovs-dev,ovn,v2,1/2] Add ovn-appctl utility
diff mbox series

Message ID 20190910074257.23151-1-nusiddiq@redhat.com
State Accepted
Headers show
Series
  • [ovs-dev,ovn,v2,1/2] Add ovn-appctl utility
Related show

Commit Message

Numan Siddique Sept. 10, 2019, 7:42 a.m. UTC
From: Numan Siddique <nusiddiq@redhat.com>

Now that OVN has it's own rundir, "ovs-appctl -t ovn-controller/ovn-northd"
doesn't work. To fix this, ovn-appctl utility is added which
looks for the OVN pid/ctl files in the ovn rundir.

The code is taken from ovs-appctl.c and modified to use ovn_rundir()
instead of ovs_rundir().

Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
---
 rhel/ovn-fedora.spec.in    |   2 +
 utilities/.gitignore       |   2 +
 utilities/automake.mk      |  13 +-
 utilities/ovn-appctl.8.xml | 352 +++++++++++++++++++++++++++++++++++++
 utilities/ovn-appctl.c     | 239 +++++++++++++++++++++++++
 utilities/ovn-ctl          |  18 +-
 6 files changed, 615 insertions(+), 11 deletions(-)
 create mode 100644 utilities/ovn-appctl.8.xml
 create mode 100644 utilities/ovn-appctl.c

Comments

0-day Robot Sept. 10, 2019, 7:57 a.m. UTC | #1
Bleep bloop.  Greetings Numan Siddique, I am a robot and I have tried out your patch.
Thanks for your contribution.

I encountered some error that I wasn't expecting.  See the details below.


checkpatch:
WARNING: Line lacks whitespace around operator
WARNING: Line lacks whitespace around operator
#555 FILE: utilities/ovn-appctl.c:90:
  -t, --target=TARGET  pidfile or socket to contact\n\

WARNING: Line lacks whitespace around operator
#557 FILE: utilities/ovn-appctl.c:92:
  list-commands      List commands supported by the target\n\

WARNING: Line lacks whitespace around operator
#559 FILE: utilities/ovn-appctl.c:94:
  vlog/list          List current logging levels\n\

WARNING: Line lacks whitespace around operator
WARNING: Line lacks whitespace around operator
#560 FILE: utilities/ovn-appctl.c:95:
  vlog/list-pattern  List logging patterns for each destination.\n\

WARNING: Line lacks whitespace around operator
#561 FILE: utilities/ovn-appctl.c:96:
  vlog/set [SPEC]\n\

WARNING: Line lacks whitespace around operator
#566 FILE: utilities/ovn-appctl.c:101:
  vlog/reopen        Make the program reopen its log file\n\

WARNING: Line lacks whitespace around operator
WARNING: Line lacks whitespace around operator
#568 FILE: utilities/ovn-appctl.c:103:
  --timeout=SECS     wait at most SECS seconds for a response\n\

WARNING: Line lacks whitespace around operator
#570 FILE: utilities/ovn-appctl.c:105:
  -V, --version      Display ovn-appctl version information\n",

WARNING: Line is 113 characters long (recommended limit is 79)
#731 FILE: utilities/ovn-ctl:68:
        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`

WARNING: Line is 87 characters long (recommended limit is 79)
#732 FILE: utilities/ovn-ctl:69:
        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/connect-active-ovsdb-server

WARNING: Line is 113 characters long (recommended limit is 79)
#742 FILE: utilities/ovn-ctl:82:
        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`

WARNING: Line is 87 characters long (recommended limit is 79)
#743 FILE: utilities/ovn-ctl:83:
        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/connect-active-ovsdb-server

WARNING: Line is 86 characters long (recommended limit is 79)
#752 FILE: utilities/ovn-ctl:92:
    ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/disconnect-active-ovsdb-server

WARNING: Line is 86 characters long (recommended limit is 79)
#758 FILE: utilities/ovn-ctl:97:
    ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/disconnect-active-ovsdb-server

WARNING: Line is 98 characters long (recommended limit is 79)
#767 FILE: utilities/ovn-ctl:277:
    ovn-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status | awk '{if(NR==1) print $2}'

Lines checked: 773, Warnings: 18, Errors: 0


Please check this out.  If you feel there has been an error, please email aconole@redhat.com

Thanks,
0-day Robot
Mark Michelson Sept. 10, 2019, 6:07 p.m. UTC | #2
For the series,
Acked-by: Mark Michelson <mmichels@redhat.com>

On 9/10/19 3:42 AM, nusiddiq@redhat.com wrote:
> From: Numan Siddique <nusiddiq@redhat.com>
> 
> Now that OVN has it's own rundir, "ovs-appctl -t ovn-controller/ovn-northd"
> doesn't work. To fix this, ovn-appctl utility is added which
> looks for the OVN pid/ctl files in the ovn rundir.
> 
> The code is taken from ovs-appctl.c and modified to use ovn_rundir()
> instead of ovs_rundir().
> 
> Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
> ---
>   rhel/ovn-fedora.spec.in    |   2 +
>   utilities/.gitignore       |   2 +
>   utilities/automake.mk      |  13 +-
>   utilities/ovn-appctl.8.xml | 352 +++++++++++++++++++++++++++++++++++++
>   utilities/ovn-appctl.c     | 239 +++++++++++++++++++++++++
>   utilities/ovn-ctl          |  18 +-
>   6 files changed, 615 insertions(+), 11 deletions(-)
>   create mode 100644 utilities/ovn-appctl.8.xml
>   create mode 100644 utilities/ovn-appctl.c
> 
> diff --git a/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in
> index 14035de9a..9ee807fab 100644
> --- a/rhel/ovn-fedora.spec.in
> +++ b/rhel/ovn-fedora.spec.in
> @@ -430,6 +430,7 @@ fi
>   %{_bindir}/ovn-sbctl
>   %{_bindir}/ovn-trace
>   %{_bindir}/ovn-detrace
> +%{_bindir}/ovn-appctl
>   %{_datadir}/ovn/scripts/ovn-ctl
>   %{_datadir}/ovn/scripts/ovn-lib
>   %{_datadir}/ovn/scripts/ovndb-servers.ocf
> @@ -440,6 +441,7 @@ fi
>   %{_mandir}/man8/ovn-nbctl.8*
>   %{_mandir}/man8/ovn-trace.8*
>   %{_mandir}/man1/ovn-detrace.1*
> +%{_mandir}/man8/ovn-appctl.8*
>   #%{_mandir}/man7/ovn-architecture.7* - Uncomment this once the manpage is fixed
>   %{_mandir}/man8/ovn-sbctl.8*
>   #%{_mandir}/man5/ovn-nb.5* - Uncomment this once the manpage is fixed
> diff --git a/utilities/.gitignore b/utilities/.gitignore
> index 1d01e0b28..b319e8366 100644
> --- a/utilities/.gitignore
> +++ b/utilities/.gitignore
> @@ -3,6 +3,8 @@
>   /ovn-nbctl.8
>   /ovn-sbctl
>   /ovn-sbctl.8
> +/ovn-appctl
> +/ovn-appctl.8
>   /ovn-trace
>   /ovn-trace.8
>   /ovn-detrace
> diff --git a/utilities/automake.mk b/utilities/automake.mk
> index 21dd8ccdf..ab0f6003a 100644
> --- a/utilities/automake.mk
> +++ b/utilities/automake.mk
> @@ -8,7 +8,8 @@ man_MANS += \
>       utilities/ovn-nbctl.8 \
>       utilities/ovn-sbctl.8 \
>       utilities/ovn-trace.8 \
> -    utilities/ovn-detrace.1
> +    utilities/ovn-detrace.1 \
> +    utilities/ovn-appctl.8
>   
>   MAN_ROOTS += \
>       utilities/ovn-sbctl.8.in \
> @@ -27,6 +28,7 @@ EXTRA_DIST += \
>       utilities/ovn-docker-overlay-driver.in \
>       utilities/ovn-docker-underlay-driver.in \
>       utilities/ovn-nbctl.8.xml \
> +    utilities/ovn-appctl.8.xml \
>       utilities/ovn-trace.8.xml \
>       utilities/ovn-detrace.in \
>       utilities/ovndb-servers.ocf \
> @@ -49,7 +51,9 @@ CLEANFILES += \
>       utilities/ovn-sbctl.8 \
>       utilities/ovn-trace.8 \
>       utilities/ovn-detrace.1 \
> -    utilities/ovn-detrace
> +    utilities/ovn-detrace \
> +    utilities/ovn-appctl.8 \
> +    utilities/ovn-appctl
>   
>   utilities/ovn-lib: $(top_builddir)/config.status
>   
> @@ -68,4 +72,9 @@ bin_PROGRAMS += utilities/ovn-trace
>   utilities_ovn_trace_SOURCES = utilities/ovn-trace.c
>   utilities_ovn_trace_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la
>   
> +# ovn-nbctl
> +bin_PROGRAMS += utilities/ovn-appctl
> +utilities_ovn_appctl_SOURCES = utilities/ovn-appctl.c
> +utilities_ovn_appctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la
> +
>   include utilities/bugtool/automake.mk
> diff --git a/utilities/ovn-appctl.8.xml b/utilities/ovn-appctl.8.xml
> new file mode 100644
> index 000000000..32a42a766
> --- /dev/null
> +++ b/utilities/ovn-appctl.8.xml
> @@ -0,0 +1,352 @@
> +<?xml version="1.0" encoding="utf-8"?>
> +<manpage program="ovn-appctl" section="8" title="ovn-appctl">
> +    <h1>Name</h1>
> +    <p>ovn-appctl -- utility for configuring running OVN daemons</p>
> +
> +    <h1>Synopsis</h1>
> +    <p>
> +      <code> ovn-appctl</code> [--target=target | -t target]
> +      [-T secs | --timeout=secs] <var>command</var> [<var>arg</var>...]
> +    </p>
> +    <p><code>ovn-appctl</code> --help </p>
> +    <p><code>ovn-appctl</code> --version </p>
> +
> +    <h1>Description</h1>
> +    <p>
> +      OVN daemons accept certain commands at runtime to control their behavior
> +      and query their settings. Every daemon accepts a common set of commands
> +      documented under COMMON COMMANDS below. Some daemons support additional
> +      commands documented in their own manpages.
> +    </p>
> +
> +    <p>
> +       The <code>ovn-appctl</code> program provides a simple way to invoke
> +       these commands. The command to be sent is specified on
> +       <code>ovn-appctl's</code> command line as non-option arguments.
> +       <code>ovn-appctl</code> sends the command and prints the daemon's
> +       response on standard output.
> +    </p>
> +
> +    <p>
> +      <code>ovn-ctl</code> is exactly similar to Open vSwitch
> +      <code>ovs-appctl</code> utility.
> +    </p>
> +
> +    <h1>Command Commands</h1>
> +    <p>
> +      Every OVN daemon supports a common set of commands, which are documented
> +      in this section.
> +    </p>
> +
> +    <h2>General Commands</h2>
> +    <p>
> +      These commands display daemon-specific commands and the running version.
> +      Note that these commands are different from the --help and --version
> +      options that return information about the <code>ovn-appctl</code>
> +      utility itself.
> +    </p>
> +
> +    <dl>
> +      <dt><code>list-commands</code></dt>
> +      <dd>
> +        Lists the commands supported by the target.
> +      </dd>
> +
> +      <dt><code>version</code></dt>
> +      <dd>
> +        Displays the version and compilation date of the target.
> +      </dd>
> +    </dl>
> +
> +    <h2>Logging Commands</h2>
> +    <p>
> +      OVN has several log levels.  The highest-severity log level is:
> +    </p>
> +
> +    <dl>
> +      <dt><code>off</code></dt>
> +      <dd>
> +        No message is ever logged at this level, so setting a logging
> +        destination's log level to off disables logging to that
> +        destination.
> +      </dd>
> +    </dl>
> +
> +    <p>
> +      The following log levels, in order of descending severity, are
> +      available:
> +    </p>
> +
> +    <dl>
> +      <dt><code>emer</code></dt>
> +      <dd>
> +        A major failure forced a process to abort.
> +      </dd>
> +
> +      <dt><code>err</code></dt>
> +      <dd>
> +        A high-level operation or a subsystem failed.  Attention is warranted.
> +      </dd>
> +
> +      <dt><code>warn</code></dt>
> +      <dd>
> +        A low-level operation failed, but higher-level subsystems may be able
> +        to recover.
> +      </dd>
> +
> +      <dt><code>info</code></dt>
> +      <dd>
> +        Information that may be useful in retrospect when investigating a
> +        problem.
> +      </dd>
> +
> +      <dt><code>dbg</code></dt>
> +      <dd>
> +        Information useful only to someone with intricate knowledge of the
> +        system, or that would commonly cause too-voluminous log output.
> +        Log messages at this level are not logged by default.
> +      </dd>
> +    </dl>
> +
> +    <p>
> +      Every OVN daemon supports the following commands for examining and
> +      adjusting log levels.
> +    </p>
> +
> +    <dl>
> +      <dt><code>vlog/list</code></dt>
> +      <dd>
> +        Lists the known logging modules and their current levels.
> +      </dd>
> +
> +      <dt><code>vlog/list-pattern</code></dt>
> +      <dd>
> +        Lists logging pattern used for each destination.
> +      </dd>
> +
> +      <dt><code>vlog/set <var>[spec]</var></code></dt>
> +      <dd>
> +        Sets logging levels. Without any spec, sets the log level for every
> +        module and destination to dbg. Otherwise, spec is a list of words
> +        separated by spaces or commas or colons, up to one from each
> +        category below:
> +        <ul>
> +          <li>
> +            A valid module name, as displayed by the vlog/list command on
> +            ovn-appctl(8), limits the log level change to the specified module.
> +          </li>
> +
> +          <li>
> +            <p>
> +              <code>syslog</code>, <code>console</code>, or <code>file</code>,
> +              to limit the log level change to only to the system log, to the
> +              console, or to a file, respectively.
> +            </p>
> +
> +            <p>
> +              On Windows platform, <code>syslog</code> is accepted as a word
> +              and is only useful if the target was started with the
> +              <code>--syslog-target</code> option (the word has no effect
> +              otherwise).
> +            </p>
> +          </li>
> +
> +          <li>
> +            <code>off</code>, <code>emer</code>, <code>err</code>,
> +            <code>warn</code>, <code>info</code>, or <code>dbg</code>, to
> +            control the log level.  Messages of the given severity or higher
> +            will be logged, and messages of lower severity will be filtered
> +            out. <code>off</code> filters out all messages.
> +          </li>
> +        </ul>
> +
> +        <p>
> +          Case is not significant within <var>spec</var>.
> +        </p>
> +      </dd>
> +
> +      <dt>
> +        <code>vlog/set PATTERN</code>:<var>destination</var>:
> +        <var>pattern</var>
> +      </dt>
> +      <dd>
> +        Sets the log pattern for <var>destination</var> to <var>pattern</var>.
> +        Each time a message is logged to destination, pattern determines the
> +        message's formatting. Most characters in pattern are copied literally
> +        to the log, but special escapes beginning with <code>%</code> are
> +        expanded as follows:
> +
> +        <ul>
> +          <li>
> +            <code>%A</code> : The name of the application logging the
> +            message, e.g. ovn-controller.
> +          </li>
> +
> +          <li>
> +            <code>%B</code> : The RFC5424 syslog PRI of the message.
> +          </li>
> +
> +          <li>
> +            <code>%c</code> : The name of the module
> +            (as shown by ovn-appctl --list) logging the message.
> +          </li>
> +
> +          <li>
> +            <code>%d</code> : The current date and time in ISO 8601 format
> +            (YYYY-MM-DD HH:MM:SS).
> +          </li>
> +
> +          <li>
> +            <code>%d<var>{format}</var></code> : The  current  date and time in
> +            the specified format, which takes the same format as the template
> +            argument to strftime(3). As an extension, any # characters in
> +            format will be replaced by fractional seconds, e.g. use
> +            <code>%H:%M:%S.###</code> for the time to the nearest millisecond.
> +            Sub-second times are only approximate and currently decimal places
> +            after the third will always be reported as zero.
> +          </li>
> +
> +          <li>
> +            <code>%D</code> : The current UTC date and time in ISO 8601 format
> +            <code>(YYYY-MM-DD HH:MM:SS)</code>.
> +          </li>
> +
> +          <li>
> +            <code>%D<var>{format}</var></code> : The current UTC date and time
> +            in the specified format, which takes the same format as the
> +            template argument to strftime(3). Supports the same extension for
> +            sub-second resolution as <code>%d{...}</code>.
> +          </li>
> +
> +          <li>
> +            <code>%E</code> : The hostname of the node running the application.
> +          </li>
> +
> +          <li>
> +            <code>%m</code> : The message being logged.
> +          </li>
> +
> +          <li>
> +            <code>%N</code> : A serial number for this message within this run
> +            of the program, as a decimal number. The first message a program
> +            logs has serial number 1, the second one has serial number 2,
> +            and so on.
> +          </li>
> +
> +          <li>
> +            <code>%n</code> : A new-line.
> +          </li>
> +
> +          <li>
> +            <code>%p</code> : The level at which the message is logged, e.g.
> +            <code>DBG</code>.
> +          </li>
> +
> +          <li>
> +            <code>%P</code> : The program's process ID (pid), as a decimal
> +            number.
> +          </li>
> +
> +          <li>
> +            <code>%r</code> : The number of milliseconds elapsed from the start
> +            of the application to the time the message was logged.
> +          </li>
> +
> +          <li>
> +            <code>%t</code> : The subprogram name, that is, an identifying name
> +            for the process or thread that emitted the log message, such as
> +            monitor for the process used for --monitor or main for the primary
> +            process or thread in a program.
> +          </li>
> +
> +          <li>
> +            <code>%T</code> : The subprogram name enclosed in parentheses, e.g.
> +            (monitor), or the empty string for the primary process or thread in
> +            a program.
> +          </li>
> +
> +          <li>
> +            <code>%%</code> : A literal %.
> +          </li>
> +        </ul>
> +
> +        <p>
> +          A few options may appear between the % and the format specifier
> +          character, in this order:
> +        </p>
> +
> +        <ul>
> +        <li>
> +          <code>-</code> : Left justify the escape's expansion within its field
> +          width. Right justification is the default.
> +        </li>
> +
> +        <li>
> +          <code>-</code> : Pad the field to the field width with 0s.  Padding
> +          with spaces is the default.
> +        </li>
> +        </ul>
> +
> +        <p>
> +          <var>width</var>  A number specifies the minimum field width. If the
> +          escape expands to fewer characters than width then it is padded to
> +          fill the field width. (A field wider than width is not truncated to
> +          fit.)
> +        </p>
> +
> +        <p>
> +          The default pattern for console and file output is
> +          <code>%D{%Y-%m-%dT %H:%M:%SZ}|%05N|%c|%p|%m;</code> for syslog
> +          output, <code>%05N|%c|%p|%m</code>.
> +        </p>
> +      </dd>
> +
> +      <dt><code>vlog/set FACILITY:<var>facility</var></code></dt>
> +      <dd>
> +        Sets the RFC5424 facility of the log message. facility can be one of
> +        <code>kern</code>, <code>user</code>, <code>mail</code>,
> +        <code>daemon</code>, <code>auth</code>, <code>syslog</code>,
> +        <code>lpr</code>, <code>news</code>, <code>uucp</code>,
> +        <code>clock</code>, <code>ftp</code>, <code>ntp</code>,
> +        <code>audit</code>, <code>alert</code>, <code>clock2</code>,
> +        <code>local0</code>, <code>local1</code>, <code>local2</code>,
> +        <code>local3</code>, <code>local4</code>, <code>local5</code>,
> +        <code>local6</code> or <code>local7</code>.
> +      </dd>
> +
> +      <dt><code>vlog/close</code></dt>
> +      <dd>
> +        Causes the daemon to close its log file, if it is open.
> +        (Use <code>vlog/reopen</code> to reopen it later.)
> +      </dd>
> +
> +      <dt><code>vlog/reopen</code></dt>
> +      <dd>
> +        <p>
> +          Causes the daemon to close its log file, if it is open, and then
> +          reopen it. (This is useful after rotating log files, to cause a
> +          new log file to be used.)
> +        </p>
> +
> +        <p>
> +          This has no effect if the target application was not invoked
> +          with the <code>--log-file</code> option.
> +        </p>
> +      </dd>
> +    </dl>
> +
> +    <h1>Options</h1>
> +    <dl>
> +      <dt><code>-h</code></dt>
> +      <dt><code>--help</code></dt>
> +      <dd>
> +        Prints a brief help message to the console.
> +      </dd>
> +
> +      <dt><code>-V</code></dt>
> +      <dt><code>--version</code></dt>
> +      <dd>
> +        Prints version information to the console.
> +      </dd>
> +    </dl>
> +</manpage>
> \ No newline at end of file
> diff --git a/utilities/ovn-appctl.c b/utilities/ovn-appctl.c
> new file mode 100644
> index 000000000..ffd30b452
> --- /dev/null
> +++ b/utilities/ovn-appctl.c
> @@ -0,0 +1,239 @@
> +/*
> + * Copyright (c) 2019 Nicira, Inc.
> + *
> + * Licensed under the Apache License, Version 2.0 (the "License");
> + * you may not use this file except in compliance with the License.
> + * You may obtain a copy of the License at:
> + *
> + *     http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing, software
> + * distributed under the License is distributed on an "AS IS" BASIS,
> + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + * See the License for the specific language governing permissions and
> + * limitations under the License.
> + */
> +
> +#include <config.h>
> +
> +#include <errno.h>
> +#include <getopt.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <stdlib.h>
> +
> +#include "command-line.h"
> +#include "daemon.h"
> +#include "lib/ovn-dirs.h"
> +#include "openvswitch/dynamic-string.h"
> +#include "jsonrpc.h"
> +#include "process.h"
> +#include "timeval.h"
> +#include "unixctl.h"
> +#include "util.h"
> +#include "openvswitch/vlog.h"
> +
> +static void usage(void);
> +static const char *parse_command_line(int argc, char *argv[]);
> +static struct jsonrpc *connect_to_target(const char *target);
> +
> +int
> +main(int argc, char *argv[])
> +{
> +    char *cmd_result, *cmd_error;
> +    struct jsonrpc *client;
> +    char *cmd, **cmd_argv;
> +    const char *target;
> +    int cmd_argc;
> +    int error;
> +
> +    set_program_name(argv[0]);
> +
> +    /* Parse command line and connect to target. */
> +    target = parse_command_line(argc, argv);
> +    client = connect_to_target(target);
> +
> +    /* Transact request and process reply. */
> +    cmd = argv[optind++];
> +    cmd_argc = argc - optind;
> +    cmd_argv = cmd_argc ? argv + optind : NULL;
> +    error = unixctl_client_transact(client, cmd, cmd_argc, cmd_argv,
> +                                    &cmd_result, &cmd_error);
> +    if (error) {
> +        ovs_fatal(error, "%s: transaction error", target);
> +    }
> +
> +    if (cmd_error) {
> +        jsonrpc_close(client);
> +        fputs(cmd_error, stderr);
> +        ovs_error(0, "%s: server returned an error", target);
> +        exit(2);
> +    } else if (cmd_result) {
> +        fputs(cmd_result, stdout);
> +    } else {
> +        OVS_NOT_REACHED();
> +    }
> +
> +    jsonrpc_close(client);
> +    free(cmd_result);
> +    free(cmd_error);
> +    return 0;
> +}
> +
> +static void
> +usage(void)
> +{
> +    printf("\
> +%s, for querying and controlling OVN daemon\n\
> +usage: %s [TARGET] COMMAND [ARG...]\n\
> +Targets:\n\
> +  -t, --target=TARGET  pidfile or socket to contact\n\
> +Common commands:\n\
> +  list-commands      List commands supported by the target\n\
> +  version            Print version of the target\n\
> +  vlog/list          List current logging levels\n\
> +  vlog/list-pattern  List logging patterns for each destination.\n\
> +  vlog/set [SPEC]\n\
> +      Set log levels as detailed in SPEC, which may include:\n\
> +      A valid module name (all modules, by default)\n\
> +      'syslog', 'console', 'file' (all destinations, by default))\n\
> +      'off', 'emer', 'err', 'warn', 'info', or 'dbg' ('dbg', bydefault)\n\
> +  vlog/reopen        Make the program reopen its log file\n\
> +Other options:\n\
> +  --timeout=SECS     wait at most SECS seconds for a response\n\
> +  -h, --help         Print this helpful information\n\
> +  -V, --version      Display ovn-appctl version information\n",
> +           program_name, program_name);
> +    exit(EXIT_SUCCESS);
> +}
> +
> +static const char *
> +parse_command_line(int argc, char *argv[])
> +{
> +    enum {
> +        OPT_START = UCHAR_MAX + 1,
> +        VLOG_OPTION_ENUMS
> +    };
> +    static const struct option long_options[] = {
> +        {"target", required_argument, NULL, 't'},
> +        {"execute", no_argument, NULL, 'e'},
> +        {"help", no_argument, NULL, 'h'},
> +        {"option", no_argument, NULL, 'o'},
> +        {"version", no_argument, NULL, 'V'},
> +        {"timeout", required_argument, NULL, 'T'},
> +        VLOG_LONG_OPTIONS,
> +        {NULL, 0, NULL, 0},
> +    };
> +    char *short_options_ =
> +        ovs_cmdl_long_options_to_short_options(long_options);
> +    char *short_options = xasprintf("+%s", short_options_);
> +    const char *target;
> +    int e_options;
> +    unsigned int timeout = 0;
> +
> +    target = NULL;
> +    e_options = 0;
> +    for (;;) {
> +        int option;
> +
> +        option = getopt_long(argc, argv, short_options, long_options, NULL);
> +        if (option == -1) {
> +            break;
> +        }
> +        switch (option) {
> +        case 't':
> +            if (target) {
> +                ovs_fatal(0, "-t or --target may be specified only once");
> +            }
> +            target = optarg;
> +            break;
> +
> +        case 'e':
> +            /* We ignore -e for compatibility.  Older versions specified the
> +             * command as the argument to -e.  Since the current version takes
> +             * the command as non-option arguments and we say that -e has no
> +             * arguments, this just works in the common case. */
> +            if (e_options++) {
> +                ovs_fatal(0, "-e or --execute may be speciifed only once");
> +            }
> +            break;
> +
> +        case 'h':
> +            usage();
> +            break;
> +
> +        case 'o':
> +            ovs_cmdl_print_options(long_options);
> +            exit(EXIT_SUCCESS);
> +
> +        case 'T':
> +            if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> +                ovs_fatal(0, "value %s on -T or --timeout is invalid", optarg);
> +            }
> +            break;
> +
> +        case 'V':
> +            ovs_print_version(0, 0);
> +            exit(EXIT_SUCCESS);
> +
> +        VLOG_OPTION_HANDLERS
> +
> +        case '?':
> +            exit(EXIT_FAILURE);
> +
> +        default:
> +            OVS_NOT_REACHED();
> +        }
> +    }
> +    free(short_options_);
> +    free(short_options);
> +
> +    ctl_timeout_setup(timeout);
> +
> +    if (optind >= argc) {
> +        ovs_fatal(0, "at least one non-option argument is required "
> +                  "(use --help for help)");
> +    }
> +
> +    return target ? target : "ovn-controller";
> +}
> +
> +static struct jsonrpc *
> +connect_to_target(const char *target)
> +{
> +    struct jsonrpc *client;
> +    char *socket_name;
> +    int error;
> +
> +#ifndef _WIN32
> +    if (target[0] != '/') {
> +        char *pidfile_name;
> +        pid_t pid;
> +
> +        pidfile_name = xasprintf("%s/%s.pid", ovn_rundir(), target);
> +        pid = read_pidfile(pidfile_name);
> +        if (pid < 0) {
> +            ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
> +        }
> +        free(pidfile_name);
> +        socket_name = xasprintf("%s/%s.%ld.ctl",
> +                                ovn_rundir(), target, (long int) pid);
> +#else
> +    /* On windows, if the 'target' contains ':', we make an assumption that
> +     * it is an absolute path. */
> +    if (!strchr(target, ':')) {
> +        socket_name = xasprintf("%s/%s.ctl", ovn_rundir(), target);
> +#endif
> +    } else {
> +        socket_name = xstrdup(target);
> +    }
> +
> +    error = unixctl_client_create(socket_name, &client);
> +    if (error) {
> +        ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
> +    }
> +    free(socket_name);
> +
> +    return client;
> +}
> +
> diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl
> index c955aa177..4242cd2c8 100755
> --- a/utilities/ovn-ctl
> +++ b/utilities/ovn-ctl
> @@ -44,13 +44,13 @@ pidfile_is_running () {
>   
>   stop_nb_ovsdb() {
>       if pidfile_is_running $DB_NB_PID; then
> -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
> +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
>       fi
>   }
>   
>   stop_sb_ovsdb() {
>       if pidfile_is_running $DB_SB_PID; then
> -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
> +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
>       fi
>   }
>   
> @@ -65,8 +65,8 @@ demote_ovnnb() {
>       fi
>   
>       if test -e $ovnnb_active_conf_file; then
> -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
> -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/connect-active-ovsdb-server
> +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
> +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/connect-active-ovsdb-server
>       else
>           echo >&2 "$0: active server details not set"
>           exit 1
> @@ -79,8 +79,8 @@ demote_ovnsb() {
>       fi
>   
>       if test -e $ovnsb_active_conf_file; then
> -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
> -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/connect-active-ovsdb-server
> +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
> +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/connect-active-ovsdb-server
>       else
>           echo >&2 "$0: active server details not set"
>           exit 1
> @@ -89,12 +89,12 @@ demote_ovnsb() {
>   
>   promote_ovnnb() {
>       rm -f $ovnnb_active_conf_file
> -    ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
> +    ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
>   }
>   
>   promote_ovnsb() {
>       rm -f $ovnsb_active_conf_file
> -    ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
> +    ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
>   }
>   
>   start_ovsdb__() {
> @@ -274,7 +274,7 @@ start_ovsdb () {
>   }
>   
>   sync_status() {
> -    ovs-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status | awk '{if(NR==1) print $2}'
> +    ovn-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status | awk '{if(NR==1) print $2}'
>   }
>   
>   status_ovnnb() {
>
Numan Siddique Sept. 11, 2019, 7:23 a.m. UTC | #3
On Tue, Sep 10, 2019 at 11:37 PM Mark Michelson <mmichels@redhat.com> wrote:

> For the series,
> Acked-by: Mark Michelson <mmichels@redhat.com>
>

Thanks.
I applied this series to master.

Numan


>
> On 9/10/19 3:42 AM, nusiddiq@redhat.com wrote:
> > From: Numan Siddique <nusiddiq@redhat.com>
> >
> > Now that OVN has it's own rundir, "ovs-appctl -t
> ovn-controller/ovn-northd"
> > doesn't work. To fix this, ovn-appctl utility is added which
> > looks for the OVN pid/ctl files in the ovn rundir.
> >
> > The code is taken from ovs-appctl.c and modified to use ovn_rundir()
> > instead of ovs_rundir().
> >
> > Signed-off-by: Numan Siddique <nusiddiq@redhat.com>
> > ---
> >   rhel/ovn-fedora.spec.in    |   2 +
> >   utilities/.gitignore       |   2 +
> >   utilities/automake.mk      |  13 +-
> >   utilities/ovn-appctl.8.xml | 352 +++++++++++++++++++++++++++++++++++++
> >   utilities/ovn-appctl.c     | 239 +++++++++++++++++++++++++
> >   utilities/ovn-ctl          |  18 +-
> >   6 files changed, 615 insertions(+), 11 deletions(-)
> >   create mode 100644 utilities/ovn-appctl.8.xml
> >   create mode 100644 utilities/ovn-appctl.c
> >
> > diff --git a/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in
> > index 14035de9a..9ee807fab 100644
> > --- a/rhel/ovn-fedora.spec.in
> > +++ b/rhel/ovn-fedora.spec.in
> > @@ -430,6 +430,7 @@ fi
> >   %{_bindir}/ovn-sbctl
> >   %{_bindir}/ovn-trace
> >   %{_bindir}/ovn-detrace
> > +%{_bindir}/ovn-appctl
> >   %{_datadir}/ovn/scripts/ovn-ctl
> >   %{_datadir}/ovn/scripts/ovn-lib
> >   %{_datadir}/ovn/scripts/ovndb-servers.ocf
> > @@ -440,6 +441,7 @@ fi
> >   %{_mandir}/man8/ovn-nbctl.8*
> >   %{_mandir}/man8/ovn-trace.8*
> >   %{_mandir}/man1/ovn-detrace.1*
> > +%{_mandir}/man8/ovn-appctl.8*
> >   #%{_mandir}/man7/ovn-architecture.7* - Uncomment this once the manpage
> is fixed
> >   %{_mandir}/man8/ovn-sbctl.8*
> >   #%{_mandir}/man5/ovn-nb.5* - Uncomment this once the manpage is fixed
> > diff --git a/utilities/.gitignore b/utilities/.gitignore
> > index 1d01e0b28..b319e8366 100644
> > --- a/utilities/.gitignore
> > +++ b/utilities/.gitignore
> > @@ -3,6 +3,8 @@
> >   /ovn-nbctl.8
> >   /ovn-sbctl
> >   /ovn-sbctl.8
> > +/ovn-appctl
> > +/ovn-appctl.8
> >   /ovn-trace
> >   /ovn-trace.8
> >   /ovn-detrace
> > diff --git a/utilities/automake.mk b/utilities/automake.mk
> > index 21dd8ccdf..ab0f6003a 100644
> > --- a/utilities/automake.mk
> > +++ b/utilities/automake.mk
> > @@ -8,7 +8,8 @@ man_MANS += \
> >       utilities/ovn-nbctl.8 \
> >       utilities/ovn-sbctl.8 \
> >       utilities/ovn-trace.8 \
> > -    utilities/ovn-detrace.1
> > +    utilities/ovn-detrace.1 \
> > +    utilities/ovn-appctl.8
> >
> >   MAN_ROOTS += \
> >       utilities/ovn-sbctl.8.in \
> > @@ -27,6 +28,7 @@ EXTRA_DIST += \
> >       utilities/ovn-docker-overlay-driver.in \
> >       utilities/ovn-docker-underlay-driver.in \
> >       utilities/ovn-nbctl.8.xml \
> > +    utilities/ovn-appctl.8.xml \
> >       utilities/ovn-trace.8.xml \
> >       utilities/ovn-detrace.in \
> >       utilities/ovndb-servers.ocf \
> > @@ -49,7 +51,9 @@ CLEANFILES += \
> >       utilities/ovn-sbctl.8 \
> >       utilities/ovn-trace.8 \
> >       utilities/ovn-detrace.1 \
> > -    utilities/ovn-detrace
> > +    utilities/ovn-detrace \
> > +    utilities/ovn-appctl.8 \
> > +    utilities/ovn-appctl
> >
> >   utilities/ovn-lib: $(top_builddir)/config.status
> >
> > @@ -68,4 +72,9 @@ bin_PROGRAMS += utilities/ovn-trace
> >   utilities_ovn_trace_SOURCES = utilities/ovn-trace.c
> >   utilities_ovn_trace_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la
> $(OVS_LIBDIR)/libopenvswitch.la
> >
> > +# ovn-nbctl
> > +bin_PROGRAMS += utilities/ovn-appctl
> > +utilities_ovn_appctl_SOURCES = utilities/ovn-appctl.c
> > +utilities_ovn_appctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la
> $(OVS_LIBDIR)/libopenvswitch.la
> > +
> >   include utilities/bugtool/automake.mk
> > diff --git a/utilities/ovn-appctl.8.xml b/utilities/ovn-appctl.8.xml
> > new file mode 100644
> > index 000000000..32a42a766
> > --- /dev/null
> > +++ b/utilities/ovn-appctl.8.xml
> > @@ -0,0 +1,352 @@
> > +<?xml version="1.0" encoding="utf-8"?>
> > +<manpage program="ovn-appctl" section="8" title="ovn-appctl">
> > +    <h1>Name</h1>
> > +    <p>ovn-appctl -- utility for configuring running OVN daemons</p>
> > +
> > +    <h1>Synopsis</h1>
> > +    <p>
> > +      <code> ovn-appctl</code> [--target=target | -t target]
> > +      [-T secs | --timeout=secs] <var>command</var> [<var>arg</var>...]
> > +    </p>
> > +    <p><code>ovn-appctl</code> --help </p>
> > +    <p><code>ovn-appctl</code> --version </p>
> > +
> > +    <h1>Description</h1>
> > +    <p>
> > +      OVN daemons accept certain commands at runtime to control their
> behavior
> > +      and query their settings. Every daemon accepts a common set of
> commands
> > +      documented under COMMON COMMANDS below. Some daemons support
> additional
> > +      commands documented in their own manpages.
> > +    </p>
> > +
> > +    <p>
> > +       The <code>ovn-appctl</code> program provides a simple way to
> invoke
> > +       these commands. The command to be sent is specified on
> > +       <code>ovn-appctl's</code> command line as non-option arguments.
> > +       <code>ovn-appctl</code> sends the command and prints the daemon's
> > +       response on standard output.
> > +    </p>
> > +
> > +    <p>
> > +      <code>ovn-ctl</code> is exactly similar to Open vSwitch
> > +      <code>ovs-appctl</code> utility.
> > +    </p>
> > +
> > +    <h1>Command Commands</h1>
> > +    <p>
> > +      Every OVN daemon supports a common set of commands, which are
> documented
> > +      in this section.
> > +    </p>
> > +
> > +    <h2>General Commands</h2>
> > +    <p>
> > +      These commands display daemon-specific commands and the running
> version.
> > +      Note that these commands are different from the --help and
> --version
> > +      options that return information about the <code>ovn-appctl</code>
> > +      utility itself.
> > +    </p>
> > +
> > +    <dl>
> > +      <dt><code>list-commands</code></dt>
> > +      <dd>
> > +        Lists the commands supported by the target.
> > +      </dd>
> > +
> > +      <dt><code>version</code></dt>
> > +      <dd>
> > +        Displays the version and compilation date of the target.
> > +      </dd>
> > +    </dl>
> > +
> > +    <h2>Logging Commands</h2>
> > +    <p>
> > +      OVN has several log levels.  The highest-severity log level is:
> > +    </p>
> > +
> > +    <dl>
> > +      <dt><code>off</code></dt>
> > +      <dd>
> > +        No message is ever logged at this level, so setting a logging
> > +        destination's log level to off disables logging to that
> > +        destination.
> > +      </dd>
> > +    </dl>
> > +
> > +    <p>
> > +      The following log levels, in order of descending severity, are
> > +      available:
> > +    </p>
> > +
> > +    <dl>
> > +      <dt><code>emer</code></dt>
> > +      <dd>
> > +        A major failure forced a process to abort.
> > +      </dd>
> > +
> > +      <dt><code>err</code></dt>
> > +      <dd>
> > +        A high-level operation or a subsystem failed.  Attention is
> warranted.
> > +      </dd>
> > +
> > +      <dt><code>warn</code></dt>
> > +      <dd>
> > +        A low-level operation failed, but higher-level subsystems may
> be able
> > +        to recover.
> > +      </dd>
> > +
> > +      <dt><code>info</code></dt>
> > +      <dd>
> > +        Information that may be useful in retrospect when investigating
> a
> > +        problem.
> > +      </dd>
> > +
> > +      <dt><code>dbg</code></dt>
> > +      <dd>
> > +        Information useful only to someone with intricate knowledge of
> the
> > +        system, or that would commonly cause too-voluminous log output.
> > +        Log messages at this level are not logged by default.
> > +      </dd>
> > +    </dl>
> > +
> > +    <p>
> > +      Every OVN daemon supports the following commands for examining and
> > +      adjusting log levels.
> > +    </p>
> > +
> > +    <dl>
> > +      <dt><code>vlog/list</code></dt>
> > +      <dd>
> > +        Lists the known logging modules and their current levels.
> > +      </dd>
> > +
> > +      <dt><code>vlog/list-pattern</code></dt>
> > +      <dd>
> > +        Lists logging pattern used for each destination.
> > +      </dd>
> > +
> > +      <dt><code>vlog/set <var>[spec]</var></code></dt>
> > +      <dd>
> > +        Sets logging levels. Without any spec, sets the log level for
> every
> > +        module and destination to dbg. Otherwise, spec is a list of
> words
> > +        separated by spaces or commas or colons, up to one from each
> > +        category below:
> > +        <ul>
> > +          <li>
> > +            A valid module name, as displayed by the vlog/list command
> on
> > +            ovn-appctl(8), limits the log level change to the specified
> module.
> > +          </li>
> > +
> > +          <li>
> > +            <p>
> > +              <code>syslog</code>, <code>console</code>, or
> <code>file</code>,
> > +              to limit the log level change to only to the system log,
> to the
> > +              console, or to a file, respectively.
> > +            </p>
> > +
> > +            <p>
> > +              On Windows platform, <code>syslog</code> is accepted as a
> word
> > +              and is only useful if the target was started with the
> > +              <code>--syslog-target</code> option (the word has no
> effect
> > +              otherwise).
> > +            </p>
> > +          </li>
> > +
> > +          <li>
> > +            <code>off</code>, <code>emer</code>, <code>err</code>,
> > +            <code>warn</code>, <code>info</code>, or <code>dbg</code>,
> to
> > +            control the log level.  Messages of the given severity or
> higher
> > +            will be logged, and messages of lower severity will be
> filtered
> > +            out. <code>off</code> filters out all messages.
> > +          </li>
> > +        </ul>
> > +
> > +        <p>
> > +          Case is not significant within <var>spec</var>.
> > +        </p>
> > +      </dd>
> > +
> > +      <dt>
> > +        <code>vlog/set PATTERN</code>:<var>destination</var>:
> > +        <var>pattern</var>
> > +      </dt>
> > +      <dd>
> > +        Sets the log pattern for <var>destination</var> to
> <var>pattern</var>.
> > +        Each time a message is logged to destination, pattern
> determines the
> > +        message's formatting. Most characters in pattern are copied
> literally
> > +        to the log, but special escapes beginning with <code>%</code>
> are
> > +        expanded as follows:
> > +
> > +        <ul>
> > +          <li>
> > +            <code>%A</code> : The name of the application logging the
> > +            message, e.g. ovn-controller.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%B</code> : The RFC5424 syslog PRI of the message.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%c</code> : The name of the module
> > +            (as shown by ovn-appctl --list) logging the message.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%d</code> : The current date and time in ISO 8601
> format
> > +            (YYYY-MM-DD HH:MM:SS).
> > +          </li>
> > +
> > +          <li>
> > +            <code>%d<var>{format}</var></code> : The  current  date and
> time in
> > +            the specified format, which takes the same format as the
> template
> > +            argument to strftime(3). As an extension, any # characters
> in
> > +            format will be replaced by fractional seconds, e.g. use
> > +            <code>%H:%M:%S.###</code> for the time to the nearest
> millisecond.
> > +            Sub-second times are only approximate and currently decimal
> places
> > +            after the third will always be reported as zero.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%D</code> : The current UTC date and time in ISO 8601
> format
> > +            <code>(YYYY-MM-DD HH:MM:SS)</code>.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%D<var>{format}</var></code> : The current UTC date
> and time
> > +            in the specified format, which takes the same format as the
> > +            template argument to strftime(3). Supports the same
> extension for
> > +            sub-second resolution as <code>%d{...}</code>.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%E</code> : The hostname of the node running the
> application.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%m</code> : The message being logged.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%N</code> : A serial number for this message within
> this run
> > +            of the program, as a decimal number. The first message a
> program
> > +            logs has serial number 1, the second one has serial number
> 2,
> > +            and so on.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%n</code> : A new-line.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%p</code> : The level at which the message is logged,
> e.g.
> > +            <code>DBG</code>.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%P</code> : The program's process ID (pid), as a
> decimal
> > +            number.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%r</code> : The number of milliseconds elapsed from
> the start
> > +            of the application to the time the message was logged.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%t</code> : The subprogram name, that is, an
> identifying name
> > +            for the process or thread that emitted the log message,
> such as
> > +            monitor for the process used for --monitor or main for the
> primary
> > +            process or thread in a program.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%T</code> : The subprogram name enclosed in
> parentheses, e.g.
> > +            (monitor), or the empty string for the primary process or
> thread in
> > +            a program.
> > +          </li>
> > +
> > +          <li>
> > +            <code>%%</code> : A literal %.
> > +          </li>
> > +        </ul>
> > +
> > +        <p>
> > +          A few options may appear between the % and the format
> specifier
> > +          character, in this order:
> > +        </p>
> > +
> > +        <ul>
> > +        <li>
> > +          <code>-</code> : Left justify the escape's expansion within
> its field
> > +          width. Right justification is the default.
> > +        </li>
> > +
> > +        <li>
> > +          <code>-</code> : Pad the field to the field width with 0s.
> Padding
> > +          with spaces is the default.
> > +        </li>
> > +        </ul>
> > +
> > +        <p>
> > +          <var>width</var>  A number specifies the minimum field width.
> If the
> > +          escape expands to fewer characters than width then it is
> padded to
> > +          fill the field width. (A field wider than width is not
> truncated to
> > +          fit.)
> > +        </p>
> > +
> > +        <p>
> > +          The default pattern for console and file output is
> > +          <code>%D{%Y-%m-%dT %H:%M:%SZ}|%05N|%c|%p|%m;</code> for syslog
> > +          output, <code>%05N|%c|%p|%m</code>.
> > +        </p>
> > +      </dd>
> > +
> > +      <dt><code>vlog/set FACILITY:<var>facility</var></code></dt>
> > +      <dd>
> > +        Sets the RFC5424 facility of the log message. facility can be
> one of
> > +        <code>kern</code>, <code>user</code>, <code>mail</code>,
> > +        <code>daemon</code>, <code>auth</code>, <code>syslog</code>,
> > +        <code>lpr</code>, <code>news</code>, <code>uucp</code>,
> > +        <code>clock</code>, <code>ftp</code>, <code>ntp</code>,
> > +        <code>audit</code>, <code>alert</code>, <code>clock2</code>,
> > +        <code>local0</code>, <code>local1</code>, <code>local2</code>,
> > +        <code>local3</code>, <code>local4</code>, <code>local5</code>,
> > +        <code>local6</code> or <code>local7</code>.
> > +      </dd>
> > +
> > +      <dt><code>vlog/close</code></dt>
> > +      <dd>
> > +        Causes the daemon to close its log file, if it is open.
> > +        (Use <code>vlog/reopen</code> to reopen it later.)
> > +      </dd>
> > +
> > +      <dt><code>vlog/reopen</code></dt>
> > +      <dd>
> > +        <p>
> > +          Causes the daemon to close its log file, if it is open, and
> then
> > +          reopen it. (This is useful after rotating log files, to cause
> a
> > +          new log file to be used.)
> > +        </p>
> > +
> > +        <p>
> > +          This has no effect if the target application was not invoked
> > +          with the <code>--log-file</code> option.
> > +        </p>
> > +      </dd>
> > +    </dl>
> > +
> > +    <h1>Options</h1>
> > +    <dl>
> > +      <dt><code>-h</code></dt>
> > +      <dt><code>--help</code></dt>
> > +      <dd>
> > +        Prints a brief help message to the console.
> > +      </dd>
> > +
> > +      <dt><code>-V</code></dt>
> > +      <dt><code>--version</code></dt>
> > +      <dd>
> > +        Prints version information to the console.
> > +      </dd>
> > +    </dl>
> > +</manpage>
> > \ No newline at end of file
> > diff --git a/utilities/ovn-appctl.c b/utilities/ovn-appctl.c
> > new file mode 100644
> > index 000000000..ffd30b452
> > --- /dev/null
> > +++ b/utilities/ovn-appctl.c
> > @@ -0,0 +1,239 @@
> > +/*
> > + * Copyright (c) 2019 Nicira, Inc.
> > + *
> > + * Licensed under the Apache License, Version 2.0 (the "License");
> > + * you may not use this file except in compliance with the License.
> > + * You may obtain a copy of the License at:
> > + *
> > + *     http://www.apache.org/licenses/LICENSE-2.0
> > + *
> > + * Unless required by applicable law or agreed to in writing, software
> > + * distributed under the License is distributed on an "AS IS" BASIS,
> > + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
> implied.
> > + * See the License for the specific language governing permissions and
> > + * limitations under the License.
> > + */
> > +
> > +#include <config.h>
> > +
> > +#include <errno.h>
> > +#include <getopt.h>
> > +#include <stdio.h>
> > +#include <string.h>
> > +#include <stdlib.h>
> > +
> > +#include "command-line.h"
> > +#include "daemon.h"
> > +#include "lib/ovn-dirs.h"
> > +#include "openvswitch/dynamic-string.h"
> > +#include "jsonrpc.h"
> > +#include "process.h"
> > +#include "timeval.h"
> > +#include "unixctl.h"
> > +#include "util.h"
> > +#include "openvswitch/vlog.h"
> > +
> > +static void usage(void);
> > +static const char *parse_command_line(int argc, char *argv[]);
> > +static struct jsonrpc *connect_to_target(const char *target);
> > +
> > +int
> > +main(int argc, char *argv[])
> > +{
> > +    char *cmd_result, *cmd_error;
> > +    struct jsonrpc *client;
> > +    char *cmd, **cmd_argv;
> > +    const char *target;
> > +    int cmd_argc;
> > +    int error;
> > +
> > +    set_program_name(argv[0]);
> > +
> > +    /* Parse command line and connect to target. */
> > +    target = parse_command_line(argc, argv);
> > +    client = connect_to_target(target);
> > +
> > +    /* Transact request and process reply. */
> > +    cmd = argv[optind++];
> > +    cmd_argc = argc - optind;
> > +    cmd_argv = cmd_argc ? argv + optind : NULL;
> > +    error = unixctl_client_transact(client, cmd, cmd_argc, cmd_argv,
> > +                                    &cmd_result, &cmd_error);
> > +    if (error) {
> > +        ovs_fatal(error, "%s: transaction error", target);
> > +    }
> > +
> > +    if (cmd_error) {
> > +        jsonrpc_close(client);
> > +        fputs(cmd_error, stderr);
> > +        ovs_error(0, "%s: server returned an error", target);
> > +        exit(2);
> > +    } else if (cmd_result) {
> > +        fputs(cmd_result, stdout);
> > +    } else {
> > +        OVS_NOT_REACHED();
> > +    }
> > +
> > +    jsonrpc_close(client);
> > +    free(cmd_result);
> > +    free(cmd_error);
> > +    return 0;
> > +}
> > +
> > +static void
> > +usage(void)
> > +{
> > +    printf("\
> > +%s, for querying and controlling OVN daemon\n\
> > +usage: %s [TARGET] COMMAND [ARG...]\n\
> > +Targets:\n\
> > +  -t, --target=TARGET  pidfile or socket to contact\n\
> > +Common commands:\n\
> > +  list-commands      List commands supported by the target\n\
> > +  version            Print version of the target\n\
> > +  vlog/list          List current logging levels\n\
> > +  vlog/list-pattern  List logging patterns for each destination.\n\
> > +  vlog/set [SPEC]\n\
> > +      Set log levels as detailed in SPEC, which may include:\n\
> > +      A valid module name (all modules, by default)\n\
> > +      'syslog', 'console', 'file' (all destinations, by default))\n\
> > +      'off', 'emer', 'err', 'warn', 'info', or 'dbg' ('dbg',
> bydefault)\n\
> > +  vlog/reopen        Make the program reopen its log file\n\
> > +Other options:\n\
> > +  --timeout=SECS     wait at most SECS seconds for a response\n\
> > +  -h, --help         Print this helpful information\n\
> > +  -V, --version      Display ovn-appctl version information\n",
> > +           program_name, program_name);
> > +    exit(EXIT_SUCCESS);
> > +}
> > +
> > +static const char *
> > +parse_command_line(int argc, char *argv[])
> > +{
> > +    enum {
> > +        OPT_START = UCHAR_MAX + 1,
> > +        VLOG_OPTION_ENUMS
> > +    };
> > +    static const struct option long_options[] = {
> > +        {"target", required_argument, NULL, 't'},
> > +        {"execute", no_argument, NULL, 'e'},
> > +        {"help", no_argument, NULL, 'h'},
> > +        {"option", no_argument, NULL, 'o'},
> > +        {"version", no_argument, NULL, 'V'},
> > +        {"timeout", required_argument, NULL, 'T'},
> > +        VLOG_LONG_OPTIONS,
> > +        {NULL, 0, NULL, 0},
> > +    };
> > +    char *short_options_ =
> > +        ovs_cmdl_long_options_to_short_options(long_options);
> > +    char *short_options = xasprintf("+%s", short_options_);
> > +    const char *target;
> > +    int e_options;
> > +    unsigned int timeout = 0;
> > +
> > +    target = NULL;
> > +    e_options = 0;
> > +    for (;;) {
> > +        int option;
> > +
> > +        option = getopt_long(argc, argv, short_options, long_options,
> NULL);
> > +        if (option == -1) {
> > +            break;
> > +        }
> > +        switch (option) {
> > +        case 't':
> > +            if (target) {
> > +                ovs_fatal(0, "-t or --target may be specified only
> once");
> > +            }
> > +            target = optarg;
> > +            break;
> > +
> > +        case 'e':
> > +            /* We ignore -e for compatibility.  Older versions
> specified the
> > +             * command as the argument to -e.  Since the current
> version takes
> > +             * the command as non-option arguments and we say that -e
> has no
> > +             * arguments, this just works in the common case. */
> > +            if (e_options++) {
> > +                ovs_fatal(0, "-e or --execute may be speciifed only
> once");
> > +            }
> > +            break;
> > +
> > +        case 'h':
> > +            usage();
> > +            break;
> > +
> > +        case 'o':
> > +            ovs_cmdl_print_options(long_options);
> > +            exit(EXIT_SUCCESS);
> > +
> > +        case 'T':
> > +            if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
> > +                ovs_fatal(0, "value %s on -T or --timeout is invalid",
> optarg);
> > +            }
> > +            break;
> > +
> > +        case 'V':
> > +            ovs_print_version(0, 0);
> > +            exit(EXIT_SUCCESS);
> > +
> > +        VLOG_OPTION_HANDLERS
> > +
> > +        case '?':
> > +            exit(EXIT_FAILURE);
> > +
> > +        default:
> > +            OVS_NOT_REACHED();
> > +        }
> > +    }
> > +    free(short_options_);
> > +    free(short_options);
> > +
> > +    ctl_timeout_setup(timeout);
> > +
> > +    if (optind >= argc) {
> > +        ovs_fatal(0, "at least one non-option argument is required "
> > +                  "(use --help for help)");
> > +    }
> > +
> > +    return target ? target : "ovn-controller";
> > +}
> > +
> > +static struct jsonrpc *
> > +connect_to_target(const char *target)
> > +{
> > +    struct jsonrpc *client;
> > +    char *socket_name;
> > +    int error;
> > +
> > +#ifndef _WIN32
> > +    if (target[0] != '/') {
> > +        char *pidfile_name;
> > +        pid_t pid;
> > +
> > +        pidfile_name = xasprintf("%s/%s.pid", ovn_rundir(), target);
> > +        pid = read_pidfile(pidfile_name);
> > +        if (pid < 0) {
> > +            ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
> > +        }
> > +        free(pidfile_name);
> > +        socket_name = xasprintf("%s/%s.%ld.ctl",
> > +                                ovn_rundir(), target, (long int) pid);
> > +#else
> > +    /* On windows, if the 'target' contains ':', we make an assumption
> that
> > +     * it is an absolute path. */
> > +    if (!strchr(target, ':')) {
> > +        socket_name = xasprintf("%s/%s.ctl", ovn_rundir(), target);
> > +#endif
> > +    } else {
> > +        socket_name = xstrdup(target);
> > +    }
> > +
> > +    error = unixctl_client_create(socket_name, &client);
> > +    if (error) {
> > +        ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
> > +    }
> > +    free(socket_name);
> > +
> > +    return client;
> > +}
> > +
> > diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl
> > index c955aa177..4242cd2c8 100755
> > --- a/utilities/ovn-ctl
> > +++ b/utilities/ovn-ctl
> > @@ -44,13 +44,13 @@ pidfile_is_running () {
> >
> >   stop_nb_ovsdb() {
> >       if pidfile_is_running $DB_NB_PID; then
> > -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
> > +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
> >       fi
> >   }
> >
> >   stop_sb_ovsdb() {
> >       if pidfile_is_running $DB_SB_PID; then
> > -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
> > +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
> >       fi
> >   }
> >
> > @@ -65,8 +65,8 @@ demote_ovnnb() {
> >       fi
> >
> >       if test -e $ovnnb_active_conf_file; then
> > -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
> > -        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/connect-active-ovsdb-server
> > +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
> > +        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/connect-active-ovsdb-server
> >       else
> >           echo >&2 "$0: active server details not set"
> >           exit 1
> > @@ -79,8 +79,8 @@ demote_ovnsb() {
> >       fi
> >
> >       if test -e $ovnsb_active_conf_file; then
> > -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
> > -        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/connect-active-ovsdb-server
> > +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
> > +        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/connect-active-ovsdb-server
> >       else
> >           echo >&2 "$0: active server details not set"
> >           exit 1
> > @@ -89,12 +89,12 @@ demote_ovnsb() {
> >
> >   promote_ovnnb() {
> >       rm -f $ovnnb_active_conf_file
> > -    ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/disconnect-active-ovsdb-server
> > +    ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl
> ovsdb-server/disconnect-active-ovsdb-server
> >   }
> >
> >   promote_ovnsb() {
> >       rm -f $ovnsb_active_conf_file
> > -    ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/disconnect-active-ovsdb-server
> > +    ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl
> ovsdb-server/disconnect-active-ovsdb-server
> >   }
> >
> >   start_ovsdb__() {
> > @@ -274,7 +274,7 @@ start_ovsdb () {
> >   }
> >
> >   sync_status() {
> > -    ovs-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status |
> awk '{if(NR==1) print $2}'
> > +    ovn-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status |
> awk '{if(NR==1) print $2}'
> >   }
> >
> >   status_ovnnb() {
> >
>
>

Patch
diff mbox series

diff --git a/rhel/ovn-fedora.spec.in b/rhel/ovn-fedora.spec.in
index 14035de9a..9ee807fab 100644
--- a/rhel/ovn-fedora.spec.in
+++ b/rhel/ovn-fedora.spec.in
@@ -430,6 +430,7 @@  fi
 %{_bindir}/ovn-sbctl
 %{_bindir}/ovn-trace
 %{_bindir}/ovn-detrace
+%{_bindir}/ovn-appctl
 %{_datadir}/ovn/scripts/ovn-ctl
 %{_datadir}/ovn/scripts/ovn-lib
 %{_datadir}/ovn/scripts/ovndb-servers.ocf
@@ -440,6 +441,7 @@  fi
 %{_mandir}/man8/ovn-nbctl.8*
 %{_mandir}/man8/ovn-trace.8*
 %{_mandir}/man1/ovn-detrace.1*
+%{_mandir}/man8/ovn-appctl.8*
 #%{_mandir}/man7/ovn-architecture.7* - Uncomment this once the manpage is fixed
 %{_mandir}/man8/ovn-sbctl.8*
 #%{_mandir}/man5/ovn-nb.5* - Uncomment this once the manpage is fixed
diff --git a/utilities/.gitignore b/utilities/.gitignore
index 1d01e0b28..b319e8366 100644
--- a/utilities/.gitignore
+++ b/utilities/.gitignore
@@ -3,6 +3,8 @@ 
 /ovn-nbctl.8
 /ovn-sbctl
 /ovn-sbctl.8
+/ovn-appctl
+/ovn-appctl.8
 /ovn-trace
 /ovn-trace.8
 /ovn-detrace
diff --git a/utilities/automake.mk b/utilities/automake.mk
index 21dd8ccdf..ab0f6003a 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -8,7 +8,8 @@  man_MANS += \
     utilities/ovn-nbctl.8 \
     utilities/ovn-sbctl.8 \
     utilities/ovn-trace.8 \
-    utilities/ovn-detrace.1
+    utilities/ovn-detrace.1 \
+    utilities/ovn-appctl.8
 
 MAN_ROOTS += \
     utilities/ovn-sbctl.8.in \
@@ -27,6 +28,7 @@  EXTRA_DIST += \
     utilities/ovn-docker-overlay-driver.in \
     utilities/ovn-docker-underlay-driver.in \
     utilities/ovn-nbctl.8.xml \
+    utilities/ovn-appctl.8.xml \
     utilities/ovn-trace.8.xml \
     utilities/ovn-detrace.in \
     utilities/ovndb-servers.ocf \
@@ -49,7 +51,9 @@  CLEANFILES += \
     utilities/ovn-sbctl.8 \
     utilities/ovn-trace.8 \
     utilities/ovn-detrace.1 \
-    utilities/ovn-detrace
+    utilities/ovn-detrace \
+    utilities/ovn-appctl.8 \
+    utilities/ovn-appctl
 
 utilities/ovn-lib: $(top_builddir)/config.status
 
@@ -68,4 +72,9 @@  bin_PROGRAMS += utilities/ovn-trace
 utilities_ovn_trace_SOURCES = utilities/ovn-trace.c
 utilities_ovn_trace_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la
 
+# ovn-nbctl
+bin_PROGRAMS += utilities/ovn-appctl
+utilities_ovn_appctl_SOURCES = utilities/ovn-appctl.c
+utilities_ovn_appctl_LDADD = lib/libovn.la $(OVSDB_LIBDIR)/libovsdb.la $(OVS_LIBDIR)/libopenvswitch.la
+
 include utilities/bugtool/automake.mk
diff --git a/utilities/ovn-appctl.8.xml b/utilities/ovn-appctl.8.xml
new file mode 100644
index 000000000..32a42a766
--- /dev/null
+++ b/utilities/ovn-appctl.8.xml
@@ -0,0 +1,352 @@ 
+<?xml version="1.0" encoding="utf-8"?>
+<manpage program="ovn-appctl" section="8" title="ovn-appctl">
+    <h1>Name</h1>
+    <p>ovn-appctl -- utility for configuring running OVN daemons</p>
+
+    <h1>Synopsis</h1>
+    <p>
+      <code> ovn-appctl</code> [--target=target | -t target]
+      [-T secs | --timeout=secs] <var>command</var> [<var>arg</var>...]
+    </p>
+    <p><code>ovn-appctl</code> --help </p>
+    <p><code>ovn-appctl</code> --version </p>
+
+    <h1>Description</h1>
+    <p>
+      OVN daemons accept certain commands at runtime to control their behavior
+      and query their settings. Every daemon accepts a common set of commands
+      documented under COMMON COMMANDS below. Some daemons support additional
+      commands documented in their own manpages.
+    </p>
+
+    <p>
+       The <code>ovn-appctl</code> program provides a simple way to invoke
+       these commands. The command to be sent is specified on
+       <code>ovn-appctl's</code> command line as non-option arguments.
+       <code>ovn-appctl</code> sends the command and prints the daemon's
+       response on standard output.
+    </p>
+
+    <p>
+      <code>ovn-ctl</code> is exactly similar to Open vSwitch
+      <code>ovs-appctl</code> utility.
+    </p>
+
+    <h1>Command Commands</h1>
+    <p>
+      Every OVN daemon supports a common set of commands, which are documented
+      in this section.
+    </p>
+
+    <h2>General Commands</h2>
+    <p>
+      These commands display daemon-specific commands and the running version.
+      Note that these commands are different from the --help and --version
+      options that return information about the <code>ovn-appctl</code>
+      utility itself.
+    </p>
+
+    <dl>
+      <dt><code>list-commands</code></dt>
+      <dd>
+        Lists the commands supported by the target.
+      </dd>
+
+      <dt><code>version</code></dt>
+      <dd>
+        Displays the version and compilation date of the target.
+      </dd>
+    </dl>
+
+    <h2>Logging Commands</h2>
+    <p>
+      OVN has several log levels.  The highest-severity log level is:
+    </p>
+
+    <dl>
+      <dt><code>off</code></dt>
+      <dd>
+        No message is ever logged at this level, so setting a logging
+        destination's log level to off disables logging to that
+        destination.
+      </dd>
+    </dl>
+
+    <p>
+      The following log levels, in order of descending severity, are
+      available:
+    </p>
+
+    <dl>
+      <dt><code>emer</code></dt>
+      <dd>
+        A major failure forced a process to abort.
+      </dd>
+
+      <dt><code>err</code></dt>
+      <dd>
+        A high-level operation or a subsystem failed.  Attention is warranted.
+      </dd>
+
+      <dt><code>warn</code></dt>
+      <dd>
+        A low-level operation failed, but higher-level subsystems may be able
+        to recover.
+      </dd>
+
+      <dt><code>info</code></dt>
+      <dd>
+        Information that may be useful in retrospect when investigating a
+        problem.
+      </dd>
+
+      <dt><code>dbg</code></dt>
+      <dd>
+        Information useful only to someone with intricate knowledge of the
+        system, or that would commonly cause too-voluminous log output.
+        Log messages at this level are not logged by default.
+      </dd>
+    </dl>
+
+    <p>
+      Every OVN daemon supports the following commands for examining and
+      adjusting log levels.
+    </p>
+
+    <dl>
+      <dt><code>vlog/list</code></dt>
+      <dd>
+        Lists the known logging modules and their current levels.
+      </dd>
+
+      <dt><code>vlog/list-pattern</code></dt>
+      <dd>
+        Lists logging pattern used for each destination.
+      </dd>
+
+      <dt><code>vlog/set <var>[spec]</var></code></dt>
+      <dd>
+        Sets logging levels. Without any spec, sets the log level for every
+        module and destination to dbg. Otherwise, spec is a list of words
+        separated by spaces or commas or colons, up to one from each
+        category below:
+        <ul>
+          <li>
+            A valid module name, as displayed by the vlog/list command on
+            ovn-appctl(8), limits the log level change to the specified module.
+          </li>
+
+          <li>
+            <p>
+              <code>syslog</code>, <code>console</code>, or <code>file</code>,
+              to limit the log level change to only to the system log, to the
+              console, or to a file, respectively.
+            </p>
+
+            <p>
+              On Windows platform, <code>syslog</code> is accepted as a word
+              and is only useful if the target was started with the
+              <code>--syslog-target</code> option (the word has no effect
+              otherwise).
+            </p>
+          </li>
+
+          <li>
+            <code>off</code>, <code>emer</code>, <code>err</code>,
+            <code>warn</code>, <code>info</code>, or <code>dbg</code>, to
+            control the log level.  Messages of the given severity or higher
+            will be logged, and messages of lower severity will be filtered
+            out. <code>off</code> filters out all messages.
+          </li>
+        </ul>
+
+        <p>
+          Case is not significant within <var>spec</var>.
+        </p>
+      </dd>
+
+      <dt>
+        <code>vlog/set PATTERN</code>:<var>destination</var>:
+        <var>pattern</var>
+      </dt>
+      <dd>
+        Sets the log pattern for <var>destination</var> to <var>pattern</var>.
+        Each time a message is logged to destination, pattern determines the
+        message's formatting. Most characters in pattern are copied literally
+        to the log, but special escapes beginning with <code>%</code> are
+        expanded as follows:
+
+        <ul>
+          <li>
+            <code>%A</code> : The name of the application logging the
+            message, e.g. ovn-controller.
+          </li>
+
+          <li>
+            <code>%B</code> : The RFC5424 syslog PRI of the message.
+          </li>
+
+          <li>
+            <code>%c</code> : The name of the module
+            (as shown by ovn-appctl --list) logging the message.
+          </li>
+
+          <li>
+            <code>%d</code> : The current date and time in ISO 8601 format
+            (YYYY-MM-DD HH:MM:SS).
+          </li>
+
+          <li>
+            <code>%d<var>{format}</var></code> : The  current  date and time in
+            the specified format, which takes the same format as the template
+            argument to strftime(3). As an extension, any # characters in
+            format will be replaced by fractional seconds, e.g. use
+            <code>%H:%M:%S.###</code> for the time to the nearest millisecond.
+            Sub-second times are only approximate and currently decimal places
+            after the third will always be reported as zero.
+          </li>
+
+          <li>
+            <code>%D</code> : The current UTC date and time in ISO 8601 format
+            <code>(YYYY-MM-DD HH:MM:SS)</code>.
+          </li>
+
+          <li>
+            <code>%D<var>{format}</var></code> : The current UTC date and time
+            in the specified format, which takes the same format as the
+            template argument to strftime(3). Supports the same extension for
+            sub-second resolution as <code>%d{...}</code>.
+          </li>
+
+          <li>
+            <code>%E</code> : The hostname of the node running the application.
+          </li>
+
+          <li>
+            <code>%m</code> : The message being logged.
+          </li>
+
+          <li>
+            <code>%N</code> : A serial number for this message within this run
+            of the program, as a decimal number. The first message a program
+            logs has serial number 1, the second one has serial number 2,
+            and so on.
+          </li>
+
+          <li>
+            <code>%n</code> : A new-line.
+          </li>
+
+          <li>
+            <code>%p</code> : The level at which the message is logged, e.g.
+            <code>DBG</code>.
+          </li>
+
+          <li>
+            <code>%P</code> : The program's process ID (pid), as a decimal
+            number.
+          </li>
+
+          <li>
+            <code>%r</code> : The number of milliseconds elapsed from the start
+            of the application to the time the message was logged.
+          </li>
+
+          <li>
+            <code>%t</code> : The subprogram name, that is, an identifying name
+            for the process or thread that emitted the log message, such as
+            monitor for the process used for --monitor or main for the primary
+            process or thread in a program.
+          </li>
+
+          <li>
+            <code>%T</code> : The subprogram name enclosed in parentheses, e.g.
+            (monitor), or the empty string for the primary process or thread in
+            a program.
+          </li>
+
+          <li>
+            <code>%%</code> : A literal %.
+          </li>
+        </ul>
+
+        <p>
+          A few options may appear between the % and the format specifier
+          character, in this order:
+        </p>
+
+        <ul>
+        <li>
+          <code>-</code> : Left justify the escape's expansion within its field
+          width. Right justification is the default.
+        </li>
+
+        <li>
+          <code>-</code> : Pad the field to the field width with 0s.  Padding
+          with spaces is the default.
+        </li>
+        </ul>
+
+        <p>
+          <var>width</var>  A number specifies the minimum field width. If the
+          escape expands to fewer characters than width then it is padded to
+          fill the field width. (A field wider than width is not truncated to
+          fit.)
+        </p>
+
+        <p>
+          The default pattern for console and file output is
+          <code>%D{%Y-%m-%dT %H:%M:%SZ}|%05N|%c|%p|%m;</code> for syslog
+          output, <code>%05N|%c|%p|%m</code>.
+        </p>
+      </dd>
+
+      <dt><code>vlog/set FACILITY:<var>facility</var></code></dt>
+      <dd>
+        Sets the RFC5424 facility of the log message. facility can be one of
+        <code>kern</code>, <code>user</code>, <code>mail</code>,
+        <code>daemon</code>, <code>auth</code>, <code>syslog</code>,
+        <code>lpr</code>, <code>news</code>, <code>uucp</code>,
+        <code>clock</code>, <code>ftp</code>, <code>ntp</code>,
+        <code>audit</code>, <code>alert</code>, <code>clock2</code>,
+        <code>local0</code>, <code>local1</code>, <code>local2</code>,
+        <code>local3</code>, <code>local4</code>, <code>local5</code>,
+        <code>local6</code> or <code>local7</code>.
+      </dd>
+
+      <dt><code>vlog/close</code></dt>
+      <dd>
+        Causes the daemon to close its log file, if it is open.
+        (Use <code>vlog/reopen</code> to reopen it later.)
+      </dd>
+
+      <dt><code>vlog/reopen</code></dt>
+      <dd>
+        <p>
+          Causes the daemon to close its log file, if it is open, and then
+          reopen it. (This is useful after rotating log files, to cause a
+          new log file to be used.)
+        </p>
+
+        <p>
+          This has no effect if the target application was not invoked
+          with the <code>--log-file</code> option.
+        </p>
+      </dd>
+    </dl>
+
+    <h1>Options</h1>
+    <dl>
+      <dt><code>-h</code></dt>
+      <dt><code>--help</code></dt>
+      <dd>
+        Prints a brief help message to the console.
+      </dd>
+
+      <dt><code>-V</code></dt>
+      <dt><code>--version</code></dt>
+      <dd>
+        Prints version information to the console.
+      </dd>
+    </dl>
+</manpage>
\ No newline at end of file
diff --git a/utilities/ovn-appctl.c b/utilities/ovn-appctl.c
new file mode 100644
index 000000000..ffd30b452
--- /dev/null
+++ b/utilities/ovn-appctl.c
@@ -0,0 +1,239 @@ 
+/*
+ * Copyright (c) 2019 Nicira, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at:
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "command-line.h"
+#include "daemon.h"
+#include "lib/ovn-dirs.h"
+#include "openvswitch/dynamic-string.h"
+#include "jsonrpc.h"
+#include "process.h"
+#include "timeval.h"
+#include "unixctl.h"
+#include "util.h"
+#include "openvswitch/vlog.h"
+
+static void usage(void);
+static const char *parse_command_line(int argc, char *argv[]);
+static struct jsonrpc *connect_to_target(const char *target);
+
+int
+main(int argc, char *argv[])
+{
+    char *cmd_result, *cmd_error;
+    struct jsonrpc *client;
+    char *cmd, **cmd_argv;
+    const char *target;
+    int cmd_argc;
+    int error;
+
+    set_program_name(argv[0]);
+
+    /* Parse command line and connect to target. */
+    target = parse_command_line(argc, argv);
+    client = connect_to_target(target);
+
+    /* Transact request and process reply. */
+    cmd = argv[optind++];
+    cmd_argc = argc - optind;
+    cmd_argv = cmd_argc ? argv + optind : NULL;
+    error = unixctl_client_transact(client, cmd, cmd_argc, cmd_argv,
+                                    &cmd_result, &cmd_error);
+    if (error) {
+        ovs_fatal(error, "%s: transaction error", target);
+    }
+
+    if (cmd_error) {
+        jsonrpc_close(client);
+        fputs(cmd_error, stderr);
+        ovs_error(0, "%s: server returned an error", target);
+        exit(2);
+    } else if (cmd_result) {
+        fputs(cmd_result, stdout);
+    } else {
+        OVS_NOT_REACHED();
+    }
+
+    jsonrpc_close(client);
+    free(cmd_result);
+    free(cmd_error);
+    return 0;
+}
+
+static void
+usage(void)
+{
+    printf("\
+%s, for querying and controlling OVN daemon\n\
+usage: %s [TARGET] COMMAND [ARG...]\n\
+Targets:\n\
+  -t, --target=TARGET  pidfile or socket to contact\n\
+Common commands:\n\
+  list-commands      List commands supported by the target\n\
+  version            Print version of the target\n\
+  vlog/list          List current logging levels\n\
+  vlog/list-pattern  List logging patterns for each destination.\n\
+  vlog/set [SPEC]\n\
+      Set log levels as detailed in SPEC, which may include:\n\
+      A valid module name (all modules, by default)\n\
+      'syslog', 'console', 'file' (all destinations, by default))\n\
+      'off', 'emer', 'err', 'warn', 'info', or 'dbg' ('dbg', bydefault)\n\
+  vlog/reopen        Make the program reopen its log file\n\
+Other options:\n\
+  --timeout=SECS     wait at most SECS seconds for a response\n\
+  -h, --help         Print this helpful information\n\
+  -V, --version      Display ovn-appctl version information\n",
+           program_name, program_name);
+    exit(EXIT_SUCCESS);
+}
+
+static const char *
+parse_command_line(int argc, char *argv[])
+{
+    enum {
+        OPT_START = UCHAR_MAX + 1,
+        VLOG_OPTION_ENUMS
+    };
+    static const struct option long_options[] = {
+        {"target", required_argument, NULL, 't'},
+        {"execute", no_argument, NULL, 'e'},
+        {"help", no_argument, NULL, 'h'},
+        {"option", no_argument, NULL, 'o'},
+        {"version", no_argument, NULL, 'V'},
+        {"timeout", required_argument, NULL, 'T'},
+        VLOG_LONG_OPTIONS,
+        {NULL, 0, NULL, 0},
+    };
+    char *short_options_ =
+        ovs_cmdl_long_options_to_short_options(long_options);
+    char *short_options = xasprintf("+%s", short_options_);
+    const char *target;
+    int e_options;
+    unsigned int timeout = 0;
+
+    target = NULL;
+    e_options = 0;
+    for (;;) {
+        int option;
+
+        option = getopt_long(argc, argv, short_options, long_options, NULL);
+        if (option == -1) {
+            break;
+        }
+        switch (option) {
+        case 't':
+            if (target) {
+                ovs_fatal(0, "-t or --target may be specified only once");
+            }
+            target = optarg;
+            break;
+
+        case 'e':
+            /* We ignore -e for compatibility.  Older versions specified the
+             * command as the argument to -e.  Since the current version takes
+             * the command as non-option arguments and we say that -e has no
+             * arguments, this just works in the common case. */
+            if (e_options++) {
+                ovs_fatal(0, "-e or --execute may be speciifed only once");
+            }
+            break;
+
+        case 'h':
+            usage();
+            break;
+
+        case 'o':
+            ovs_cmdl_print_options(long_options);
+            exit(EXIT_SUCCESS);
+
+        case 'T':
+            if (!str_to_uint(optarg, 10, &timeout) || !timeout) {
+                ovs_fatal(0, "value %s on -T or --timeout is invalid", optarg);
+            }
+            break;
+
+        case 'V':
+            ovs_print_version(0, 0);
+            exit(EXIT_SUCCESS);
+
+        VLOG_OPTION_HANDLERS
+
+        case '?':
+            exit(EXIT_FAILURE);
+
+        default:
+            OVS_NOT_REACHED();
+        }
+    }
+    free(short_options_);
+    free(short_options);
+
+    ctl_timeout_setup(timeout);
+
+    if (optind >= argc) {
+        ovs_fatal(0, "at least one non-option argument is required "
+                  "(use --help for help)");
+    }
+
+    return target ? target : "ovn-controller";
+}
+
+static struct jsonrpc *
+connect_to_target(const char *target)
+{
+    struct jsonrpc *client;
+    char *socket_name;
+    int error;
+
+#ifndef _WIN32
+    if (target[0] != '/') {
+        char *pidfile_name;
+        pid_t pid;
+
+        pidfile_name = xasprintf("%s/%s.pid", ovn_rundir(), target);
+        pid = read_pidfile(pidfile_name);
+        if (pid < 0) {
+            ovs_fatal(-pid, "cannot read pidfile \"%s\"", pidfile_name);
+        }
+        free(pidfile_name);
+        socket_name = xasprintf("%s/%s.%ld.ctl",
+                                ovn_rundir(), target, (long int) pid);
+#else
+    /* On windows, if the 'target' contains ':', we make an assumption that
+     * it is an absolute path. */
+    if (!strchr(target, ':')) {
+        socket_name = xasprintf("%s/%s.ctl", ovn_rundir(), target);
+#endif
+    } else {
+        socket_name = xstrdup(target);
+    }
+
+    error = unixctl_client_create(socket_name, &client);
+    if (error) {
+        ovs_fatal(error, "cannot connect to \"%s\"", socket_name);
+    }
+    free(socket_name);
+
+    return client;
+}
+
diff --git a/utilities/ovn-ctl b/utilities/ovn-ctl
index c955aa177..4242cd2c8 100755
--- a/utilities/ovn-ctl
+++ b/utilities/ovn-ctl
@@ -44,13 +44,13 @@  pidfile_is_running () {
 
 stop_nb_ovsdb() {
     if pidfile_is_running $DB_NB_PID; then
-        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
+        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl exit
     fi
 }
 
 stop_sb_ovsdb() {
     if pidfile_is_running $DB_SB_PID; then
-        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
+        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl exit
     fi
 }
 
@@ -65,8 +65,8 @@  demote_ovnnb() {
     fi
 
     if test -e $ovnnb_active_conf_file; then
-        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
-        ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/connect-active-ovsdb-server
+        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnnb_active_conf_file`
+        ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/connect-active-ovsdb-server
     else
         echo >&2 "$0: active server details not set"
         exit 1
@@ -79,8 +79,8 @@  demote_ovnsb() {
     fi
 
     if test -e $ovnsb_active_conf_file; then
-        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
-        ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/connect-active-ovsdb-server
+        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/set-active-ovsdb-server `cat $ovnsb_active_conf_file`
+        ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/connect-active-ovsdb-server
     else
         echo >&2 "$0: active server details not set"
         exit 1
@@ -89,12 +89,12 @@  demote_ovnsb() {
 
 promote_ovnnb() {
     rm -f $ovnnb_active_conf_file
-    ovs-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
+    ovn-appctl -t $OVN_RUNDIR/ovnnb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
 }
 
 promote_ovnsb() {
     rm -f $ovnsb_active_conf_file
-    ovs-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
+    ovn-appctl -t $OVN_RUNDIR/ovnsb_db.ctl ovsdb-server/disconnect-active-ovsdb-server
 }
 
 start_ovsdb__() {
@@ -274,7 +274,7 @@  start_ovsdb () {
 }
 
 sync_status() {
-    ovs-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status | awk '{if(NR==1) print $2}'
+    ovn-appctl -t $OVN_RUNDIR/ovn${1}_db.ctl ovsdb-server/sync-status | awk '{if(NR==1) print $2}'
 }
 
 status_ovnnb() {