view PerfsDb/DbServer.py @ 156:f1a75985caa8

first Db test framework - work in progress
author am@osimis.io
date Thu, 16 Aug 2018 17:13:32 +0200
parents
children df1f9946571c
line wrap: on
line source

import typing
import subprocess
import time

from DbType import DbType

class DbServer:

    class DockerDefinition:

        def __init__(self, image: str, internalPort: int, envVars: typing.Dict[str, str], storagePath: str, command: typing.List[str]=None):
            self.image = image
            self.internalPort = internalPort
            self.envVars = envVars
            self.storagePath = storagePath
            self.command = command

    def __init__(self, dbType: DbType, port: int):

        self.port = port
        self.dbType = dbType

        self._containerId = None
        self._label = None

    def setLabel(self, label: str):
        self._label = label

    def launch(self):
        dockerDefinition = self.getDockerDefinition()

        # check if the container is already running
        ret = subprocess.call([
            "docker",
            "top",
            self._label
        ])            
        if ret == 0:
            print("DbServer is already running")
            return

        # create a volume (if it already exists, it wont be modified)
        subprocess.check_call([
            "docker", 
            "volume", 
            "create", 
            "--name=" + self._label
        ])
        
        dockerRunCommand = [
            "docker",
            "run",
            "-d",
            "--name=" + self._label,
            "-p", str(self.port) + ":" + str(dockerDefinition.internalPort),
            "--volume=" + self._label + ":" + dockerDefinition.storagePath
        ]

        if len(dockerDefinition.envVars) > 0:
            for k,v in dockerDefinition.envVars.items():
                dockerRunCommand.extend(["--env", k + "=" + v])
        
        dockerRunCommand.append(
            dockerDefinition.image
        )

        if dockerDefinition.command is not None:
            dockerRunCommand.extend(
                dockerDefinition.command
            )

        print("Launching DbServer")
        subprocess.check_call(dockerRunCommand)

        print("Waiting for DbServer to be ready")
        
        # wait until its port is open
        retryCounter = 0
        connected = False
        while not connected and retryCounter < 30:
            time.sleep(1)
            connected = subprocess.call(["nc", "-z", "localhost", str(self.port)]) == 0
        if retryCounter >= 30:
            print("DbServer still not ready after 30 sec")
            raise TimeoutError

    def stop(self):
        subprocess.check_call([
            "docker",
            "stop",
            self._label
        ])
        subprocess.check_call([
            "docker",
            "rm",
            self._label
        ])

    def clear(self):
        # remove the volume
        self.stop()        
        subprocess.check_call([
            "docker",
            "volume",
            "rm",
            self._label
        ])


    def getDockerDefinition(self):
        if self.dbType == DbType.MySQL:
            return DbServer.DockerDefinition(
                image="mysql:8.0",
                internalPort=3306,
                envVars={
                    "MYSQL_PASSWORD": "orthanc",
                    "MYSQL_USER": "orthanc",
                    "MYSQL_DATABASE": "orthanc",
                    "MYSQL_ROOT_PASSWORD": "foo-root"       
                },
                storagePath="/var/lib/mysql",
                command=["mysqld", "--default-authentication-plugin=mysql_native_password", "--log-bin-trust-function-creators=1"]
            )
        elif self.dbType == DbType.MSSQL:
            return DbServer.DockerDefinition(
                image="microsoft/mssql-server-linux", 
                internalPort=1433,
                envVars={
                    "ACCEPT_EULA": "Y",
                    "SA_PASSWORD": "MyStrOngPa55word!"
                },
                storagePath="/var/opt/mssql/data"
            )
        elif self.dbType == DbType.PG9 or self.dbType == DbType.PG10:
            if self.dbType == DbType.PG9:
                image = "postgres:9"
            elif self.dbType == DbType.PG10:
                image = "postgres:10"
            return DbServer.DockerDefinition(
                image=image, 
                internalPort=5432,
                envVars={
                },
                storagePath="/var/lib/postgresql/data"
            )