示例#1
0
 def test_cluster_password(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     midbc._get_password = mock.MagicMock()
     midbc._get_password.side_effect = self._fake_data
     _pass = "******"
     self.data = {"cluster-password": _pass}
     self.assertEqual(midbc.cluster_password, _pass)
示例#2
0
    def test_configure_instance(self):
        _pass = "******"
        _addr = "10.10.30.30"
        self.data = {"cluster-password": _pass}
        self.is_flag_set.return_value = False

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc._get_password = mock.MagicMock()
        midbc._get_password.side_effect = self._fake_data
        midbc._wait_until_connectable = mock.MagicMock()
        _script_template = """
        dba.configureInstance('{}:{}@{}');
        var myshell = shell.connect('{}:{}@{}');
        myshell.runSql("RESTART;");
        """.format(midbc.cluster_user, midbc.cluster_password, _addr,
                   midbc.cluster_user, midbc.cluster_password, _addr)

        midbc.configure_instance(_addr)
        self.is_flag_set.assert_called_once_with(
            "leadership.set.cluster-instance-configured-{}".format(_addr))
        self.subprocess.check_output.assert_called_once_with(
            [midbc.mysqlsh_bin, "--no-wizard", "-f", self.filename],
            stderr=self.stdin)
        self.file.write.assert_called_once_with(_script_template)
        midbc._wait_until_connectable.assert_called_once_with(
            address=_addr,
            username=midbc.cluster_user,
            password=midbc.cluster_password)
        self.leader_set.assert_called_once_with(
            {"cluster-instance-configured-{}".format(_addr): True})
示例#3
0
    def test__wait_unit_connectable(self):
        _pass = "******"
        _user = "******"
        _addr = "10.20.40.40"
        _conn_check = mock.MagicMock()

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.check_mysql_connection = _conn_check

        # Successful connect
        _conn_check.return_value = True
        midbc._wait_until_connectable(username=_user,
                                      password=_pass,
                                      address=_addr)
        _conn_check.assert_called_once_with(username=_user,
                                            password=_pass,
                                            address=_addr)

        # Failed to connect
        _conn_check.reset_mock()
        _conn_check.return_value = False
        with self.assertRaises(mysql_innodb_cluster.CannotConnectToMySQL):
            midbc._wait_until_connectable()
        _conn_check.assert_called_once_with(username=None,
                                            password=None,
                                            address=None)
示例#4
0
 def test_get_db_helper(self):
     _helper = mock.MagicMock()
     self.patch_object(mysql_innodb_cluster.mysql, "MySQL8Helper")
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     self.MySQL8Helper.return_value = _helper
     self.assertEqual(_helper, midbc.get_db_helper())
     self.MySQL8Helper.assert_called_once()
示例#5
0
    def test_custom_assess_status_check(self):
        _check = mock.MagicMock()
        _check.return_value = None, None
        _conn_check = mock.MagicMock()
        _conn_check.return_value = True

        # All is well
        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.check_if_paused = _check
        midbc.check_interfaces = _check
        midbc.check_mandatory_config = _check
        midbc.check_mysql_connection = _conn_check

        self.assertEqual((None, None), midbc.custom_assess_status_check())
        self.assertEqual(3, len(_check.mock_calls))
        _conn_check.assert_called_once_with()

        # First checks fail
        _check.return_value = "blocked", "for some reason"
        self.assertEqual(("blocked", "for some reason"),
                         midbc.custom_assess_status_check())

        # MySQL connect fails
        _check.return_value = None, None
        _conn_check.return_value = False
        self.assertEqual(("blocked", "MySQL is down"),
                         midbc.custom_assess_status_check())
示例#6
0
    def test_configure_db_router(self):
        _user = "******"
        _addr = "10.10.90.90"
        _pass = "******"
        _json_addrs = '["10.30.10.10", "10.30.10.20", "10.30.10.30"]'
        _helper = mock.MagicMock()
        _helper.configure_router.return_value = _pass
        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.get_db_helper = mock.MagicMock()
        midbc.get_db_helper.return_value = _helper

        # One host
        self.assertEqual(_pass, midbc.configure_db_router(_addr, _user))

        _helper.configure_router.assert_called_once_with(_addr, _user)

        # Json multiple hosts
        _helper.reset_mock()
        _calls = [
            mock.call("10.30.10.10", _user),
            mock.call("10.30.10.20", _user),
            mock.call("10.30.10.30", _user)
        ]
        self.assertEqual(_pass, midbc.configure_db_router(_json_addrs, _user))
        _helper.configure_router.assert_has_calls(_calls)
示例#7
0
    def test_check_mysql_connection(self):
        self.patch_object(mysql_innodb_cluster.mysql.MySQLdb, "_exceptions")
        self._exceptions.OperationalError = Exception
        _helper = mock.MagicMock()
        _pass = "******"
        _root_pass = "******"
        _user = "******"
        _addr = "10.20.30.30"
        self.data = {"mysql.passwd": _root_pass}

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.get_db_helper = mock.MagicMock()
        midbc.get_db_helper.return_value = _helper
        midbc._get_password = mock.MagicMock()
        midbc._get_password.side_effect = self._fake_data

        self.assertTrue(
            midbc.check_mysql_connection(username=_user,
                                         password=_pass,
                                         address=_addr))
        _helper.connect.assert_called_once_with(user=_user,
                                                password=_pass,
                                                host=_addr)

        _helper.reset_mock()
        _helper.connect.side_effect = self._exceptions.OperationalError
        self.assertFalse(midbc.check_mysql_connection())
        _helper.connect.assert_called_once_with(user="******",
                                                password=_root_pass,
                                                host="localhost")
示例#8
0
    def test_create_cluster(self):
        _pass = "******"
        _addr = "10.10.40.40"
        _name = "jujuCluster"
        self.get_relation_ip.return_value = _addr
        self.data = {"cluster-password": _pass}
        self.is_flag_set.side_effect = [False, True]

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc._get_password = mock.MagicMock()
        midbc._get_password.side_effect = self._fake_data
        midbc._wait_until_connectable = mock.MagicMock()
        midbc.options.cluster_name = _name
        _script_template = """
        shell.connect("{}:{}@{}")
        var cluster = dba.createCluster("{}");
        """.format(midbc.cluster_user, midbc.cluster_password,
                   midbc.cluster_address, midbc.cluster_name)

        midbc.create_cluster()
        _is_flag_set_calls = [
            mock.call("leadership.set.cluster-created"),
            mock.call(
                "leadership.set.cluster-instance-configured-{}".format(_addr))
        ]
        self.is_flag_set.assert_has_calls(_is_flag_set_calls)
        self.subprocess.check_output.assert_called_once_with(
            [midbc.mysqlsh_bin, "--no-wizard", "-f", self.filename],
            stderr=self.stdin)
        self.file.write.assert_called_once_with(_script_template)
        _leader_set_calls = [
            mock.call({"cluster-instance-clustered-{}".format(_addr): True}),
            mock.call({"cluster-created": self.uuid_of_cluster})
        ]
        self.leader_set.assert_has_calls(_leader_set_calls)
示例#9
0
 def test_get_allowed_units(self):
     _allowed = ["unit/2", "unit/1", "unit/0"]
     _expected = "unit/0 unit/1 unit/2"
     _helper = mock.MagicMock()
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     midbc.get_db_helper = mock.MagicMock()
     midbc.get_db_helper.return_value = _helper
     _helper.get_allowed_units.return_value = _allowed
     self.assertEqual(_expected,
                      midbc.get_allowed_units("db", "user", "rel:2"))
示例#10
0
 def test_install(self):
     self.patch_object(
         mysql_innodb_cluster.charms_openstack.charm.OpenStackCharm,
         "install", "super_install")
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     midbc.configure_mysql_password = mock.MagicMock()
     midbc.configure_source = mock.MagicMock()
     midbc.render_all_configs = mock.MagicMock()
     midbc.install()
     self.super_install.assert_called_once()
     midbc.configure_mysql_password.assert_called_once()
     midbc.configure_source.assert_called_once()
     midbc.render_all_configs.assert_called_once()
示例#11
0
 def test__get_password(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     # Pwgen
     _pwgenpass = "******"
     self.pwgen.return_value = _pwgenpass
     self.assertEqual(midbc._get_password("pwgenpw"), _pwgenpass)
     # Config
     _configpass = "******"
     self.config_data = {"configpw": _configpass}
     self.assertEqual(midbc._get_password("configpw"), _configpass)
     # Leader settings
     _leaderpass = "******"
     self.leader_data = {"leaderpw": _leaderpass}
     self.assertEqual(midbc._get_password("leaderpw"), _leaderpass)
示例#12
0
 def test_configure_mysql_password(self):
     _pass = "******"
     self.data = {"mysql.passwd": _pass}
     _debconf = mock.MagicMock()
     self.subprocess.Popen.return_value = _debconf
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     midbc._get_password = mock.MagicMock()
     midbc._get_password.side_effect = self._fake_data
     midbc.configure_mysql_password()
     _calls = []
     for package in ["mysql-server", "mysql-server-8.0"]:
         _calls.append(
             mock.call("{} {}/root_password password {}\n".format(
                 package, package, _pass).encode("UTF-8")))
         _calls.append(
             mock.call("{} {}/root_password_again password {}\n".format(
                 package, package, _pass).encode("UTF-8")))
     _debconf.stdin.write.assert_has_calls(_calls, any_order=True)
示例#13
0
    def test_create_cluster_user(self):
        _user = "******"
        _pass = "******"
        _addr = "10.10.20.20"
        _helper = mock.MagicMock()
        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.get_db_helper = mock.MagicMock()
        midbc.get_db_helper.return_value = _helper
        # Non-local
        midbc.create_cluster_user(_addr, _user, _pass)
        _calls = [
            mock.call("CREATE USER '{}'@'{}' IDENTIFIED BY '{}'".format(
                _user, _addr, _pass)),
            mock.call("GRANT ALL PRIVILEGES ON *.* TO '{}'@'{}'".format(
                _user, _addr)),
            mock.call("GRANT GRANT OPTION ON *.* TO '{}'@'{}'".format(
                _user, _addr)),
            mock.call("flush privileges")
        ]
        _helper.execute.assert_has_calls(_calls)

        # Local
        _localhost = "localhost"
        _helper.reset_mock()
        self.get_relation_ip.return_value = _addr
        midbc.create_cluster_user(_addr, _user, _pass)
        _calls = [
            mock.call("CREATE USER '{}'@'{}' IDENTIFIED BY '{}'".format(
                _user, _addr, _pass)),
            mock.call("GRANT ALL PRIVILEGES ON *.* TO '{}'@'{}'".format(
                _user, _addr)),
            mock.call("GRANT GRANT OPTION ON *.* TO '{}'@'{}'".format(
                _user, _addr)),
            mock.call('flush privileges'),
            mock.call("CREATE USER '{}'@'{}' IDENTIFIED BY '{}'".format(
                _user, _localhost, _pass)),
            mock.call("GRANT ALL PRIVILEGES ON *.* TO '{}'@'{}'".format(
                _user, _localhost)),
            mock.call("GRANT GRANT OPTION ON *.* TO '{}'@'{}'".format(
                _user, _localhost)),
            mock.call("flush privileges")
        ]
        _helper.execute.assert_has_calls(_calls)
示例#14
0
 def test_states_to_check(self):
     self.patch_object(
         mysql_innodb_cluster.charms_openstack.charm.OpenStackCharm,
         "states_to_check", "super_states")
     self.super_states.return_value = {}
     _required_rels = ["cluster"]
     _name = "jujuCluster"
     _addr = "10.20.20.20"
     self.get_relation_ip.return_value = _addr
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     midbc.options.cluster_name = _name
     _results = midbc.states_to_check(_required_rels)
     _states_to_check = [x[0] for x in _results["charm"]]
     self.super_states.assert_called_once_with(_required_rels)
     self.assertTrue("charm.installed" in _states_to_check)
     self.assertTrue("leadership.set.cluster-instance-configured-{}".format(
         _addr) in _states_to_check)
     self.assertTrue("leadership.set.cluster-created" in _states_to_check)
     self.assertTrue(
         "leadership.set.cluster-instances-configured" in _states_to_check)
     self.assertTrue("leadership.set.cluster-instance-clustered-{}".format(
         _addr) in _states_to_check)
     self.assertTrue(
         "leadership.set.cluster-instances-clustered" in _states_to_check)
示例#15
0
    def test_add_instance_to_cluster(self):
        _pass = "******"
        _local_addr = "10.10.50.50"
        _remote_addr = "10.10.60.60"
        _name = "theCluster"
        self.get_relation_ip.return_value = _local_addr
        self.data = {"cluster-password": _pass}
        self.is_flag_set.return_value = False

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc._get_password = mock.MagicMock()
        midbc._get_password.side_effect = self._fake_data
        midbc._wait_until_connectable = mock.MagicMock()
        midbc.options.cluster_name = _name
        _script_template = """
        shell.connect("{}:{}@{}")
        var cluster = dba.getCluster("{}");

        print("Adding instances to the cluster.");
        cluster.addInstance(
            {{user: "******", host: "{}", password: "******", port: "3306"}},
            {{recoveryMethod: "clone"}});
        """.format(midbc.cluster_user, midbc.cluster_password,
                   midbc.cluster_address, midbc.cluster_name,
                   midbc.cluster_user, _remote_addr, midbc.cluster_password)

        midbc.add_instance_to_cluster(_remote_addr)
        self.is_flag_set.assert_called_once_with(
            "leadership.set.cluster-instance-clustered-{}".format(
                _remote_addr))
        self.subprocess.check_output.assert_called_once_with(
            [midbc.mysqlsh_bin, "--no-wizard", "-f", self.filename],
            stderr=self.stdin)
        self.file.write.assert_called_once_with(_script_template)
        self.leader_set.assert_called_once_with(
            {"cluster-instance-clustered-{}".format(_remote_addr): True})
示例#16
0
    def test_create_databases_and_users_db_router(self):
        # The test setup is a bit convoluted and requires mimicking reactive,
        # however, this is the heart of the charm and therefore deserves to
        # be thoroughly tested. It is important to have multiple relations and
        # multiple units per relation.
        self.patch_object(mysql_innodb_cluster.mysql, "get_db_data")
        self.get_db_data.side_effect = self._fake_get_db_data

        _addr = "10.99.99.99"
        self.get_relation_ip.return_value = _addr

        self.interface.relations = {
            self.kmr_db_router.relation_id: self.kmr_db_router,
            self.nmr_db_router.relation_id: self.nmr_db_router
        }

        self.interface.all_joined_units = []
        for rel in self.interface.relations.values():
            self.interface.all_joined_units.extend(rel.joined_units)

        midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
        midbc.get_allowed_units = mock.MagicMock()
        midbc.get_allowed_units.side_effect = self._fake_get_allowed_units
        midbc.configure_db_for_hosts = mock.MagicMock()
        midbc.configure_db_for_hosts.side_effect = self._fake_configure
        midbc.configure_db_router = mock.MagicMock()
        midbc.configure_db_router.side_effect = self._fake_configure

        # Execute the function under test
        midbc.create_databases_and_users(self.interface)

        # Validate
        _conigure_db_router_calls = [
            mock.call(self.kmr_unit5_ip, "mysqlrouteruser"),
            mock.call(self.kmr_unit7_ip, "mysqlrouteruser"),
            mock.call(self.nmr_unit5_ip, "mysqlrouteruser"),
            mock.call(self.nmr_unit7_ip, "mysqlrouteruser")
        ]
        midbc.configure_db_router.assert_has_calls(_conigure_db_router_calls)

        _configure_db_calls = [
            mock.call(self.kmr_unit5_ip, "keystone", "keystone"),
            mock.call(self.kmr_unit7_ip, "keystone", "keystone"),
            mock.call(self.nmr_unit5_ip, "nova", "nova"),
            mock.call(self.nmr_unit5_ip, "nova_api", "nova"),
            mock.call(self.nmr_unit5_ip, "nova_cell0", "nova"),
            mock.call(self.nmr_unit7_ip, "nova", "nova"),
            mock.call(self.nmr_unit7_ip, "nova_api", "nova"),
            mock.call(self.nmr_unit7_ip, "nova_cell0", "nova")
        ]
        midbc.configure_db_for_hosts.assert_has_calls(_configure_db_calls)

        _set_calls = [
            mock.call(self.kmr_db_router.relation_id,
                      _addr,
                      "keystone-pwd",
                      allowed_units=self._fake_get_allowed_units(
                          None, None, self.kmr_db_router.relation_id),
                      prefix=self.mock_unprefixed),
            mock.call(self.kmr_db_router.relation_id,
                      _addr,
                      "mysqlrouteruser-pwd",
                      allowed_units=" ".join([
                          x.unit_name for x in self.kmr_db_router.joined_units
                      ]),
                      prefix="mysqlrouter"),
            mock.call(self.nmr_db_router.relation_id,
                      _addr,
                      "nova-pwd",
                      allowed_units=self._fake_get_allowed_units(
                          None, None, self.nmr_db_router.relation_id),
                      prefix="nova"),
            mock.call(self.nmr_db_router.relation_id,
                      _addr,
                      "nova-pwd",
                      allowed_units=self._fake_get_allowed_units(
                          None, None, self.nmr_db_router.relation_id),
                      prefix="novaapi"),
            mock.call(self.nmr_db_router.relation_id,
                      _addr,
                      "nova-pwd",
                      allowed_units=self._fake_get_allowed_units(
                          None, None, self.nmr_db_router.relation_id),
                      prefix="novacell0"),
            mock.call(self.nmr_db_router.relation_id,
                      _addr,
                      "mysqlrouteruser-pwd",
                      allowed_units=" ".join([
                          x.unit_name for x in self.nmr_db_router.joined_units
                      ]),
                      prefix="mysqlrouter")
        ]
        self.interface.set_db_connection_info.assert_has_calls(_set_calls)
示例#17
0
 def test_db_router_address(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     _addr = "10.10.10.70"
     self.get_relation_ip.return_value = _addr
     self.assertEqual(midbc.db_router_address, _addr)
示例#18
0
 def test_cluster_name(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     _name = "jujuCluster"
     midbc.options.cluster_name = _name
     self.assertEqual(midbc.cluster_name, _name)
示例#19
0
 def test_mysqlsh_bin(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     self.assertEqual(midbc.mysqlsh_bin,
                      "/snap/mysql-shell/current/usr/bin/mysqlsh")
示例#20
0
 def test_cluster_user(self):
     midbc = mysql_innodb_cluster.MySQLInnoDBClusterCharm()
     self.assertEqual(midbc.cluster_user, "clusteruser")