From 647cac63f1b4c64ba8042aec32b39e56ec5389c2 Mon Sep 17 00:00:00 2001 From: Mark Hamilton Date: Wed, 8 Jul 2015 20:45:19 -0700 Subject: [PATCH 1/4] Add support for external_id and fail_mode. Updated syntax to pass pep8 v1.6.2 and pylint v0.25.0 --- network/openvswitch_bridge.py | 152 +++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 23 deletions(-) diff --git a/network/openvswitch_bridge.py b/network/openvswitch_bridge.py index b9ddff562c6..e26f5fea904 100644 --- a/network/openvswitch_bridge.py +++ b/network/openvswitch_bridge.py @@ -17,6 +17,10 @@ # # You should have received a copy of the GNU General Public License # along with this software. If not, see . +# +# Portions copyright @ 2015 VMware, Inc. All rights reserved. + +# pylint: disable=C0111 DOCUMENTATION = ''' --- @@ -43,62 +47,98 @@ options: default: 5 description: - How long to wait for ovs-vswitchd to respond + external_id: + required: false + description: + - bridge external-id + fail_mode: + required: false + choices : [secure, standalone] + description: + - bridge fail-mode ''' EXAMPLES = ''' # Create a bridge named br-int - openvswitch_bridge: bridge=br-int state=present + +# Create an integration bridge +- openvswitch_bridge: bridge=br-int state=present external_id=br-int + fail_mode=secure ''' +import syslog +import os + class OVSBridge(object): + """ Interface to ovs-vsctl. """ def __init__(self, module): self.module = module self.bridge = module.params['bridge'] self.state = module.params['state'] self.timeout = module.params['timeout'] + self.external_id = module.params['external_id'] + self.fail_mode = module.params['fail_mode'] def _vsctl(self, command): '''Run ovs-vsctl command''' - return self.module.run_command(['ovs-vsctl', '-t', str(self.timeout)] + command) + return self.module.run_command(['ovs-vsctl', '-t', + str(self.timeout)] + command) def exists(self): '''Check if the bridge already exists''' - rc, _, err = self._vsctl(['br-exists', self.bridge]) - if rc == 0: # See ovs-vsctl(8) for status codes + rtc, _, err = self._vsctl(['br-exists', self.bridge]) + if rtc == 0: # See ovs-vsctl(8) for status codes return True - if rc == 2: + if rtc == 2: return False - raise Exception(err) + self.module.fail_json(msg=err) def add(self): '''Create the bridge''' - rc, _, err = self._vsctl(['add-br', self.bridge]) - if rc != 0: - raise Exception(err) + rtc, _, err = self._vsctl(['add-br', self.bridge]) + if rtc != 0: + self.module.fail_json(msg=err) + if self.external_id: + self.set_external_id() + if self.fail_mode: + self.set_fail_mode() def delete(self): '''Delete the bridge''' - rc, _, err = self._vsctl(['del-br', self.bridge]) - if rc != 0: - raise Exception(err) + rtc, _, err = self._vsctl(['del-br', self.bridge]) + if rtc != 0: + self.module.fail_json(msg=err) def check(self): '''Run check mode''' + changed = False + + # pylint: disable=W0703 try: - if self.state == 'absent' and self.exists(): + if self.state == 'present' and self.exists(): + if (self.external_id and + (self.external_id != self.get_external_id())): + changed = True + if (self.fail_mode and + (self.fail_mode != self.get_fail_mode())): + changed = True + elif self.state == 'absent' and self.exists(): changed = True elif self.state == 'present' and not self.exists(): changed = True - else: - changed = False - except Exception, e: - self.module.fail_json(msg=str(e)) + except Exception, earg: + self.module.fail_json(msg=str(earg)) + + # pylint: enable=W0703 self.module.exit_json(changed=changed) def run(self): '''Make the necessary changes''' changed = False + # pylint: disable=W0703 + try: if self.state == 'absent': if self.exists(): @@ -108,27 +148,93 @@ class OVSBridge(object): if not self.exists(): self.add() changed = True - except Exception, e: - self.module.fail_json(msg=str(e)) - self.module.exit_json(changed=changed) + if (self.external_id and + (self.external_id != self.get_external_id())): + self.set_external_id() + changed = True + + current_fail_mode = self.get_fail_mode() + if self.fail_mode and (self.fail_mode != current_fail_mode): + syslog.syslog(syslog.LOG_NOTICE, + "changing fail mode %s to %s" % + (current_fail_mode, self.fail_mode)) + self.set_fail_mode() + changed = True + except Exception, earg: + self.module.fail_json(msg=str(earg)) + # pylint: enable=W0703 + self.module.exit_json(changed=changed) + + def get_external_id(self): + """ Return the current external id. """ + value = '' + if self.exists(): + rtc, out, err = self._vsctl(['br-get-external-id', self.bridge]) + if rtc != 0: + self.module.fail_json(msg=err) + try: + (_, value) = out.split('=') + except ValueError: + pass + return value.strip("\n") + + def set_external_id(self): + """ Set external id. """ + if self.exists(): + (rtc, _, err) = self._vsctl(['br-set-external-id', self.bridge, + 'bridge-id', self.external_id]) + if rtc != 0: + self.module.fail_json(msg=err) + + def get_fail_mode(self): + """ Get failure mode. """ + value = '' + if self.exists(): + rtc, out, err = self._vsctl(['get-fail-mode', self.bridge]) + if rtc != 0: + self.module.fail_json(msg=err) + value = out.strip("\n") + return value + + def set_fail_mode(self): + """ Set failure mode. """ + + if self.exists(): + (rtc, _, err) = self._vsctl(['set-fail-mode', self.bridge, + self.fail_mode]) + if rtc != 0: + self.module.fail_json(msg=err) + + +# pylint: disable=E0602 def main(): + """ Entry point. """ module = AnsibleModule( argument_spec={ 'bridge': {'required': True}, 'state': {'default': 'present', 'choices': ['present', 'absent']}, - 'timeout': {'default': 5, 'type': 'int'} + 'timeout': {'default': 5, 'type': 'int'}, + 'external_id': {'default': ''}, + 'fail_mode': {'default': ''}, + 'syslogging': {'required': False, 'type': 'bool', 'default': True} }, supports_check_mode=True, ) - br = OVSBridge(module) + if (module.params["syslogging"]): + syslog.openlog('ansible-%s' % os.path.basename(__file__)) + + bridge = OVSBridge(module) if module.check_mode: - br.check() + bridge.check() else: - br.run() + bridge.run() +# pylint: disable=W0614 +# pylint: disable=W0401 +# pylint: disable=W0622 # import module snippets from ansible.module_utils.basic import * From 90a831a8285a20c368f39ded0cfc7a73ce51e036 Mon Sep 17 00:00:00 2001 From: Mark Hamilton Date: Tue, 14 Jul 2015 05:17:38 -0700 Subject: [PATCH 2/4] removed syslog. Generalized external id concept. Now user can add or remove multiple external ids. Added documenation about fail_main parameter. --- network/openvswitch_bridge.py | 99 ++++++++++++++++++++++------------- 1 file changed, 63 insertions(+), 36 deletions(-) diff --git a/network/openvswitch_bridge.py b/network/openvswitch_bridge.py index e26f5fea904..58ba8d740e6 100644 --- a/network/openvswitch_bridge.py +++ b/network/openvswitch_bridge.py @@ -3,6 +3,8 @@ # (c) 2013, David Stygstra # +# Portions copyright @ 2015 VMware, Inc. +# # This file is part of Ansible # # This module is free software: you can redistribute it and/or modify @@ -17,8 +19,6 @@ # # You should have received a copy of the GNU General Public License # along with this software. If not, see . -# -# Portions copyright @ 2015 VMware, Inc. All rights reserved. # pylint: disable=C0111 @@ -47,15 +47,20 @@ options: default: 5 description: - How long to wait for ovs-vswitchd to respond - external_id: + external_ids: + version_added: 2.0 required: false + default: None description: - - bridge external-id + - A dictionary of external-ids. Omitting this parameter is a No-op. + To clear all external-ids pass an empty value. fail_mode: + version_added: 2.0 + default: None required: false choices : [secure, standalone] description: - - bridge fail-mode + - Set bridge fail-mode. The default value (None) is a No-op. ''' EXAMPLES = ''' @@ -63,12 +68,13 @@ EXAMPLES = ''' - openvswitch_bridge: bridge=br-int state=present # Create an integration bridge -- openvswitch_bridge: bridge=br-int state=present external_id=br-int - fail_mode=secure +- openvswitch_bridge: bridge=br-int state=present fail_mode=secure + args: + external_ids: + bridge-id: "br-int" ''' import syslog -import os class OVSBridge(object): @@ -78,7 +84,6 @@ class OVSBridge(object): self.bridge = module.params['bridge'] self.state = module.params['state'] self.timeout = module.params['timeout'] - self.external_id = module.params['external_id'] self.fail_mode = module.params['fail_mode'] def _vsctl(self, command): @@ -100,8 +105,6 @@ class OVSBridge(object): rtc, _, err = self._vsctl(['add-br', self.bridge]) if rtc != 0: self.module.fail_json(msg=err) - if self.external_id: - self.set_external_id() if self.fail_mode: self.set_fail_mode() @@ -118,12 +121,25 @@ class OVSBridge(object): # pylint: disable=W0703 try: if self.state == 'present' and self.exists(): - if (self.external_id and - (self.external_id != self.get_external_id())): - changed = True if (self.fail_mode and (self.fail_mode != self.get_fail_mode())): changed = True + + ## + # Check if external ids would change. + current_external_ids = self.get_external_ids() + items = self.module.params['external_ids'].items() + for (key, value) in items: + if ((key in current_external_ids) and + (value != current_external_ids[key])): + changed = True + + ## + # Check if external ids would be removed. + for (key, value) in current_external_ids.items(): + if key not in self.module.params['external_ids']: + changed = True + elif self.state == 'absent' and self.exists(): changed = True elif self.state == 'present' and not self.exists(): @@ -145,15 +161,11 @@ class OVSBridge(object): self.delete() changed = True elif self.state == 'present': + if not self.exists(): self.add() changed = True - if (self.external_id and - (self.external_id != self.get_external_id())): - self.set_external_id() - changed = True - current_fail_mode = self.get_fail_mode() if self.fail_mode and (self.fail_mode != current_fail_mode): syslog.syslog(syslog.LOG_NOTICE, @@ -162,31 +174,50 @@ class OVSBridge(object): self.set_fail_mode() changed = True + current_external_ids = self.get_external_ids() + + ## + # Change and add existing external ids. + items = self.module.params['external_ids'].items() + for (key, value) in items: + if (value != current_external_ids.get(key, None)): + changed = self.set_external_id(key, value) or changed + + ## + # Remove current external ids that are not passed in. + for (key, value) in current_external_ids.items(): + if key not in self.module.params['external_ids']: + changed = self.set_external_id(key, None) or changed + except Exception, earg: self.module.fail_json(msg=str(earg)) # pylint: enable=W0703 self.module.exit_json(changed=changed) - def get_external_id(self): - """ Return the current external id. """ - value = '' + def get_external_ids(self): + """ Return the bridge's external ids as a dict. """ if self.exists(): rtc, out, err = self._vsctl(['br-get-external-id', self.bridge]) if rtc != 0: self.module.fail_json(msg=err) - try: - (_, value) = out.split('=') - except ValueError: - pass - return value.strip("\n") + lines = out.split("\n") + lines = [item.split("=") for item in lines if (len(item) > 0)] + return {item[0]: item[1] for item in lines} - def set_external_id(self): + return {} + + def set_external_id(self, key, value): """ Set external id. """ if self.exists(): - (rtc, _, err) = self._vsctl(['br-set-external-id', self.bridge, - 'bridge-id', self.external_id]) + cmd = ['br-set-external-id', self.bridge, key] + if (value): + cmd += [value] + + (rtc, _, err) = self._vsctl(cmd) if rtc != 0: self.module.fail_json(msg=err) + return True + return False def get_fail_mode(self): """ Get failure mode. """ @@ -216,16 +247,12 @@ def main(): 'bridge': {'required': True}, 'state': {'default': 'present', 'choices': ['present', 'absent']}, 'timeout': {'default': 5, 'type': 'int'}, - 'external_id': {'default': ''}, - 'fail_mode': {'default': ''}, - 'syslogging': {'required': False, 'type': 'bool', 'default': True} + 'external_ids': {'default': None}, + 'fail_mode': {'default': None}, }, supports_check_mode=True, ) - if (module.params["syslogging"]): - syslog.openlog('ansible-%s' % os.path.basename(__file__)) - bridge = OVSBridge(module) if module.check_mode: bridge.check() From a6f3a0e0a92079a42f723b852073d034c8d35028 Mon Sep 17 00:00:00 2001 From: Mark Hamilton Date: Thu, 16 Jul 2015 10:05:59 -0700 Subject: [PATCH 3/4] Changed syntax to support python2.4. Allow external_ids to be None. --- network/openvswitch_bridge.py | 56 +++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/network/openvswitch_bridge.py b/network/openvswitch_bridge.py index 58ba8d740e6..2396b1f2b49 100644 --- a/network/openvswitch_bridge.py +++ b/network/openvswitch_bridge.py @@ -128,17 +128,18 @@ class OVSBridge(object): ## # Check if external ids would change. current_external_ids = self.get_external_ids() - items = self.module.params['external_ids'].items() - for (key, value) in items: - if ((key in current_external_ids) and - (value != current_external_ids[key])): - changed = True - - ## - # Check if external ids would be removed. - for (key, value) in current_external_ids.items(): - if key not in self.module.params['external_ids']: - changed = True + exp_external_ids = self.module.params['external_ids'] + if exp_external_ids is not None: + for (key, value) in exp_external_ids: + if ((key in current_external_ids) and + (value != current_external_ids[key])): + changed = True + + ## + # Check if external ids would be removed. + for (key, value) in current_external_ids.items(): + if key not in exp_external_ids: + changed = True elif self.state == 'absent' and self.exists(): changed = True @@ -178,16 +179,19 @@ class OVSBridge(object): ## # Change and add existing external ids. - items = self.module.params['external_ids'].items() - for (key, value) in items: - if (value != current_external_ids.get(key, None)): - changed = self.set_external_id(key, value) or changed - - ## - # Remove current external ids that are not passed in. - for (key, value) in current_external_ids.items(): - if key not in self.module.params['external_ids']: - changed = self.set_external_id(key, None) or changed + exp_external_ids = self.module.params['external_ids'] + if exp_external_ids is not None: + for (key, value) in exp_external_ids.items(): + if ((value != current_external_ids.get(key, None)) and + self.set_external_id(key, value)): + changed = True + + ## + # Remove current external ids that are not passed in. + for (key, value) in current_external_ids.items(): + if ((key not in exp_external_ids) and + self.set_external_id(key, None)): + changed = True except Exception, earg: self.module.fail_json(msg=str(earg)) @@ -196,21 +200,23 @@ class OVSBridge(object): def get_external_ids(self): """ Return the bridge's external ids as a dict. """ + results = {} if self.exists(): rtc, out, err = self._vsctl(['br-get-external-id', self.bridge]) if rtc != 0: self.module.fail_json(msg=err) lines = out.split("\n") - lines = [item.split("=") for item in lines if (len(item) > 0)] - return {item[0]: item[1] for item in lines} + lines = [item.split("=") for item in lines if len(item) > 0] + for item in lines: + results[item[0]] = item[1] - return {} + return results def set_external_id(self, key, value): """ Set external id. """ if self.exists(): cmd = ['br-set-external-id', self.bridge, key] - if (value): + if value: cmd += [value] (rtc, _, err) = self._vsctl(cmd) From b51c252127472719562d44a706a6dd5482a32f8a Mon Sep 17 00:00:00 2001 From: Mark Hamilton Date: Mon, 20 Jul 2015 18:06:17 -0700 Subject: [PATCH 4/4] removed syslog import --- network/openvswitch_bridge.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/network/openvswitch_bridge.py b/network/openvswitch_bridge.py index 2396b1f2b49..8f29735862f 100644 --- a/network/openvswitch_bridge.py +++ b/network/openvswitch_bridge.py @@ -74,8 +74,6 @@ EXAMPLES = ''' bridge-id: "br-int" ''' -import syslog - class OVSBridge(object): """ Interface to ovs-vsctl. """