NFVBENCH-184: Add a feature (+ options) allowing to change ownership of shared log... 69/71269/2
authorPierrick Louin <pierrick.louin@orange.com>
Tue, 13 Oct 2020 17:02:16 +0000 (19:02 +0200)
committerfmenguy <francoisregis.menguy@orange.com>
Mon, 19 Oct 2020 15:16:41 +0000 (17:16 +0200)
Change-Id: Id77426dade28aed48986ce6c18db6a193da5b6ed
Signed-off-by: Pierrick Louin <pierrick.louin@orange.com>
nfvbench/cfg.default.yaml
nfvbench/nfvbench.py
nfvbench/utils.py

index 80d5b68..26df919 100644 (file)
@@ -351,14 +351,15 @@ cores_used:
 intf_speed_used:
 intf_speed_detected:
 
-# Add cache size in packet generation for TRex field engine (FE).
+# A cache size value is passed to the TRex field engine (FE) at packet generation.
+# Can be overridden by --cache-size
 # More information for TRex performance:
 # https://trex-tgn.cisco.com/trex/doc/trex_stateless.html#_tutorial_field_engine_significantly_improve_performance
 # If cache_size = 0 (or empty): no cache will be used by TRex (default)
 # If cache_size < 0: cache_size will be set to flow count value
 cache_size: 0
 # The cache size is actually limited by the number of 64B mbufs configured in the trex platform configuration (see Trex manual 6.2.2. Memory section configuration)
-# Note that the resulting value is finally clipped to 10000, whatever the requested size is (by design limitation).
+# Note that the resulting value is finally capped to 10000, whatever the requested size is (by design limitation).
 
 # Trex will use 1 x 64B mbuf per pre-built cached packet, assuming 1 pre-built cached packet per flow, it means for very large number of flows, the number of configured mbuf_64 will need to be set accordingly.
 mbuf_64:
@@ -795,6 +796,26 @@ debug: false
 # Defaults to disabled
 log_file:
 
+# One can specify a user ID for changing ownership of output log/json files
+#   - empty: depends on file existency
+#     . yes? replacement, owner is unchanged
+#     . no ? creation with root as user
+#   - 0: this is the root user ID
+#   - other: will corresponds (or not) to an existing user/group in the host
+#            (the current user ID can be obtained with the command 'id -u')
+# Can be overriden by --user-id
+# Consider also that the default value below is overridable by a USER_ID env variable,
+# if nfvbench is run into a container, this information can be passed at its creation.
+# The overall precedence rule is: 'default_config (this) < env < config < command_line'
+user_id:
+
+# Similarly, the group ID is defined
+# Can be overriden by --group-id
+# Default may be set through env GROUP_ID
+# Caveat: user and group with a same name may have different numerical IDs
+#         (the current group ID can be obtained with the command 'id -g')
+group_id:
+
 # When enabled, all results and/or logs will be sent to a fluentd servers at the requested IPs and ports
 # A list of one or more fluentd servers identified by their IPs and  port numbers should be given.
 # For each recipient it is possible to enable both sending logs and performance
@@ -845,6 +866,7 @@ user_label:
 # (the command-line parameter value is expressed as a json object string)
 user_info:
 
+
 # THESE FIELDS SHOULD BE USED VERY RARELY OR ON PURPOSE
 
 # Skip vswitch configuration and retrieving of stats
index 314b828..da069bf 100644 (file)
@@ -165,7 +165,9 @@ class NFVBench(object):
                                self.config.service_chain,
                                self.config.service_chain_count,
                                self.config.flow_count,
-                               self.config.frame_sizes)
+                               self.config.frame_sizes,
+                               self.config.user_id,
+                               self.config.group_id)
 
     def _update_config(self, opts):
         """Recalculate the running config based on the base config and opts.
@@ -560,6 +562,20 @@ def _parse_opts_from_cli():
                         default=False,
                         help='Disable latency measurements (no streams)')
 
+    parser.add_argument('--user-id', dest='user_id',
+                        type=int_arg,
+                        metavar='<uid>',
+                        action='store',
+                        default=None,
+                        help='Change json/log files ownership with this user (int)')
+
+    parser.add_argument('--group-id', dest='group_id',
+                        type=int_arg,
+                        metavar='<gid>',
+                        action='store',
+                        default=None,
+                        help='Change json/log files ownership with this group (int)')
+
     parser.add_argument('--debug-mask', dest='debug_mask',
                         type=int_arg,
                         metavar='<mask>',
@@ -633,6 +649,12 @@ def main():
         log.setup()
         # load default config file
         config, default_cfg = load_default_config()
+        # possibly override the default user_id & group_id values
+        if 'USER_ID' in os.environ:
+            config.user_id = int(os.environ['USER_ID'])
+        if 'GROUP_ID' in os.environ:
+            config.group_id = int(os.environ['GROUP_ID'])
+
         # create factory for platform specific classes
         try:
             factory_module = importlib.import_module(config['factory_module'])
@@ -771,6 +793,13 @@ def main():
         # add file log if requested
         if config.log_file:
             log.add_file_logger(config.log_file)
+            # possibly change file ownership
+            uid = config.user_id
+            gid = config.group_id
+            if gid is None:
+                gid = uid
+            if uid is not None:
+                os.chown(config.log_file, uid, gid)
 
         openstack_spec = config_plugin.get_openstack_spec() if config.openrc_file \
             else None
index 2ce735b..6da14ed 100644 (file)
@@ -51,7 +51,7 @@ def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
 
 
 def save_json_result(result, json_file, std_json_path, service_chain, service_chain_count,
-                     flow_count, frame_sizes):
+                     flow_count, frame_sizes, user_id=None, group_id=None):
     """Save results in json format file."""
     filepaths = []
     if json_file:
@@ -71,6 +71,11 @@ def save_json_result(result, json_file, std_json_path, service_chain, service_ch
                           sort_keys=True,
                           separators=(',', ': '),
                           default=lambda obj: obj.to_json())
+                # possibly change file ownership
+                if group_id is None:
+                    group_id = user_id
+                if user_id is not None:
+                    os.chown(file_path, user_id, group_id)
 
 
 def dict_to_json_dict(record):
@@ -155,7 +160,6 @@ def get_intel_pci(nic_slot=None, nic_ports=None):
     return pcis
 
 
-
 def parse_flow_count(flow_count):
     flow_count = str(flow_count)
     input_fc = flow_count