Esempio n. 1
0
def test_dump_configuration_busy(database_connection):
    magic_castle = MagicCastle(database_connection, "missingfloatingips.c3.ca")
    assert magic_castle.dump_configuration() == {
        "cluster_name": "missingfloatingips",
        "domain": "c3.ca",
        "image": "CentOS-7-x64-2019-07",
        "nb_users": 17,
        "instances": {
            "mgmt": {
                "type": "p4-6gb",
                "count": 1
            },
            "login": {
                "type": "p4-6gb",
                "count": 1
            },
            "node": {
                "type": "p2-3gb",
                "count": 3
            },
        },
        "storage": {
            "type": "nfs",
            "home_size": 50,
            "project_size": 1,
            "scratch_size": 1,
        },
        "public_keys": [""],
        "hieradata": "",
        "guest_passwd": "password-123",
        "os_floating_ips": ["Automatic allocation"],
    }
Esempio n. 2
0
def test_get_status_valid(database_connection):
    created = MagicCastle(database_connection, "created.calculquebec.cloud")
    assert created.get_status() == ClusterStatusCode.CREATED
    buildplanning = MagicCastle(database_connection,
                                "buildplanning.calculquebec.cloud")
    assert buildplanning.get_status() == ClusterStatusCode.PLAN_RUNNING
    valid1 = MagicCastle(database_connection, "valid1.calculquebec.cloud")
    assert valid1.get_status() == ClusterStatusCode.PROVISIONING_SUCCESS
Esempio n. 3
0
 def get_all_magic_castles(self):
     """
     Retrieve all the Magic Castles retrieved in the database.
     :return: A list of MagicCastle objects
     """
     results = self._database_connection.execute(
         "SELECT hostname FROM magic_castles").fetchall()
     return [MagicCastle(result[0]) for result in results]
Esempio n. 4
0
 def get_magic_castle_by_hostname(self, hostname):
     if self.is_admin():
         results = self._database_connection.execute(
             "SELECT hostname, owner FROM magic_castles WHERE hostname = ?",
             (hostname, ),
         )
     else:
         results = self._database_connection.execute(
             "SELECT hostname, owner FROM magic_castles WHERE owner = ? AND hostname = ?",
             (self.edu_person_principal_name, hostname),
         )
     row = results.fetchone()
     if row:
         return MagicCastle(hostname=row[0], owner=row[1])
     else:
         raise ClusterNotFoundException
Esempio n. 5
0
def test_create_magic_castle_init_fail(database_connection, monkeypatch):
    def fake_run(process_args, *args, **kwargs):
        if process_args == ["terraform", "init", "-no-color", "-input=false"]:
            raise CalledProcessError(1, "terraform init")

    monkeypatch.setattr("models.magic_castle.magic_castle.run", fake_run)
    cluster = MagicCastle(database_connection, "a-123-45.calculquebec.cloud")
    cluster.set_configuration(VALID_CLUSTER_CONFIGURATION)
    with pytest.raises(
            PlanException,
            match="An error occurred while initializing Terraform."):
        cluster.plan_creation()
Esempio n. 6
0
    def get_all_magic_castles(self):
        """
        If the user is admin, it will retrieve all the clusters,
        otherwise, only the clusters owned by the user.

        :return: A list of MagicCastle objects
        """
        if self.is_admin():
            results = self._database_connection.execute(
                "SELECT hostname, owner FROM magic_castles")
        else:
            results = self._database_connection.execute(
                "SELECT hostname, owner FROM magic_castles WHERE owner = ?",
                (self.edu_person_principal_name, ),
            )
        return [
            MagicCastle(hostname=result[0], owner=result[1])
            for result in results.fetchall()
        ]
Esempio n. 7
0
def test_create_magic_castle_plan_export_fail(database_connection,
                                              monkeypatch):
    def fake_run(process_args, *args, **kwargs):
        if process_args[:4] == [
                "terraform",
                "show",
                "-no-color",
                "-json",
        ]:
            raise CalledProcessError(1, "terraform show")

    monkeypatch.setattr("models.magic_castle.magic_castle.run", fake_run)
    cluster = MagicCastle(database_connection, "a-123-45.calculquebec.cloud")
    cluster.set_configuration(VALID_CLUSTER_CONFIGURATION)
    with pytest.raises(
            PlanException,
            match="An error occurred while exporting planned changes."):
        cluster.plan_creation()
Esempio n. 8
0
 def create_empty_magic_castle(self):
     return MagicCastle(self._database_connection,
                        owner=self.edu_person_principal_name)
Esempio n. 9
0
def test_get_available_resources_missing_nodes(database_connection):
    """
    Mock context :

    missingnodes cluster uses
    0 instance
    0 vcpus
    0 ram
    0 [root disks] + 3 [external volumes] = 3 volumes
    0 + 0 + 0 [root disks]
    + 50 + 50 + 100 [external volumes] = 200 GiO of volume storage

    openstack's quotas says there currently remains:
    128 - 28 = 100 instances
    500 - 199 = 301 vcpus
    286,720 - 184,320 = 102,400 ram (100 GiO)
    128 - 100 = 28 volumes
    1000 - 720 = 280 GiO of volume storage

    Therefore, missingnodes cluster can use a total of:
    0 + 100 = 0 instances
    0 + 301 = 301 vcpus
    0 + 102,400 = 102,400 ram (100 GiO)
    3 + 28 = 31 volumes
    200 + 280 = 480 GiO of volume storage
    """
    magic_castle = MagicCastle(database_connection,
                               "missingnodes.sub.example.com")
    assert magic_castle.get_available_resources() == {
        "quotas": {
            "instance_count": {
                "max": 100
            },
            "ram": {
                "max": 102_400
            },
            "vcpus": {
                "max": 301
            },
            "volume_count": {
                "max": 31
            },
            "volume_size": {
                "max": 480
            },
        },
        "resource_details": {
            "instance_types": [
                {
                    "name": "p1-1.5gb",
                    "vcpus": 1,
                    "ram": 1_536,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "p2-3gb",
                    "vcpus": 2,
                    "ram": 3_072,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "p4-6gb",
                    "vcpus": 4,
                    "ram": 6_144,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "c8-30gb-186",
                    "vcpus": 8,
                    "ram": 30_720,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "c8-90gb-186",
                    "vcpus": 8,
                    "ram": 92_160,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "g2-c24-112gb-500",
                    "vcpus": 24,
                    "ram": 114_688,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "c16-120gb-392",
                    "vcpus": 16,
                    "ram": 122_880,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
            ]
        },
        "possible_resources": {
            "image": ["centos7", "CentOS-8 x64", "CentOS VGPU"],
            "instances": {
                "mgmt": {
                    "type": [
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
                "login": {
                    "type": [
                        "p2-3gb",
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
                "node": {
                    "type": [
                        "p2-3gb",
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
            },
            "os_floating_ips": [
                "Automatic allocation",
                "100.101.102.103",
                "2.1.1.1",
                "2.1.1.2",
                "2.1.1.3",
            ],
            "storage": {
                "type": ["nfs"]
            },
            "domain": ["calculquebec.cloud", "c3.ca", "sub.example.com"],
        },
    }
Esempio n. 10
0
def test_dump_configuration_not_found(database_connection):
    magic_castle = MagicCastle(database_connection)
    with pytest.raises(ClusterNotFoundException):
        magic_castle.dump_configuration()
Esempio n. 11
0
def test_create_magic_castle_plan_valid(database_connection):
    cluster = MagicCastle(database_connection, "a-123-45.calculquebec.cloud")
    cluster.set_configuration(VALID_CLUSTER_CONFIGURATION)
    cluster.plan_creation()
Esempio n. 12
0
def test_dump_configuration_missing_nodes(database_connection):
    magic_castle = MagicCastle(database_connection,
                               "missingnodes.sub.example.com")
    assert magic_castle.dump_configuration(planned_only=True) == {
        "cluster_name": "missingnodes",
        "nb_users": 10,
        "guest_passwd": "password-123",
        "storage": {
            "type": "nfs",
            "home_size": 100,
            "scratch_size": 50,
            "project_size": 50,
        },
        "instances": {
            "mgmt": {
                "type": "p4-6gb",
                "count": 1
            },
            "login": {
                "type": "p4-6gb",
                "count": 1
            },
            "node": {
                "type": "p2-3gb",
                "count": 1
            },
        },
        "domain": "sub.example.com",
        "hieradata": "",
        "public_keys": [""],
        "image": "CentOS-7-x64-2019-07",
        "os_floating_ips": ["100.101.102.103"],
    }
    assert magic_castle.dump_configuration(planned_only=False) == {
        "cluster_name": "missingnodes",
        "nb_users": 10,
        "guest_passwd": "password-123",
        "storage": {
            "type": "nfs",
            "home_size": 100,
            "scratch_size": 50,
            "project_size": 50,
        },
        "instances": {
            "mgmt": {
                "type": "",
                "count": 0
            },
            "login": {
                "type": "",
                "count": 0
            },
            "node": {
                "type": "",
                "count": 0
            },
        },
        "domain": "sub.example.com",
        "hieradata": "",
        "public_keys": ["ssh-rsa FAKE"],
        "image": "CentOS-7-x64-2019-07",
        "os_floating_ips": ["100.101.102.103"],
    }
Esempio n. 13
0
 def create_empty_magic_castle(self):
     return MagicCastle()
Esempio n. 14
0
def test_get_owner_no_owner(database_connection):
    magic_castle = MagicCastle(database_connection,
                               "noowner.calculquebec.cloud")
    assert magic_castle.get_owner() == None
Esempio n. 15
0
def test_get_status_errors(database_connection):
    empty = MagicCastle(database_connection, "empty.calculquebec.cloud")
    assert empty.get_status() == ClusterStatusCode.BUILD_ERROR
    missingnodes = MagicCastle(database_connection,
                               "missingnodes.sub.example.com")
    assert missingnodes.get_status() == ClusterStatusCode.BUILD_ERROR
Esempio n. 16
0
 def create_empty_magic_castle(self):
     return MagicCastle(self._database_connection)
Esempio n. 17
0
 def create_empty_magic_castle(self):
     return MagicCastle(owner=self.edu_person_principal_name)
Esempio n. 18
0
def test_get_plan_type_destroy(database_connection):
    magic_castle = MagicCastle(database_connection,
                               "valid1.calculquebec.cloud")
    assert magic_castle.get_plan_type() == PlanType.DESTROY
Esempio n. 19
0
def test_get_plan_type_build(database_connection):
    build_planning = MagicCastle(database_connection,
                                 "buildplanning.calculquebec.cloud")
    assert build_planning.get_plan_type() == PlanType.BUILD
    created = MagicCastle(database_connection, "created.calculquebec.cloud")
    assert created.get_plan_type() == PlanType.BUILD
Esempio n. 20
0
def test_get_status_not_found(database_connection):
    magic_castle1 = MagicCastle(database_connection, "nonexisting")
    assert magic_castle1.get_status() == ClusterStatusCode.NOT_FOUND
    magic_castle2 = MagicCastle(database_connection)
    assert magic_castle2.get_status() == ClusterStatusCode.NOT_FOUND
Esempio n. 21
0
def test_get_available_resources_not_found(database_connection):
    """
    Mock context :

    openstack's quotas says there currently remains:
    128 - 28 = 100 instances
    500 - 199 = 301 vcpus
    286,720 - 184,320 = 102,400 ram (100 GiO)
    128 - 100 = 28 volumes
    1000 - 720 = 280 GiO of volume storage
    """
    magic_castle = MagicCastle(database_connection)
    assert magic_castle.get_available_resources() == {
        "quotas": {
            "instance_count": {
                "max": 100
            },
            "ram": {
                "max": 102_400
            },
            "vcpus": {
                "max": 301
            },
            "volume_count": {
                "max": 28
            },
            "volume_size": {
                "max": 280
            },
        },
        "resource_details": {
            "instance_types": [
                {
                    "name": "p1-1.5gb",
                    "vcpus": 1,
                    "ram": 1_536,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "p2-3gb",
                    "vcpus": 2,
                    "ram": 3_072,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "p4-6gb",
                    "vcpus": 4,
                    "ram": 6_144,
                    "required_volume_count": 1,
                    "required_volume_size": 10,
                },
                {
                    "name": "c8-30gb-186",
                    "vcpus": 8,
                    "ram": 30_720,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "c8-90gb-186",
                    "vcpus": 8,
                    "ram": 92_160,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "g2-c24-112gb-500",
                    "vcpus": 24,
                    "ram": 114_688,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
                {
                    "name": "c16-120gb-392",
                    "vcpus": 16,
                    "ram": 122_880,
                    "required_volume_count": 0,
                    "required_volume_size": 0,
                },
            ]
        },
        "possible_resources": {
            "image": ["centos7", "CentOS-8 x64", "CentOS VGPU"],
            "instances": {
                "mgmt": {
                    "type": [
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
                "login": {
                    "type": [
                        "p2-3gb",
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
                "node": {
                    "type": [
                        "p2-3gb",
                        "p4-6gb",
                        "c8-30gb-186",
                        "c8-90gb-186",
                        "g2-c24-112gb-500",
                        "c16-120gb-392",
                    ]
                },
            },
            "os_floating_ips": [
                "Automatic allocation",
                "2.1.1.1",
                "2.1.1.2",
                "2.1.1.3",
            ],
            "storage": {
                "type": ["nfs"]
            },
            "domain": ["calculquebec.cloud", "c3.ca", "sub.example.com"],
        },
    }
Esempio n. 22
0
def test_dump_configuration_empty(database_connection):
    magic_castle = MagicCastle(database_connection, "empty.calculquebec.cloud")
    assert magic_castle.dump_configuration() == dict()
Esempio n. 23
0
def test_get_plan_type_none(database_connection):
    magic_castle = MagicCastle(database_connection, "missingfloatingips.c3.ca")
    assert magic_castle.get_plan_type() == PlanType.NONE
Esempio n. 24
0
 def get_magic_castle_by_hostname(self, hostname):
     return MagicCastle(hostname)
Esempio n. 25
0
 def get_magic_castle_by_hostname(self, hostname):
     return MagicCastle(self._database_connection, hostname)
Esempio n. 26
0
def test_get_owner_valid(database_connection):
    magic_castle = MagicCastle(database_connection, "missingfloatingips.c3.ca")
    assert magic_castle.get_owner() == "*****@*****.**"