lfc_controller.cc 8.11 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright (C) 2015  Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

15
#include <lfc/lfc_controller.h>
16
#include <util/pid_file.h>
17
#include <exceptions/exceptions.h>
Shawn Routhier's avatar
Shawn Routhier committed
18
#include <config.h>
19
#include <iostream>
20 21
#include <sstream>
#include <unistd.h>
22
#include <stdlib.h>
23 24

using namespace std;
25
using namespace isc::util;
26 27 28 29 30 31

namespace isc {
namespace lfc {

/// @brief Defines the application name, it may be used to locate
/// configuration data and appears in log statements.
32
const char* LFCController::lfc_app_name_ = "DhcpLFC";
33 34

/// @brief Defines the executable name.
35
const char* LFCController::lfc_bin_name_ = "kea-lfc";
36

37
LFCController::LFCController()
38
    : protocol_version_(0), verbose_(false), config_file_(""), previous_file_(""),
Shawn Routhier's avatar
Shawn Routhier committed
39
      copy_file_(""), output_file_(""), finish_file_(""), pid_file_("") {
40 41
}

42
LFCController::~LFCController() {
43 44 45
}

void
46
LFCController::launch(int argc, char* argv[]) {
47 48 49 50 51 52 53 54 55 56 57
    try {
        parseArgs(argc, argv);
    } catch (const InvalidUsage& ex) {
        usage(ex.what());
        throw;  // rethrow it
    }

    std::cerr << "Starting lease file cleanup" << std::endl;

    // verify we are the only instance
    PIDFile pid_file(pid_file_);
58 59 60 61 62 63 64 65 66

    try {
        if (pid_file.check() == true) {
            // Already running instance, bail out
            std::cerr << "LFC instance already running" <<  std::endl;
            return;
        }
    } catch (const PIDFileError& pid_ex) {
        std::cerr << pid_ex.what() << std::endl;
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
        return;
    }

    // create the pid file for this instance
    try {
        pid_file.write();
    } catch (const PIDFileError& pid_ex) {
        std::cerr << pid_ex.what() << std::endl;
        return;
    }

    // do other work (TBD)
    std::cerr << "Add code to perform lease cleanup" << std::endl;

    // delete the pid file for this instance
82 83 84 85 86 87
    try {
        pid_file.deleteFile();
    } catch (const PIDFileError& pid_ex) {
        std::cerr << pid_ex.what() << std::endl;
        return;
    }
88 89

    std::cerr << "LFC complete" << std::endl;
90 91 92
}

void
93
LFCController::parseArgs(int argc, char* argv[]) {
94 95
    int ch;

96 97
    opterr = 0;
    optind = 1;
98
    while ((ch = getopt(argc, argv, ":46dvVp:x:i:o:c:f:")) != -1) {
99
        switch (ch) {
Shawn Routhier's avatar
Shawn Routhier committed
100
        case '4':
101
            // Process DHCPv4 lease files.
102
            protocol_version_ = 4;
103 104
            break;

Shawn Routhier's avatar
Shawn Routhier committed
105
        case '6':
106
            // Process DHCPv6 lease files.
107
            protocol_version_ = 6;
108 109
            break;

Shawn Routhier's avatar
Shawn Routhier committed
110
        case 'v':
111
            // Print just Kea vesion and exit.
Shawn Routhier's avatar
Shawn Routhier committed
112
            std::cout << getVersion(false) << std::endl;
113 114
            exit(EXIT_SUCCESS);

Shawn Routhier's avatar
Shawn Routhier committed
115
        case 'V':
116
            // Print extended  Kea vesion and exit.
Shawn Routhier's avatar
Shawn Routhier committed
117
            std::cout << getVersion(true) << std::endl;
118 119
            exit(EXIT_SUCCESS);

Shawn Routhier's avatar
Shawn Routhier committed
120 121 122 123 124 125
        case 'd':
            // Verbose output.
            verbose_ = true;
            break;

        case 'p':
126 127 128 129 130 131 132 133 134
            // PID file name.
            if (optarg == NULL) {
                isc_throw(InvalidUsage, "PID file name missing");
            }
            pid_file_ = optarg;
            break;

        case 'x':
            // Previous (or ex) file name.
Shawn Routhier's avatar
Shawn Routhier committed
135
            if (optarg == NULL) {
136
                isc_throw(InvalidUsage, "Previous (ex) file name missing");
Shawn Routhier's avatar
Shawn Routhier committed
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
            }
            previous_file_ = optarg;
            break;

        case 'i':
            // Copy file name.
            if (optarg == NULL) {
                isc_throw(InvalidUsage, "Copy file name missing");
            }
            copy_file_ = optarg;
            break;

        case 'o':
            // Output file name.
            if (optarg == NULL) {
                isc_throw(InvalidUsage, "Output file name missing");
            }
            output_file_ = optarg;
            break;

        case 'f':
158
            // Finish file name.
Shawn Routhier's avatar
Shawn Routhier committed
159 160 161 162 163 164 165
            if (optarg == NULL) {
                isc_throw(InvalidUsage, "Finish file name missing");
            }
            finish_file_ = optarg;
            break;

        case 'c':
166
            // Configuration file name
Shawn Routhier's avatar
Shawn Routhier committed
167 168 169 170 171 172
            if (optarg == NULL) {
                isc_throw(InvalidUsage, "Configuration file name missing");
            }
            config_file_ = optarg;
            break;

173
        case 'h':
Shawn Routhier's avatar
Shawn Routhier committed
174
            usage("");
175 176 177 178 179 180 181 182 183
            exit(EXIT_SUCCESS);

        case '?':
            // Unknown argument
            isc_throw(InvalidUsage, "Unknown argument");

        case ':':
            // Missing option argument
            isc_throw(InvalidUsage, "Missing option argument");
184 185

        default:
186 187 188
            // I don't think we should get here as the unknown arguments
            // and missing options cases should cover everything else
            isc_throw(InvalidUsage, "Invalid command line");
Shawn Routhier's avatar
Shawn Routhier committed
189
        }
190 191 192 193 194 195 196
    }

    // Check for extraneous parameters.
    if (argc > optind) {
        isc_throw(InvalidUsage, "Extraneous parameters.");
    }

197
    if (protocol_version_ == 0) {
198 199 200
        isc_throw(InvalidUsage, "DHCP version required");
    }

201 202 203 204
    if (pid_file_.empty()) {
        isc_throw(InvalidUsage, "PID file not specified");
    }

205
    if (previous_file_.empty()) {
Shawn Routhier's avatar
Shawn Routhier committed
206
        isc_throw(InvalidUsage, "Previous file not specified");
207 208 209
    }

    if (copy_file_.empty()) {
Shawn Routhier's avatar
Shawn Routhier committed
210
        isc_throw(InvalidUsage, "Copy file not specified");
211 212 213
    }

    if (output_file_.empty()) {
Shawn Routhier's avatar
Shawn Routhier committed
214
        isc_throw(InvalidUsage, "Output file not specified");
215 216
    }

217
    if (finish_file_.empty()) {
Shawn Routhier's avatar
Shawn Routhier committed
218
        isc_throw(InvalidUsage, "Finish file not specified");
219 220
    }

221
    if (config_file_.empty()) {
Shawn Routhier's avatar
Shawn Routhier committed
222
        isc_throw(InvalidUsage, "Config file not specified");
223 224 225 226
    }

    // If verbose is set echo the input information
    if (verbose_ == true) {
227
      std::cerr << "Protocol version:    DHCPv" << protocol_version_ << std::endl
228 229 230 231 232 233
                << "Previous or ex lease file: " << previous_file_ << std::endl
                << "Copy lease file:           " << copy_file_ << std::endl
                << "Output lease file:         " << output_file_ << std::endl
                << "Finishn file:              " << finish_file_ << std::endl
                << "Config file:               " << config_file_ << std::endl
                << "PID file:                  " << pid_file_ << std::endl;
234 235 236 237
    }
}

void
238
LFCController::usage(const std::string& text) {
239 240 241 242 243
    if (text != "") {
        std::cerr << "Usage error: " << text << std::endl;
    }

    std::cerr << "Usage: " << lfc_bin_name_ << std::endl
244
              << " [-4|-6] -p file -x file -i file -o file -f file -c file" << std::endl
245
              << "   -4 or -6 clean a set of v4 or v6 lease files" << std::endl
246 247
              << "   -p <file>: PID file" << std::endl
              << "   -x <file>: previous or ex lease file" << std::endl
248 249
              << "   -i <file>: copy of lease file" << std::endl
              << "   -o <file>: output lease file" << std::endl
250
              << "   -f <file>: finish file" << std::endl
251 252 253 254
              << "   -c <file>: configuration file" << std::endl
              << "   -v: print version number and exit" << std::endl
              << "   -V: print extended version inforamtion and exit" << std::endl
              << "   -d: optional, verbose output " << std::endl
255
              << "   -h: print this message " << std::endl
256 257 258
              << std::endl;
}

259
std::string
260 261
LFCController::getVersion(const bool extended) const{
    std::stringstream version_stream;
262

263
    version_stream << VERSION;
264
    if (extended) {
265
        version_stream << std::endl << EXTENDED_VERSION;
266 267
    }

268
    return (version_stream.str());
269 270
}

271 272
}; // namespace isc::lfc
}; // namespace isc