Esempio n. 1
0
    def get_netconf_protocol(self):
        self.last_connection_id += 1

        return NetconfProtocol(
            datastore=self.datastore,
            capabilities=self.capabilities(),
            additionnal_namespaces={"junos": NS_JUNOS},
            logger=logging.getLogger(
                "fake_switches.juniper.%s.%s.netconf" %
                (self.switch_configuration.name, self.last_connection_id)))
Esempio n. 2
0
    def get_netconf_protocol(self):
        self.last_connection_id += 1

        return NetconfProtocol(
            datastore=self.datastore,
            capabilities=[
                Candidate1_0, ConfirmedCommit1_0, Validate1_0, Url1_0,
                NetconfJunos1_0, DmiSystem1_0
            ],
            additionnal_namespaces={"junos": NS_JUNOS},
            logger=logging.getLogger(
                "fake_switches.juniper.%s.%s.netconf" %
                (self.switch_configuration.name, self.last_connection_id)))
Esempio n. 3
0
 def setUp(self):
     self.netconf = NetconfProtocol(logger=logging.getLogger())
     self.netconf.transport = Mock()
Esempio n. 4
0
class NetconfProtocolTest(unittest.TestCase):
    def setUp(self):
        self.netconf = NetconfProtocol(logger=logging.getLogger())
        self.netconf.transport = Mock()

    def test_says_hello_upon_connection_and_receive_an_hello(self):
        self.netconf.connectionMade()

        self.assert_xml_response("""
            <hello>
              <session-id>1</session-id>
              <capabilities>
                <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability>
              </capabilities>
            </hello>
            """)

    def test_close_session_support(self):
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived(
            '<nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="12345">\n'
        )
        self.netconf.dataReceived('  <nc:close-session/>\n')
        self.netconf.dataReceived('</nc:rpc>\n')
        self.netconf.dataReceived(']]>]]>\n')

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="12345">
                <ok/>
            </rpc-reply>
            """)
        self.netconf.transport.loseConnection.assert_called_with()

    def test_get_config_support(self):
        self.netconf.datastore.set_data(
            RUNNING, {"configuration": {
                "stuff": "is cool!"
            }})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <get-config>
                <source><running /></source>
              </get-config>
            </rpc>
            ]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
                <data>
                  <configuration>
                    <stuff>is cool!</stuff>
                  </configuration>
                </data>
            </rpc-reply>
            """)

        assert_that(self.netconf.transport.loseConnection.called,
                    equal_to(False))

    def test_request_with_namespace(self):
        self.netconf.datastore.set_data(
            RUNNING, {"configuration": {
                "stuff": "is cool!"
            }})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <nc:get-config>
                <nc:source><nc:running/></nc:source>
              </nc:get-config>
            </nc:rpc>
            ]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
                <data>
                  <configuration>
                    <stuff>is cool!</stuff>
                  </configuration>
                </data>
            </rpc-reply>
            """)

    def test_edit_config(self):
        self.netconf.datastore.set_data(
            RUNNING, {"configuration": {
                "stuff": {
                    "substuff": "is cool!"
                }
            }})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""<?xml version="1.0" encoding="UTF-8"?>
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:346c9f18-c420-11e4-8e4c-fa163ecd3b0a">
                <nc:edit-config>
                    <nc:target>
                        <nc:candidate/>
                    </nc:target>
                    <nc:config>
                        <nc:configuration><nc:stuff><substuff>is hot!</substuff></nc:stuff></nc:configuration>
                    </nc:config>
                </nc:edit-config>
            </nc:rpc>]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:346c9f18-c420-11e4-8e4c-fa163ecd3b0a">
                <ok/>
            </rpc-reply>
            """)

    def test_reply_includes_additional_namespaces(self):
        self.netconf.additionnal_namespaces = {
            "junos": "http://xml.juniper.net/junos/11.4R1/junos",
            "nc": "urn:ietf:params:xml:ns:netconf:base:1.0",
        }
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <nc:get-config>
                <nc:source><nc:running/></nc:source>
              </nc:get-config>
            </nc:rpc>
            ]]>]]>""")

        assert_that(
            self.netconf.transport.write.call_args[0][0],
            xml_equals_to("""
            <rpc-reply xmlns:junos="http://xml.juniper.net/junos/11.4R1/junos" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <data/>
            </rpc-reply>
            ]]>]]>
            """))

    def test_filtering(self):
        content = dict_2_etree({
            "data": {
                "configuration": [{
                    "shizzle": {
                        "whizzle": {}
                    }
                }, {
                    "shizzle": {
                        "whizzle": {
                            "howdy": {}
                        },
                        "not-whizzle": {
                            "not-howdy": {}
                        }
                    }
                }, {
                    "zizzle": {
                        "nothing": {}
                    }
                }, {
                    "outzzle": {
                        "nothing": {}
                    }
                }]
            }
        })

        content_filter = dict_2_etree({
            "filter": {
                "configuration": {
                    "shizzle": {
                        "whizzle": {}
                    },
                    "zizzle": {},
                }
            }
        })

        filter_content(content, content_filter)

        assert_that(content.xpath("//data/configuration/shizzle"),
                    has_length(2))
        assert_that(content.xpath("//data/configuration/shizzle/*"),
                    has_length(2))
        assert_that(
            content.xpath("//data/configuration/shizzle/whizzle/howdy"),
            has_length(1))
        assert_that(content.xpath("//data/configuration/zizzle"),
                    has_length(1))
        assert_that(content.xpath("//data/configuration/outzzle"),
                    has_length(0))

    def test_filtering_with_a_value(self):
        content = dict_2_etree({
            "data": {
                "configuration": [
                    {
                        "element": {
                            "element-key": "MY-KEY",
                            "attribute": {
                                "sub-attribute": {}
                            }
                        }
                    },
                    {
                        "element": {
                            "element-key": "MY-OTHER-KEY",
                            "other-attribute": {
                                "sub-attribute": {}
                            }
                        }
                    },
                ]
            }
        })

        content_filter = dict_2_etree({
            "filter": {
                "configuration": {
                    "element": {
                        "element-key": "MY-KEY"
                    },
                }
            }
        })

        filter_content(content, content_filter)

        assert_that(content.xpath("//data/configuration/element"),
                    has_length(1))
        assert_that(content.xpath("//data/configuration/element/*"),
                    has_length(2))
        assert_that(content.xpath("//data/configuration/element/attribute/*"),
                    has_length(1))

    def say_hello(self):
        self.netconf.dataReceived(
            '<hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability></capabilities></hello>]]>]]>'
        )

    def assert_xml_response(self, expected):
        data = self.netconf.transport.write.call_args[0][0]
        assert_that(data, ends_with("]]>]]>\n"))
        data = data.replace("]]>]]>", "")
        assert_that(data, xml_equals_to(expected))
 def setUp(self):
     self.netconf = NetconfProtocol(logger=logging.getLogger())
     self.netconf.transport = Mock()
class NetconfProtocolTest(unittest.TestCase):
    def setUp(self):
        self.netconf = NetconfProtocol(logger=logging.getLogger())
        self.netconf.transport = Mock()

    def test_says_hello_upon_connection_and_receive_an_hello(self):
        self.netconf.connectionMade()

        self.assert_xml_response("""
            <hello>
              <session-id>1</session-id>
              <capabilities>
                <capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability>
              </capabilities>
            </hello>
            """)

    def test_close_session_support(self):
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived('<nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="12345">\n')
        self.netconf.dataReceived('  <nc:close-session/>\n')
        self.netconf.dataReceived('</nc:rpc>\n')
        self.netconf.dataReceived(']]>]]>\n')

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="12345">
                <ok/>
            </rpc-reply>
            """)
        self.netconf.transport.loseConnection.assert_called_with()

    def test_get_config_support(self):
        self.netconf.datastore.set_data(RUNNING, {"configuration": {"stuff": "is cool!"}})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <rpc xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <get-config>
                <source><running /></source>
              </get-config>
            </rpc>
            ]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
                <data>
                  <configuration>
                    <stuff>is cool!</stuff>
                  </configuration>
                </data>
            </rpc-reply>
            """)

        assert_that(self.netconf.transport.loseConnection.called, equal_to(False))

    def test_request_with_namespace(self):
        self.netconf.datastore.set_data(RUNNING, {"configuration": {"stuff": "is cool!"}})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <nc:get-config>
                <nc:source><nc:running/></nc:source>
              </nc:get-config>
            </nc:rpc>
            ]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
                <data>
                  <configuration>
                    <stuff>is cool!</stuff>
                  </configuration>
                </data>
            </rpc-reply>
            """)

    def test_edit_config(self):
        self.netconf.datastore.set_data(RUNNING, {"configuration": {"stuff": {"substuff": "is cool!"}}})
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""<?xml version="1.0" encoding="UTF-8"?>
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:346c9f18-c420-11e4-8e4c-fa163ecd3b0a">
                <nc:edit-config>
                    <nc:target>
                        <nc:candidate/>
                    </nc:target>
                    <nc:config>
                        <nc:configuration><nc:stuff><substuff>is hot!</substuff></nc:stuff></nc:configuration>
                    </nc:config>
                </nc:edit-config>
            </nc:rpc>]]>]]>""")

        self.assert_xml_response("""
            <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="urn:uuid:346c9f18-c420-11e4-8e4c-fa163ecd3b0a">
                <ok/>
            </rpc-reply>
            """)

    def test_reply_includes_additional_namespaces(self):
        self.netconf.additionnal_namespaces = {
            "junos": "http://xml.juniper.net/junos/11.4R1/junos",
            "nc": "urn:ietf:params:xml:ns:netconf:base:1.0",
        }
        self.netconf.connectionMade()
        self.say_hello()

        self.netconf.dataReceived("""
            <nc:rpc xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <nc:get-config>
                <nc:source><nc:running/></nc:source>
              </nc:get-config>
            </nc:rpc>
            ]]>]]>""")

        assert_that(self.netconf.transport.write.call_args[0][0], xml_equals_to("""
            <rpc-reply xmlns:junos="http://xml.juniper.net/junos/11.4R1/junos" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" message-id="67890">
              <data/>
            </rpc-reply>
            ]]>]]>
            """
                                                                                ))

    def test_filtering(self):
        content = dict_2_etree({
            "data": {
                "configuration": [
                    {"shizzle": {
                        "whizzle": {}
                    }},
                    {"shizzle": {
                        "whizzle": {
                            "howdy": {}
                        },
                        "not-whizzle": {
                            "not-howdy": {}
                        }
                    }},
                    {"zizzle": {
                        "nothing": {}
                    }},
                    {"outzzle": {
                        "nothing": {}
                    }}
                ]
            }
        })

        content_filter = dict_2_etree({
            "filter": {
                "configuration": {
                    "shizzle": {"whizzle": {}},
                    "zizzle": {},
                }
            }
        })

        filter_content(content, content_filter)

        assert_that(content.xpath("//data/configuration/shizzle"), has_length(2))
        assert_that(content.xpath("//data/configuration/shizzle/*"), has_length(2))
        assert_that(content.xpath("//data/configuration/shizzle/whizzle/howdy"), has_length(1))
        assert_that(content.xpath("//data/configuration/zizzle"), has_length(1))
        assert_that(content.xpath("//data/configuration/outzzle"), has_length(0))

    def test_filtering_with_a_value(self):
        content = dict_2_etree({
            "data": {
                "configuration": [
                    {"element": {
                        "element-key": "MY-KEY",
                        "attribute": {"sub-attribute": {}}
                    }},
                    {"element": {
                        "element-key": "MY-OTHER-KEY",
                        "other-attribute": {"sub-attribute": {}}
                    }},
                ]
            }
        })

        content_filter = dict_2_etree({
            "filter": {
                "configuration": {
                    "element": {
                        "element-key": "MY-KEY"
                    },
                }
            }
        })

        filter_content(content, content_filter)

        assert_that(content.xpath("//data/configuration/element"), has_length(1))
        assert_that(content.xpath("//data/configuration/element/*"), has_length(2))
        assert_that(content.xpath("//data/configuration/element/attribute/*"), has_length(1))

    def say_hello(self):
        self.netconf.dataReceived(
            '<hello xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><capabilities><capability>urn:ietf:params:xml:ns:netconf:base:1.0</capability></capabilities></hello>]]>]]>')

    def assert_xml_response(self, expected):
        data = self.netconf.transport.write.call_args[0][0]
        assert_that(data, ends_with("]]>]]>\n"))
        data = data.replace("]]>]]>", "")
        assert_that(data, xml_equals_to(expected))