SDSM-for-SDI / experiment-scripts / migrate-server-console.py
migrate-server-console.py
Raw
#!/usr/bin/env python
#code taken from https://www.redhat.com/en/blog/container-migration-around-world and partially modified
import socket
import sys
from thread import *
import json
import os
import distutils.util
import subprocess
#import dns.update
#import dns.query
#import dns.tsigkeyring

def migrate_server(app_using_tcp):
    HOST = ''   # Symbolic name meaning all available interfaces
    PORT = 18863 # Arbitrary non-privileged port 8888

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print 'Socket created'

    #Bind socket to local host and port
    try:
        s.bind((HOST, PORT))
    except socket.error as msg:
        print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1]
        sys.exit()

    print 'Socket bind complete'

    #Start listening on socket
    s.listen(10)
    print 'Socket now listening'

    #Function for handling connections. This will be used to create threads
    def clientthread(conn, addr, app_using_tcp):
        #Sending message to connected client
        
        #infinite loop so that function do not terminate and thread do not end.
        while True:

            reply = ""
            #Receiving from client
            data = conn.recv(1024)
            if not data:
                break
            if data == 'exit':
                break

            try:
                msg = json.loads(data)
                if 'restore' in msg:

                    os.system('criu -V')

                    try:
                        lazy = bool(distutils.util.strtobool(msg['restore']['lazy']))
                    except:
                        lazy = False

                    old_cwd = os.getcwd()
                    os.chdir(msg['restore']['path'])
                    cmd = 'time -p runc restore --console-socket ' + msg['restore']['path']
                    cmd += '/console.sock -d --image-path ' + msg['restore']['image_path']
                    cmd += ' --work-path ' + msg['restore']['image_path']
                    if lazy:
                            cmd += ' --lazy-pages'
                    cmd += ' ' + msg['restore']['name']
                    print "Running " +  cmd
                    p = subprocess.Popen(cmd, shell=True)
                    if lazy:
                        cmd = "criu lazy-pages --page-server --address " + addr
                        cmd += " --port 27 -vv -D "
                        cmd += msg['restore']['image_path']
                        cmd += " -W "
                        cmd += msg['restore']['image_path']
                        print "Running lazy-pages server: " + cmd
                        lp = subprocess.Popen(cmd, shell=True)
                    ret = p.wait()
                    if ret == 0:
                        reply = "runc restored %s successfully" % msg['restore']['name']
                    else:
                        reply = "runc failed(%d)" % ret
                    os.chdir(old_cwd)
                else:
                    print "Unkown request : " + msg
            except:
                continue
            
            print reply

            #update the DNS server with the new IP address of the container
            #this is done only in case of app_using_tcp = True
            #if QUIC is used instead, this is not done
            #if app_using_tcp:
                #print("Starting update of DNS")
                #os.system("python3 /home/oem/master/dnsupdater.py")
                #keyring = dns.tsigkeyring.from_text({
                 #   'mycompanion.com.': 'OlOAxkefYKheCw8+rm92jw=='
                #})

                #update = dns.update.Update('mycompanion.com', keyring=keyring, keyalgorithm='hmac-md5.sig-alg.reg.int')
                #update.replace('myservice', 5, 'A', '192.168.3.1')
                #response = dns.query.tcp(update, '192.168.1.53')
                #print(str(response))

            conn.sendall(reply)

        #came out of loop
        conn.close()


    #now keep talking with the client
    while 1:
        #wait to accept a connection - blocking call
        conn, addr = s.accept()
        print 'Connected with ' + addr[0] + ':' + str(addr[1])

        #start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
        start_new_thread(clientthread ,(conn, str(addr[0]), app_using_tcp))

    s.close()

if __name__ == '__main__':
    
    #app_using_tcp is a boolean that indicates whether (True) or not (False) the client-server application is using TCP at transport layer
    #this is used to decide if DNS server needs to be updated with the new IP address of the container
    app_using_tcp = sys.argv[1]

    migrate_server(app_using_tcp)