def test_comment(self): string= """\ # junk1 name1: value1 #junk2 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 #junk6 name5: value5 #junk7 """ parsed = """\ name1: value1 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 """ ac(str(config_parser.parse_string(string)), parsed) string= """\ # junk1 section1 { # junk2 } section2 # junk2 { } section3 { } #junk3 """ parsed = """\ section1 { } section2 # junk2 { } section3 { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section { #} """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ #section { } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string )
def test_comment(self): string= """\ # junk1 name1: value1 #junk2 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 #junk6 name5: value5 #junk7 """ parsed = """\ name1: value1 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 """ ac(str(config_parser.parse_string(string)), parsed) string= """\ # junk1 section1 { # junk2 } section2 # junk2 { } section3 { } #junk3 """ parsed = """\ section1 { } section2 # junk2 { } section3 { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section { #} """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ #section { } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string )
def test_attributes(self): string = """\ name:value\ """ parsed = """\ name: value """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name:value name:value """ parsed = """\ name: value name: value """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name1:value1 name2 :value2 name3: value3 name4 : value4 """ parsed = """\ name1: value1 name2: value2 name3: value3 name4: value4 """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name:foo:value """ parsed = """\ name: foo:value """ root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", "foo:value"]]) ac(str(root), parsed) string = """\ name : """ parsed = """\ name: """ root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", ""]]) ac(str(root), parsed)
def test_attributes(self): string = """\ name:value\ """ parsed = """\ name: value """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name:value name:value """ parsed = """\ name: value name: value """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name1:value1 name2 :value2 name3: value3 name4 : value4 """ parsed = """\ name1: value1 name2: value2 name3: value3 name4: value4 """ ac(str(config_parser.parse_string(string)), parsed) string = """\ name:foo:value """ parsed = """\ name: foo:value """ root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", "foo:value"]]) ac(str(root), parsed) string = """\ name : """ parsed = """\ name: """ root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", ""]]) ac(str(root), parsed)
def test_all_valid(self): text = outdent( """\ name1: value1 name2: value2 child1 { name1_1: value1.1 name1_2: value1.2 child1A { name1A1: value } child1B { name1B1: value name1B2: value } } child2 { child2 { name: value } } """ ) section = config_parser.parse_string(text) self.assertEqual(config_parser.verify_section(section), ([], [], []))
def test_attributes_one_attribute(self): string = outdent("""\ name:value\ """) parsed = outdent("""\ name: value """) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def test_attributes_colon_in_value(self): string = outdent("""\ name:foo:value """) parsed = outdent("""\ name: foo:value """) root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", "foo:value"]]) self.assertEqual(str(root), parsed)
def test_attributes_empty_value(self): string = outdent("""\ name : """) parsed = outdent("""\ name: """) root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", ""]]) self.assertEqual(str(root), parsed)
def test_sections_empty_section(self): string = outdent("""\ section1 { }\ """) parsed = outdent("""\ section1 { } """) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def from_string(cls, config_string): """ Parse corosync config and create a facade around it config_string corosync config text """ try: return cls(config_parser.parse_string(config_string)) except config_parser.MissingClosingBraceException: raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfMissingClosingBrace() ) ) except config_parser.UnexpectedClosingBraceException: # pylint: disable=line-too-long raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfUnexpectedClosingBrace() ) ) except config_parser.MissingSectionNameBeforeOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfMissingSectionNameBeforeOpeningBrace() ) ) except config_parser.ExtraCharactersAfterOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfExtraCharactersAfterOpeningBrace() ) ) except config_parser.ExtraCharactersBeforeOrAfterClosingBraceException: # pylint: disable=line-too-long raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfExtraCharactersBeforeOrAfterClosingBrace() ) ) except config_parser.LineIsNotSectionNorKeyValueException: # pylint: disable=line-too-long raise LibraryError( ReportItem.error( reports.messages.ParseErrorCorosyncConfLineIsNotSectionNorKeyValue() ) ) except config_parser.CorosyncConfParserException: raise LibraryError( ReportItem.error(reports.messages.ParseErrorCorosyncConf()) )
def test_attributes_more_attributes_whitespace(self): string = outdent("""\ name1:value1 name2 :value2 name3: value3 name4 : value4 """) parsed = outdent("""\ name1: value1 name2: value2 name3: value3 name4: value4 """) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def from_string(cls, config_string): """ Parse corosync config and create a facade around it config_string corosync config text """ try: return cls(config_parser.parse_string(config_string)) except config_parser.MissingClosingBraceException: raise LibraryError( reports.corosync_config_parser_missing_closing_brace()) except config_parser.UnexpectedClosingBraceException: raise LibraryError( reports.corosync_config_parser_unexpected_closing_brace()) except config_parser.CorosyncConfParserException: raise LibraryError(reports.corosync_config_parser_other_error())
def test_attributes_empty_value(self): # pylint: disable=trailing-whitespace string = outdent( """\ name : """ ) parsed = outdent( """\ name: """ ) root = config_parser.parse_string(string) self.assertEqual(root.get_attributes(), [["name", ""]]) self.assertEqual(str(root), parsed)
def test_comments_attributes(self): string = outdent("""\ # junk1 name1: value1 #junk2 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 #junk6 name5: value5 #junk7 """) parsed = outdent("""\ name1: value1 name2: value2#junk3 name3: value3 #junk4 name4 # junk5: value4 """) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def from_string(cls, config_string): """ Parse corosync config and create a facade around it config_string corosync config text """ try: return cls(config_parser.parse_string(config_string)) except config_parser.MissingClosingBraceException: raise LibraryError( reports.corosync_config_parser_missing_closing_brace() ) except config_parser.UnexpectedClosingBraceException: raise LibraryError( reports.corosync_config_parser_unexpected_closing_brace() ) except config_parser.CorosyncConfParserException: raise LibraryError( reports.corosync_config_parser_other_error() )
def test_sections_empty_section_in_section_whitespace(self): string = outdent("""\ section1 { section1a { } section1b { } } """) parsed = outdent("""\ section1 { section1a { } section1b { } } """) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def test_complex(self): text = outdent( """\ name1: value1 name#2: value2 child1 { name1_1: value1.1 name1#2: value1.2 child1A { name1A1: value } child1B# { name#1B1: value name1B2: value } } child2 { child2# { na#me: value } } """ ) section = config_parser.parse_string(text) # this would be rejected by the parser section.add_attribute("name1_3", "va{l}ue") self.assertEqual( config_parser.verify_section(section), ( ["child1.child1B#", "child2.child2#"], [ "name#2", "child1.name1#2", "child1.child1B#.name#1B1", "child2.child2#.na#me", ], [("name1_3", "va{l}ue")], ), )
def from_string(cls, config_string): """ Parse corosync config and create a facade around it config_string corosync config text """ try: return cls(config_parser.parse_string(config_string)) except config_parser.MissingClosingBraceException: raise LibraryError( reports.corosync_config_parser_missing_closing_brace() ) except config_parser.UnexpectedClosingBraceException: raise LibraryError( reports.corosync_config_parser_unexpected_closing_brace() ) except config_parser.MissingSectionNameBeforeOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_missing_section_name_before_opening_brace() ) except config_parser.ExtraCharactersAfterOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_extra_characters_after_opening_brace() ) except config_parser.ExtraCharactersBeforeOrAfterClosingBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_extra_characters_before_or_after_closing_brace() ) except config_parser.LineIsNotSectionNorKeyValueException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_line_is_not_section_nor_key_value() ) except config_parser.CorosyncConfParserException: raise LibraryError( reports.corosync_config_parser_other_error() )
def from_string(cls, config_string): """ Parse corosync config and create a facade around it config_string corosync config text """ try: return cls(config_parser.parse_string(config_string)) except config_parser.MissingClosingBraceException: raise LibraryError( reports.corosync_config_parser_missing_closing_brace() ) except config_parser.UnexpectedClosingBraceException: raise LibraryError( reports.corosync_config_parser_unexpected_closing_brace() ) except config_parser.MissingSectionNameBeforeOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_missing_section_name_before_opening_brace() ) except config_parser.ExtraCharactersAfterOpeningBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_extra_characters_after_opening_brace() ) except config_parser.ExtraCharactersBeforeOrAfterClosingBraceException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_extra_characters_before_or_after_closing_brace() ) except config_parser.LineIsNotSectionNorKeyValueException: # pylint: disable=line-too-long raise LibraryError( reports.corosync_config_parser_line_is_not_section_nor_key_value() ) except config_parser.CorosyncConfParserException: raise LibraryError( reports.corosync_config_parser_other_error() )
def test_full(self): string = """\ # Please read the corosync.conf.5 manual page totem { version: 2 # crypto_cipher and crypto_hash: Used for mutual node authentication. # If you choose to enable this, then do remember to create a shared # secret with "corosync-keygen". # enabling crypto_cipher, requires also enabling of crypto_hash. crypto_cipher: none crypto_hash: none # interface: define at least one interface to communicate # over. If you define more than one interface stanza, you must # also set rrp_mode. interface { # Rings must be consecutively numbered, starting at 0. ringnumber: 0 # This is normally the *network* address of the # interface to bind to. This ensures that you can use # identical instances of this configuration file # across all your cluster nodes, without having to # modify this option. bindnetaddr: 192.168.1.0 # However, if you have multiple physical network # interfaces configured for the same subnet, then the # network address alone is not sufficient to identify # the interface Corosync should bind to. In that case, # configure the *host* address of the interface # instead: # bindnetaddr: 192.168.1.1 # When selecting a multicast address, consider RFC # 2365 (which, among other things, specifies that # 239.255.x.x addresses are left to the discretion of # the network administrator). Do not reuse multicast # addresses across multiple Corosync clusters sharing # the same network. mcastaddr: 239.255.1.1 # Corosync uses the port you specify here for UDP # messaging, and also the immediately preceding # port. Thus if you set this to 5405, Corosync sends # messages over UDP ports 5405 and 5404. mcastport: 5405 # Time-to-live for cluster communication packets. The # number of hops (routers) that this ring will allow # itself to pass. Note that multicast routing must be # specifically enabled on most network routers. ttl: 1 } } logging { # Log the source file and line where messages are being # generated. When in doubt, leave off. Potentially useful for # debugging. fileline: off # Log to standard error. When in doubt, set to no. Useful when # running in the foreground (when invoking "corosync -f") to_stderr: no # Log to a log file. When set to "no", the "logfile" option # must not be set. to_logfile: yes logfile: /var/log/cluster/corosync.log # Log to the system log daemon. When in doubt, set to yes. to_syslog: yes # Log debug messages (very verbose). When in doubt, leave off. debug: off # Log messages with time stamps. When in doubt, set to on # (unless you are only logging to syslog, where double # timestamps can be annoying). timestamp: on logger_subsys { subsys: QUORUM debug: off } } quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 #provider: corosync_votequorum } """ parsed = """\ totem { version: 2 crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 192.168.1.0 mcastaddr: 239.255.1.1 mcastport: 5405 ttl: 1 } } logging { fileline: off to_stderr: no to_logfile: yes logfile: /var/log/cluster/corosync.log to_syslog: yes debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } quorum { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ # Please read the corosync.conf.5 manual page totem { version: 2 crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } transport: udpu } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 #provider: corosync_votequorum } """ parsed = """\ totem { version: 2 crypto_cipher: none crypto_hash: none transport: udpu interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { } """ ac(str(config_parser.parse_string(string)), parsed)
def test_section(self): string = """\ section1 { }\ """ parsed = """\ section1 { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a { } section1b { } } """ parsed = """\ section1 { section1a { } section1b { } } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a junk1 { junk2 junk3 } junk4 section1b junk5{junk6 junk7}junk8 } section2 { section2a { } section2b { } } """ parsed = """\ section1 { section1a junk1 { } section1b junk5 { } } section2 { section2a { } section2b { } } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a { } section1b { } } } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string ) string = """\ section1 { section1a { section1b { } } """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ section1 { """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string )
def test_full_2(self): string = outdent("""\ # Please read the corosync.conf.5 manual page totem { version: 2 crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } transport: udpu } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 #provider: corosync_votequorum } """ ) parsed = outdent("""\ totem { version: 2 crypto_cipher: none crypto_hash: none transport: udpu interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { } """ ) self.assertEqual(str(config_parser.parse_string(string)), parsed)
def test_empty(self): self.assertEqual(str(config_parser.parse_string("")), "")
def test_empty(self): ac(str(config_parser.parse_string("")), "")
def test_full(self): string = """\ # Please read the corosync.conf.5 manual page totem { version: 2 # crypto_cipher and crypto_hash: Used for mutual node authentication. # If you choose to enable this, then do remember to create a shared # secret with "corosync-keygen". # enabling crypto_cipher, requires also enabling of crypto_hash. crypto_cipher: none crypto_hash: none # interface: define at least one interface to communicate # over. If you define more than one interface stanza, you must # also set rrp_mode. interface { # Rings must be consecutively numbered, starting at 0. ringnumber: 0 # This is normally the *network* address of the # interface to bind to. This ensures that you can use # identical instances of this configuration file # across all your cluster nodes, without having to # modify this option. bindnetaddr: 192.168.1.0 # However, if you have multiple physical network # interfaces configured for the same subnet, then the # network address alone is not sufficient to identify # the interface Corosync should bind to. In that case, # configure the *host* address of the interface # instead: # bindnetaddr: 192.168.1.1 # When selecting a multicast address, consider RFC # 2365 (which, among other things, specifies that # 239.255.x.x addresses are left to the discretion of # the network administrator). Do not reuse multicast # addresses across multiple Corosync clusters sharing # the same network. mcastaddr: 239.255.1.1 # Corosync uses the port you specify here for UDP # messaging, and also the immediately preceding # port. Thus if you set this to 5405, Corosync sends # messages over UDP ports 5405 and 5404. mcastport: 5405 # Time-to-live for cluster communication packets. The # number of hops (routers) that this ring will allow # itself to pass. Note that multicast routing must be # specifically enabled on most network routers. ttl: 1 } } logging { # Log the source file and line where messages are being # generated. When in doubt, leave off. Potentially useful for # debugging. fileline: off # Log to standard error. When in doubt, set to no. Useful when # running in the foreground (when invoking "corosync -f") to_stderr: no # Log to a log file. When set to "no", the "logfile" option # must not be set. to_logfile: yes logfile: /var/log/cluster/corosync.log # Log to the system log daemon. When in doubt, set to yes. to_syslog: yes # Log debug messages (very verbose). When in doubt, leave off. debug: off # Log messages with time stamps. When in doubt, set to on # (unless you are only logging to syslog, where double # timestamps can be annoying). timestamp: on logger_subsys { subsys: QUORUM debug: off } } quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 #provider: corosync_votequorum } """ parsed = """\ totem { version: 2 crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 192.168.1.0 mcastaddr: 239.255.1.1 mcastport: 5405 ttl: 1 } } logging { fileline: off to_stderr: no to_logfile: yes logfile: /var/log/cluster/corosync.log to_syslog: yes debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } quorum { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ # Please read the corosync.conf.5 manual page totem { version: 2 crypto_cipher: none crypto_hash: none interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } transport: udpu } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { # Enable and configure quorum subsystem (default: off) # see also corosync.conf.5 and votequorum.5 #provider: corosync_votequorum } """ parsed = """\ totem { version: 2 crypto_cipher: none crypto_hash: none transport: udpu interface { ringnumber: 0 bindnetaddr: 10.16.35.0 mcastport: 5405 ttl: 1 } } logging { fileline: off to_logfile: yes to_syslog: yes logfile: /var/log/cluster/corosync.log debug: off timestamp: on logger_subsys { subsys: QUORUM debug: off } } nodelist { node { ring0_addr: 10.16.35.101 nodeid: 1 } node { ring0_addr: 10.16.35.102 nodeid: 2 } node { ring0_addr: 10.16.35.103 } node { ring0_addr: 10.16.35.104 } node { ring0_addr: 10.16.35.105 } } quorum { } """ ac(str(config_parser.parse_string(string)), parsed)
def test_empty(self): ac(str(config_parser.parse_string("")), "")
def test_section(self): string = """\ section1 { }\ """ parsed = """\ section1 { } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a { } section1b { } } """ parsed = """\ section1 { section1a { } section1b { } } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a junk1 { junk2 junk3 } junk4 section1b junk5{junk6 junk7}junk8 } section2 { section2a { } section2b { } } """ parsed = """\ section1 { section1a junk1 { } section1b junk5 { } } section2 { section2a { } section2b { } } """ ac(str(config_parser.parse_string(string)), parsed) string = """\ section1 { section1a { } section1b { } } } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string ) string = """\ section1 { section1a { section1b { } } """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ section1 { """ self.assertRaises( config_parser.MissingClosingBraceException, config_parser.parse_string, string ) string = """\ } """ self.assertRaises( config_parser.UnexpectedClosingBraceException, config_parser.parse_string, string )