~zyga/checkbox/remove-libxml2

« back to all changes in this revision

Viewing changes to providers/plainbox-provider-checkbox/bin/network

"automatic merge of lp:~bladernr/checkbox/remove-ftp-network-test/ by tarmac [r=zyga][bug=][author=bladernr]"

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/env python3
2
2
"""
3
 
Copyright (C) 2012-2014 Canonical Ltd.
 
3
Copyright (C) 2012-2015 Canonical Ltd.
4
4
 
5
5
Authors
6
6
  Jeff Marcom <jeff.marcom@canonical.com>
7
7
  Daniel Manrique <roadmr@ubuntu.com>
 
8
  Jeff Lane <jeff@ubuntu.com>
8
9
 
9
10
This program is free software: you can redistribute it and/or modify
10
11
it under the terms of the GNU General Public License version 3,
24
25
    RawTextHelpFormatter
25
26
)
26
27
import fcntl
27
 
import ftplib
28
 
from ftplib import FTP
29
28
import logging
30
29
import os
31
30
import re
153
152
            return 1
154
153
 
155
154
 
156
 
class FTPPerformanceTest(object):
157
 
    """Provides file transfer rate based information while
158
 
    using the FTP protocol and sending a file (DEFAULT=1GB)
159
 
    over the local or public network using a specified network
160
 
    interface on the host."""
161
 
 
162
 
    def __init__(
163
 
            self,
164
 
            target,
165
 
            username,
166
 
            password,
167
 
            interface,
168
 
            binary_size=1,
169
 
            file2send="ftp_performance_test"):
170
 
 
171
 
        self.target = target
172
 
        self.username = username
173
 
        self.password = password
174
 
        self.iface = Interface(interface)
175
 
        self.binary_size = binary_size
176
 
        self.file2send = file2send
177
 
 
178
 
    def _make_file2send(self):
179
 
        """
180
 
        Makes binary file to send over FTP.
181
 
        Size defaults to 1GB if not supplied.
182
 
        """
183
 
 
184
 
        logging.debug("Creating %sGB file", self.binary_size)
185
 
 
186
 
        file_size = (1024 * 1024 * 1024) * self.binary_size
187
 
        with open(self.file2send, "wb") as out:
188
 
            out.seek((file_size) - 1)
189
 
            out.write('\0'.encode())
190
 
 
191
 
    def send_file(self, filename=None):
192
 
        """
193
 
        Sends file over the network using FTP and returns the
194
 
        amount of bytes sent and delay between send and completed.
195
 
        """
196
 
 
197
 
        if filename is None:
198
 
            file = open(self.file2send, 'rb')
199
 
            filename = self.file2send
200
 
 
201
 
        send_time = time.time()
202
 
 
203
 
        try:
204
 
            logging.debug("Sending file")
205
 
            self.remote.storbinary("STOR " + filename, file, 1024)
206
 
        except (ftplib.all_errors) as send_failure:
207
 
            logging.error("Failed to send file to %s", self.target)
208
 
            logging.error("Reason: %s", send_failure)
209
 
            return 0, 0
210
 
 
211
 
        file.close()
212
 
 
213
 
        time_lapse = time.time() - send_time
214
 
        bytes_sent = os.stat(filename).st_size
215
 
 
216
 
        return bytes_sent, time_lapse
217
 
 
218
 
    def close_connection(self):
219
 
        """
220
 
        Close connection to remote FTP target
221
 
        """
222
 
        self.remote.close()
223
 
 
224
 
    def connect(self):
225
 
        """
226
 
        Connects to FTP target and set the current directory as /
227
 
        """
228
 
 
229
 
        logging.debug("Connecting to %s", self.target)
230
 
        try:
231
 
            self.remote = FTP(self.target)
232
 
            self.remote.set_debuglevel(2)
233
 
            self.remote.set_pasv(True)
234
 
        except socket.error as connect_exception:
235
 
            logging.error("Failed to connect to: %s: %s", self.target,
236
 
                          connect_exception)
237
 
            return False
238
 
 
239
 
        logging.debug("Logging in")
240
 
        logging.debug("{USER:%s, PASS:%s}", self.username, self.password)
241
 
 
242
 
        try:
243
 
            self.remote.login(self.username, self.password)
244
 
        except ftplib.error_perm as login_exception:
245
 
            logging.error("failed to log into target: %s: %s", self.target,
246
 
                          login_exception)
247
 
            return False
248
 
 
249
 
        default_out_dir = ""
250
 
        self.remote.cwd(default_out_dir)
251
 
        return True
252
 
 
253
 
    def run(self):
254
 
 
255
 
        info = {
256
 
            "Interface": self.iface.interface,
257
 
            "HWAddress": self.iface.macaddress,
258
 
            "Duplex": self.iface.duplex_mode,
259
 
            "Speed": self.iface.max_speed,
260
 
            "Status": self.iface.status
261
 
        }
262
 
 
263
 
        logging.debug(info)
264
 
 
265
 
        if not os.path.isfile(self.file2send):
266
 
            self._make_file2send()
267
 
 
268
 
        # Connect to FTP target and send file
269
 
        connected = self.connect()
270
 
 
271
 
        if connected is False:
272
 
            return 3
273
 
 
274
 
        datasize, delay = self.send_file()
275
 
 
276
 
        # Remove created binary
277
 
        try:
278
 
            os.remove(self.file2send)
279
 
        except (IOError, OSError) as file_delete_error:
280
 
            logging.error("Could not remove previous ftp file")
281
 
            logging.error(file_delete_error)
282
 
 
283
 
        if connected and datasize > 0:
284
 
 
285
 
            logging.debug("Bytes sent (%s): %.2f seconds", datasize, delay)
286
 
 
287
 
            # Calculate transfer rate and determine pass/fail status
288
 
            mbs_speed = float(datasize / 131072) / float(delay)
289
 
            percent = (mbs_speed / int(info["Speed"])) * 100
290
 
            print("Transfer speed:")
291
 
            print("%3.2f%% of" % percent)
292
 
            print("theoretical max %smbs" % int(info["Speed"]))
293
 
 
294
 
            if percent < 40:
295
 
                logging.warn("Poor network performance detected")
296
 
                return 30
297
 
 
298
 
            logging.debug("Passed benchmark")
299
 
        else:
300
 
            print("Failed sending file via ftp")
301
 
            return 1
302
 
 
303
 
 
304
155
class StressPerformanceTest:
305
156
 
306
157
    def __init__(self, interface, target):
438
289
    # - If command-line args were given, they take precedence
439
290
    # - Next come environment variables, if set.
440
291
 
441
 
    params = {"test_target_ftp": None,
442
 
              "test_user": None,
443
 
              "test_pass": None,
444
 
              "test_target_iperf": None}
 
292
    params = {"test_target_iperf": None}
445
293
 
446
294
    # See if we have environment variables
447
295
    for key in params.keys():
450
298
    # Finally, see if we have the command-line arguments that are the ultimate
451
299
    # override.
452
300
    if args.target:
453
 
        params["test_target_ftp"] = args.target
454
301
        params["test_target_iperf"] = args.target
455
 
    if args.username:
456
 
        params["test_user"] = args.username
457
 
    if args.password:
458
 
        params["test_pass"] = args.password
459
302
 
460
303
    return params
461
304
 
489
332
    # Get the actual test data from one of two possible sources
490
333
    test_parameters = get_test_parameters(args, os.environ)
491
334
 
492
 
    test_user = test_parameters["test_user"]
493
 
    test_pass = test_parameters["test_pass"]
494
335
    if (args.test_type.lower() == "iperf" or
495
336
            args.test_type.lower() == "stress"):
496
337
        test_target = test_parameters["test_target_iperf"]
497
 
    else:
498
 
        test_target = test_parameters["test_target_ftp"]
499
338
 
500
339
    # Validate that we got reasonable values
501
340
    if not test_target or "example.com" in test_target:
509
348
        logging.info("Please run this script with -h to see more details on how to configure")
510
349
        sys.exit(1)
511
350
 
512
 
    if args.test_type.lower() == 'ftp' and not (test_user and test_pass):
513
 
        logging.error("Target user/password have not been supplied.")
514
 
        logging.info("Target user/password can be configured 3 different ways:")
515
 
        logging.info("1- If calling the script directly, give --user or  --pass option")
516
 
        logging.info("2- Define the TEST_USER or TEST_PASS environment variables")
517
 
        logging.info("3- (If running the test via checkbox/plainbox, define the ")
518
 
        logging.info("settings in /etc/xdg/canonical-certification.conf)")
519
 
        logging.info("Please run this script with -h to see more details on how to configure")
520
 
        sys.exit(1)
521
 
 
522
351
    # Testing begins here!
523
352
    #
524
353
    # Make sure that the interface is indeed connected
558
387
            logging.error("Can't ping test server on %s", args.interface)
559
388
            return 1
560
389
 
561
 
        # Execute FTP transfer benchmarking test
562
 
        if args.test_type.lower() == "ftp":
563
 
            ftp_benchmark = FTPPerformanceTest(
564
 
                test_target, test_user, test_pass, args.interface)
565
 
 
566
 
            if args.datasize:
567
 
                ftp_benchmark.binary_size = int(args.datasize)
568
 
            result = ftp_benchmark.run()
569
 
 
570
 
        elif args.test_type.lower() == "iperf":
 
390
        # Execute requested networking test
 
391
        if args.test_type.lower() == "iperf":
571
392
            iperf_benchmark = IPerfPerformanceTest(args.interface, test_target,
572
393
                                                   args.fail_threshold) 
573
394
            if args.datasize:
629
450
Example NIC information usage:
630
451
network info -i eth0 --max-speed
631
452
 
632
 
For running ftp benchmark test:
633
 
network test -i eth0 -t ftp
634
 
--target 192.168.0.1 --username USERID --password PASSW0RD
635
 
--datasize-2
636
 
 
637
453
For running iperf test:
638
454
network test -i eth0 -t iperf --target 192.168.0.1
639
455
NOTE: The iperf test requires an iperf server running on the same network
655
471
Environment variables
656
472
=====================
657
473
The variables are:
658
 
TEST_TARGET_FTP
659
 
TEST_USER
660
 
TEST_PASS
661
474
TEST_TARGET_IPERF
662
475
 
663
476
example config file
664
477
===================
665
478
[environment]
666
 
TEST_TARGET_FTP = ftp-server.example.com
667
 
TEST_USER = my-name
668
 
TEST_PASS = a-password
669
479
TEST_TARGET_IPERF = iperf-server.example.com
670
480
 
671
481
 
688
498
        '-i', '--interface', type=str, required=True)
689
499
    test_parser.add_argument(
690
500
        '-t', '--test_type', type=str,
691
 
        choices=("ftp", "iperf", "stress"), default="ftp",
692
 
        help=("[FTP *Default*]"))
 
501
        choices=("iperf", "stress"), default="iperf",
 
502
        help=("[iperf *Default*]"))
693
503
    test_parser.add_argument('--target', type=str)
694
504
    test_parser.add_argument(
695
 
        '--username', type=str, help=("For FTP test only"))
696
 
    test_parser.add_argument(
697
 
        '--password', type=str, help=("For FTP test only"))
698
 
    test_parser.add_argument(
699
505
        '--datasize', type=str,
700
506
        default="1",
701
507
        help=("Amount of data to send.  For iperf tests this will direct "
702
 
              "iperf to send DATASIZE GB of data.  For FTP tests, this "
703
 
              "will create a file that is DATASIZE GB large to be transmitted "
704
 
              "to the target."))
 
508
              "iperf to send DATASIZE GB of data to the target."))
705
509
    test_parser.add_argument(
706
510
        '--config', type=str,
707
511
        default="/etc/checkbox.d/network.cfg",