Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

modules/nilrt_ip.py: Add EtherCAT Support #48617

Merged

Conversation

alexvasiu
Copy link
Contributor

@alexvasiu alexvasiu commented Jul 17, 2018

  • modules/nilrt_ip.py: Add EtherCAT Support

The possibilities for adapter mode are: TCP/IP, EhterCAT and Disabled.

Signed-off-by: Alexandru Vasiu alexandru.vasiu@ni.com
Signed-off-by: Ovidiu-Adrian Vancea ovidiu.vancea@ni.com

  • modules/nilrt_ip.py: Fix configparser compatibility

read_file is available only since python 3.2 so readfp should
be used instead

Signed-off-by: Alexandru Vasiu alexandru.vasiu@ni.com

@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from 1cd1b8b to 14dcec7 Compare July 17, 2018 08:59
The possibilities for adapter mode are: TCP/IP, EhterCAT and
Disabled.

Signed-off-by: Alexandru Vasiu <alexandru.vasiu@ni.com>
Signed-off-by: Ovidiu-Adrian Vancea <ovidiu.vancea@ni.com>
@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from 14dcec7 to 3e502c1 Compare July 17, 2018 10:46
config_parser = configparser.RawConfigParser(dict_type=CaseInsensitiveDict)
config_parser.read_file(config_file)
mode = '' if not config_parser.has_option(interface, 'mode') else \
_remove_quotes(config_parser.get(interface, 'mode').lower())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be an anti-pattern - doing an 'has_option' then a 'get()'. Can we use a default for the get() and do only that?

More than that, the first 5 lines seems to be a pattern that is repeated throughout the code. Can/Should we create a higher-level wrapper over the configparser to hide all this boilerplate code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get() throws an exception if the option doesn't exist

We can make a class or a global variable where the config will be read only one time, but the problem is that if we write something with nirtcfg then we should reload config from INI_FILE in configparser, so a method like this one will be ok:

def _get_option_configparser(section, option, default_value='', file=INI_FILE):
        with salt.utils.files.fopen(file, 'r') as config_file:
            config_parser = configparser.RawConfigParser(dict_type=CaseInsensitiveDict)
            config_parser.read_file(config_file)
            if config_parser.has_section(section) and config_parser.has_option(option):
                return config_parser.get(section, option)
            return default_value

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There should be some option to pass defaults to the get, so you can avoid the has_option/get pair.

We shouldn't need a class, but only a function that can take a list of keys and returns a dict with keys/values

if initial_mode == 'ethercat':
__salt__['system.set_reboot_required_witnessed']()
else:
disable(interface)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there seem to be a lot of disable(interface) followed by enable(interface). Should we create a 'restart' or something?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep 👍

'''
if __grains__['lsb_distrib_id'] == 'nilrt':
initial_mode = _get_adaptermode_info(interface)
_set_adapter_mode(interface, 'EtherCAT')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why you spell 'EtherCAT' here, but do this in other places: if initial_mode == 'ethercat':

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is for network settings to understand the mode is EtherCAT but when I parse INI_FILE, I user CaseInsensitiveDict so that will transform EtherCAT in ethercat

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about creating a constant and use that everywhere?

I find confusing to see both 'EtherCAT' and 'ethercat' as values.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will make a constant:

NIRTCFG_ETHERCAT = 'EtherCAT'

@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from 3e502c1 to b3d626d Compare July 18, 2018 11:17

# some versions of nirtcfg don't set the dhcpenabled/linklocalenabled variables
# when selecting "DHCP or Link Local" from MAX, so return it by default to avoid
# having the requestmode "None" because none of the conditions above matched.
return 'dhcp_linklocal'


def _get_adapter_mode_info(interface):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this benefit from the newly created function? - _get_config_options

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot about that function ... I'll change it

},
'hwaddr': interface.hwaddr[:-1]
}
with salt.utils.files.fopen(INI_FILE, 'r') as config_file:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this used anywhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will delete that

},
'hwaddr': interface.hwaddr[:-1]
}
with salt.utils.files.fopen(INI_FILE, 'r') as config_file:
config_parser = configparser.RawConfigParser(dict_type=CaseInsensitiveDict)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this use the _persist_config method? And have that method fixed to use the config parser?

should we rename the _persist_config and _get_config_options to match i.e. (save/load or serialize/deserialize or something that makes sense).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe _save_config for _persist_config and _load_config for _get_config_options

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense

@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from b3d626d to e0f8d6a Compare July 18, 2018 14:37
'''
return adaptermode for given interface
'''
mode = _load_config(interface, ['mode'])['mode']
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't put default_value = 'tcpip' because the file may be corrupted and mode should be one of these values:

  • disabled
  • ethercat
  • tcpip (default value)

'''
return adaptermode for given interface
'''
mode = _load_config(interface, ['mode'])['mode']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will raise if 'mode' is not in the file.

Should you go with:
mode = _load_config(interface, ['mode']).get('mode') ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If mode is not in file, _load_config will return the default_value for it:

mode = {
    'mode': ''
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, forgot about that.

if out['retcode'] != 0:
msg = 'Couldn\'t disable interface {0}. Error: {1}'.format(interface, out['stderr'])
raise salt.exceptions.CommandExecutionError(msg)
initial_mode = _get_adapter_mode_info(interface)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

up/down code is almost identical. Can you create a worker to share the logic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A function called _change_state(state) and state can be up or down ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Alexandru Vasiu added 2 commits July 18, 2018 18:12
The possibilities for adapter mode are: TCP/IP, EhterCAT and
Disabled.

Signed-off-by: Alexandru Vasiu <alexandru.vasiu@ni.com>
Signed-off-by: Ovidiu-Adrian Vancea <ovidiu.vancea@ni.com>
read_file is available only since python 3.2 so readfp should
be used instead

Signed-off-by: Alexandru Vasiu <alexandru.vasiu@ni.com>
@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from e0f8d6a to 73f533e Compare July 18, 2018 15:13
@rares-pop
Copy link
Contributor

Things look good to me.

@gtmanfred can you take a look on these? They are something we'd need for Fluorine.

Copy link
Contributor

@gtmanfred gtmanfred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blind-review

@gtmanfred gtmanfred added the ZRELEASED - Fluorine reitred label label Jul 19, 2018
Copy link
Contributor

@rares-pop rares-pop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is still a small cleanup to be made. I'm fine doing it in a different review since the functionality is correct as is.

@@ -404,43 +495,81 @@ def get_interfaces_details():
return {'interfaces': list(map(_get_info, _interfaces))}


def up(interface, iface_type=None): # pylint: disable=invalid-name,unused-argument
def _set_adapter_mode(interface, mode):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I overlooked this before - but this shouldn't be needed. We should use _save_config() directly instead of this

@@ -504,7 +621,7 @@ def disable(interface):
return down(interface)


def _persist_config(section, token, value):
def _save_config(section, token, value):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this was supposed to use the configparser too. Did we change our mind?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for reading, we use config parser and for writing nirtcfg (is also used by the system) ... we should test if the file will be corrupted if we are writing at the same time with nirtcfg and config parser

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. It looks good!

if __grains__['lsb_distrib_id'] == 'nilrt':
initial_mode = _get_adapter_mode_info(interface)
_set_adapter_mode(interface, NIRTCFG_ETHERCAT)
if __salt__['cmd.run_all']('{0} --set section={1},token=MasterID,value={2}'.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not _save_config()?

Copy link
Contributor

@rallytime rallytime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just have a couple of small requests.

@@ -258,45 +259,102 @@ def _remove_quotes(value):
return value


def _get_requestmode_info(interface):
def _load_config(section, options, default_value='', file=INI_FILE):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use a variable name other than file here? It's a reserved word and can cause problems.

@@ -258,45 +259,102 @@ def _remove_quotes(value):
return value


def _get_requestmode_info(interface):
def _load_config(section, options, default_value='', file=INI_FILE):
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is picky, but can you use single quotes for docstrings? That's how we like them in Salt. :)

'''
Enable the specified interface
def _change_state(interface, new_state):
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Single quotes here, too.



def _restart(interface):
"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here. :)

@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from 20210cb to 7cd5543 Compare July 24, 2018 06:42
Signed-off-by: Alexandru Vasiu <alexandru.vasiu@ni.com>
@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from 7cd5543 to a429ef8 Compare July 25, 2018 10:38
@rallytime
Copy link
Contributor

@rares-pop How does this look to you now?

@rares-pop
Copy link
Contributor

@rallytime - the code looks good and works correctly.

In the near future we'll replace the _save_config to use the ConfigParser as opposed to a binary that's saving the things in the ini.. It's fine to leave it in a separate commit since it's not critical by any means and we have to check that the ConfigParser is 'thread-safe' in terms of not corrupting the ini file when called multiple times from multiple processes.

@rallytime
Copy link
Contributor

@alexvasiu There's one lint error that needs to be fixed here: https://jenkinsci.saltstack.com/job/pr-lint/job/PR-48617/10/

Signed-off-by: Alexandru Vasiu <alexandru.vasiu@ni.com>
@alexvasiu alexvasiu force-pushed the dev/avasiu/add_ethercat_support branch from e54d761 to 354e664 Compare July 27, 2018 14:16
@alexvasiu
Copy link
Contributor Author

alexvasiu commented Jul 27, 2018

@rallytime Fixed

UPDATE: Lint failed because of salt.modules.config

@rallytime rallytime merged commit 73ec7fb into saltstack:develop Jul 27, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants