예제 #1
0
    def execute(self, parameters=None):
        """
        installs worker node on the machine.
        """
        logger = XprLogger()
        if not linux_utils.check_root():
            logger.fatal("Please run this as root")

        self.cleanup()
        logger.info("Initialising Kubernetes worker node...")
        try:

            if parameters and self.PARAMETER_MASTER_IP in parameters:
                master_ip = parameters[self.PARAMETER_MASTER_IP]
            else:
                master_ip = input("Enter the IP address of the master"
                                  " node you want to join:")
            path = '/mnt/nfs/data/k8/k8_clusters/{}/{}.txt'. \
                format(master_ip, master_ip)
            with open(path, "r") as f:
                join_command = f.read()  # extract join command
            self.executor.execute(
                join_command)  # run command to join the cluster
        except CommandExecutionFailedException as e:
            logger.error("Failed to setup worker node. \n{}".format(str(e)))
            return False
        return True
    def execute(self):
        """
        installs kubeadm on the machine.
        """
        logger = XprLogger()
        if not linux_utils.check_root():
            logger.fatal("Please run this as root")
        logger.info("Installing Kubeadm...")

        try:
            swapoff = 'swapoff -a'
            self.executor.execute(swapoff)  # turns swap off
            add_key = 'curl -s ' \
                      'https://packages.cloud.google.com/apt/doc/apt-key.gpg ' \
                      '| apt-key add -'
            self.executor.execute(add_key)
            add_list_path = '/etc/apt/sources.list.d/kubernetes.list'
            add_list_content = 'deb https://apt.kubernetes.io/ ' \
                               'kubernetes-xenial main'
            linux_utils.write_to_file(add_list_content, add_list_path, "a")
            install_kubeadm = 'apt-get update && apt-get install ' \
                              '-y kubelet kubeadm kubectl'
            self.executor.execute(install_kubeadm)  # installs kubeadm
            hold_kubeadm = 'apt-mark hold kubelet kubeadm kubectl'
            self.executor.execute(hold_kubeadm)
        except CommandExecutionFailedException as e:
            logger.error("Failed to install Kubeadm. \n{}".format(str(e)))
            return False
        return True
    def execute(self, **kwargs):
        """
        Mounts the NFS on the VM
        """
        logger = XprLogger()
        if not linux_utils.check_root():
            logger.fatal("Please run this as root")
        logger.info("Mounting NFS File")
        subnet_to_nfs_map = self.config[self.NFS_SECTION][self.SUBNET_MAP_KEY]
        ip_address = linux_utils.get_ip_address()
        matched_nfs = None
        for nfs, subnet in subnet_to_nfs_map.items():
            logger.info("Matching {} {}".format(subnet, ip_address))
            check = re.match(subnet, ip_address)
            print(check)
            if check:
                matched_nfs = nfs
                break

        if not matched_nfs:
            logger.info("Could not determine nfs value")
            return False

        mount_location = self.config[self.NFS_SECTION][self.MOUNT_LOCATION_KEY]
        nfs_location = self.config[self.NFS_SECTION][self.NFS_LOCATION_KEY]
        mount_script = "mount {}:{} {}".format(matched_nfs, nfs_location,
                                               mount_location)
        logger.info("Mounting {}".format(mount_script))
        try:
            linux_utils.create_directory(mount_location, 0o755)
            self.executor.execute(mount_script)
            logger.info("Mount Succesful")
            logger.info("Updating fstab file")
            with open(self.FSTAB_FILE, "a+") as f:
                fstab_statement = "{}:{}    {}   nfs " \
                                  "auto,nofail,noatime,nolock,intr,tcp," \
                                  "actimeo=1800 0 0" \
                    .format(matched_nfs, nfs_location, mount_location)
                logger.info(
                    "Updating fstab file with {}".format(fstab_statement))
                f.write(fstab_statement)
                logger.info("Update Successful")
        except CommandExecutionFailedException as e:
            logger.error("Script Failed to run = {}\n{}".format(
                mount_script, str(e)))
            return False
        return True
예제 #4
0
 def execute(self):
     """
     installs kubernetes dashboard on the machine.
     """
     logger = XprLogger()
     if not linux_utils.check_root():
         logger.fatal("Please run this as root")
     logger.info("Setting up the Kubernetes dashboard...")
     try:
         deploy_dashboard = 'kubectl create -f https://raw.githubusercontent' \
                            '.com/kubernetes/dashboard/master/aio/deploy' \
                            '/recommended/kubernetes-dashboard.yaml'
         self.executor.execute(deploy_dashboard)  # creates deployment
         nodeport = """kubectl -n kube-system patch service \
                 kubernetes-dashboard --type='json' -p \
                 '[{"op":"replace","path":"/spec/type","value":"NodePort"}]'"""
         self.executor.execute(nodeport)  # exposes dashboard
         constant_port = """kubectl -n kube-system patch service \
                 kubernetes-dashboard --type='json' -p \
                 '[{"op":"replace","path":"/spec/ports/0/nodePort","value":30252}]'"""
         self.executor.execute(constant_port)  # sets constant port
         content_path = '/opt/xpresso.ai/config/kubernetes-dashboard-access.yaml'
         with open(content_path, "r") as f:
             content = f.read()
         path = '/etc/kubernetes/kube-dashboard-access.yaml'
         linux_utils.write_to_file(content, path, "w+")
         dashboard_access = 'kubectl create -f {}'.format(path)
         self.executor.execute(dashboard_access)  # grants permission
         skip_login = """kubectl patch deployment -n kube-system \
                 kubernetes-dashboard --type='json' -p='[{"op": "add", "path": \
                 "/spec/template/spec/containers/0/args/1", \
                 "value":"--enable-skip-login" }]'"""
         self.executor.execute(skip_login)  # enables skip login
     except CommandExecutionFailedException as e:
         logger.error("Failed to setup dashboard. \n{}".format(str(e)))
         return False
     return True
예제 #5
0
class XprDbSetup:
    """
        Class that provides tools to setup mongodb on a node
    """

    def __init__(self, executor=None):
        if not executor:
            self.executor = LocalShellExecutor()
        self.logger = XprLogger()
        self.service_path = '/lib/systemd/system/mongod.service'

    def install_mongo(self):
        """
        installs mongodb on the system
        """
        self.logger.info('entering install_mongo method')
        if not linux_utils.check_root():
            self.logger.fatal("Please run this as root")
        import_key = 'sudo apt-key adv --keyserver ' \
                     'hkp://keyserver.ubuntu.com:80 --recv ' \
                     '9DA31620334BD75D9DCB49F368818C72E52529D4'
        self.executor.execute(import_key)
        create_list = 'echo "deb [ arch=amd64 ] https://repo.mongodb.org/' \
                      'apt/ubuntu bionic/mongodb-org/4.0 multiverse" | ' \
                      'sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list'
        self.executor.execute(create_list)
        reload_packages = 'sudo apt-get update'
        self.executor.execute(reload_packages)
        self.logger.debug('installing mongo')
        install_mongo = 'sudo apt-get install -y mongodb-org'
        self.executor.execute(install_mongo)
        hold = """echo "mongodb-org hold" | sudo dpkg --set-selections
                  echo "mongodb-org-server hold" | sudo dpkg --set-selections
                  echo "mongodb-org-shell hold" | sudo dpkg --set-selections
                  echo "mongodb-org-mongos hold" | sudo dpkg --set-selections
                  echo "mongodb-org-tools hold" | sudo dpkg --set-selections"""
        self.executor.execute(hold)
        self.logger.info('exiting install_mongo')

    def initial_setup(self, db):
        """
        sets up the initial users and collections in the db
        :param db: database against which the setup is to be done
        :return: nothing
        """
        self.logger.info('entering initial_setup method')
        # initiate users collection
        users = db.users
        self.insert_default_users(users)
        db.users.create_index([('uid', ASCENDING)], unique=True)
        self.logger.debug('created index for users collection')

        # initiate nodes collection
        nodes = db.nodes
        self.logger.debug('setting up initial node')
        initial_node = {
            "name": "initial_node",
            "address": ""
        }
        nodes.insert_one(initial_node)
        nodes.create_index([('address', ASCENDING)], unique=True)
        self.logger.debug('created index for nodes collection')
        nodes.delete_one({"name": "initial_node"})

        # initiate clusters collection
        clusters = db.clusters
        self.logger.debug('setting up initial cluster')
        initial_cluster = {
            "name": "initial_cluster",
            "activationStatus": True,
            "master_nodes": [],
            "worker_nodes": []
        }
        clusters.insert_one(initial_cluster)
        clusters.create_index([('name', ASCENDING)], unique=True)
        self.logger.debug('created index for clusters collection')
        clusters.delete_one({"name": "initial_cluster"})

        # initiate projects collection
        projects = db.projects
        self.logger.debug('setting up initial project')
        initial_project = {
            "name": "initial_project",
            "projectDescription": "Initiates the collection",
            "owner": {},
            "developers": [],
            "components": []
        }
        projects.insert_one(initial_project)
        projects.create_index([('name', ASCENDING)], unique=True)
        self.logger.debug('created index for projects collection')
        projects.delete_one({"name": "initial_project"})

        # create xprdb_admin user in mongo
        self.logger.debug('creating xprdb user in mongo')
        db.command("createUser", "xprdb_admin", pwd="xprdb@Abz00ba",
                   roles=[{"role": "root", "db": "admin"}])
        self.logger.info('exiting initial_setup method')

    def insert_default_users(self, users):
        self.logger.debug('setting up default users')
        admin_user = {
            "uid": "xprdb_admin",
            "firstName": "Xpresso",
            "lastName": "Admin",
            "pwd": sha512_crypt.hash('xprdb@Abz00ba'),
            "email": "*****@*****.**",
            "primaryRole": "Admin",
            "activationStatus": True,
            "loginStatus": False
        }
        users.insert_one(admin_user)
        superuser = {
            "uid": "superuser1",
            "firstName": "superuser1",
            "lastName": "superuser1",
            "pwd": sha512_crypt.hash('superuser1'),
            "email": "*****@*****.**",
            "primaryRole": "Su",
            "activationStatus": True,
            "loginStatus": False
        }
        users.insert_one(superuser)
        admin1_user = {
            "uid": "admin1",
            "firstName": "admin1",
            "lastName": "admin1",
            "pwd": sha512_crypt.hash('admin1'),
            "email": "*****@*****.**",
            "primaryRole": "Admin",
            "activationStatus": True,
            "loginStatus": False
        }
        users.insert_one(admin1_user)

    def enable_replication(self):
        """
        installs replica set for the database
        :return: nothing
        """
        self.logger.info('entering enable_replication method')
        path = '/srv/mongodb/rs0-0'
        linux_utils.create_directory(path, 0o777)
        self.logger.debug('created directory for replica set')
        ip = linux_utils.get_ip_address()
        start = 'mongod --replSet rs0 --port 27017 --bind_ip localhost,' \
                '{} --dbpath /srv/mongodb/rs0-0 --fork ' \
                '--logpath /var/log/mongodb/mongod.log'.format(ip)
        self.executor.execute(start)
        self.logger.debug('mongo daemon started')
        client = MongoClient('localhost', replicaset='rs0')
        db = client.xprdb
        client.admin.command("replSetInitiate")
        self.logger.debug('Replica set initiated')
        time.sleep(5)
        self.initial_setup(db)
        # stop mongo to restart with auth
        stop_mongod = 'pgrep mongod | xargs kill'
        self.executor.execute(stop_mongod)
        self.logger.debug('stopping mongo daemon to restart with auth')
        time.sleep(10)
        restart = 'mongod --replSet rs0 --port 27017 --bind_ip localhost,{} ' \
                  '--dbpath /srv/mongodb/rs0-0 --auth --fork --logpath ' \
                  '/var/log/mongodb/mongod.log'.format(ip)
        config = configparser.ConfigParser()
        config.read(self.service_path)
        config['Service']['ExecStart'] = restart
        with open(self.service_path, 'w') as f:
            config.write(f)
        restart_mongod = 'systemctl restart mongod'
        self.executor.execute(restart_mongod)
        self.logger.debug('db setup complete, exiting enable_replication')
예제 #6
0
    def execute(self):
        """
        installs kubernetes master node on the machine.
        """

        logger = XprLogger()
        if not linux_utils.check_root():
            logger.fatal("Please run this as root")
        logger.info("Initialising Kubernetes master node...")
        try:
            pod_network_cidr = self.config[self.PACKAGES][self.KUBE_SECTION][
                self.CIDR_KEY]
            init = 'kubeadm init --token-ttl=0 --pod-network-cidr={}'.format(
                pod_network_cidr)
            (_, output, _) = self.executor.execute_with_output(init)
            output = output.splitlines()
            join_command = (output[-2].decode("utf-8").rstrip('\\') +
                            output[-1].decode("utf-8"))
            # waiting time for master node to become active
            time.sleep(90)
            master_ip = linux_utils.get_ip_address()
            cluster_path = '/mnt/nfs/data/k8/k8_clusters/' \
                           '{}'.format(master_ip)
            linux_utils.create_directory(cluster_path, 0o755)
            join_filename = '{}/{}.txt'.format(cluster_path, master_ip)
            linux_utils.write_to_file(join_command, join_filename, "w+")
            if not os.path.isfile(join_filename):
                logger.error('Failed to write join command to file. Exiting.')
                raise CommandExecutionFailedException
            kubeconfig = 'KUBECONFIG=/etc/kubernetes/admin.conf'
            environment_path = '/etc/environment'
            linux_utils.write_to_file(kubeconfig, environment_path, "a")
            os.environ["KUBECONFIG"] = "/etc/kubernetes/admin.conf"
            kube_directory = '$HOME/.kube'
            linux_utils.create_directory(kube_directory, 0o755)
            copy_config = 'sudo cp -f /etc/kubernetes/admin.conf' \
                          ' $HOME/.kube/config'
            self.executor.execute(copy_config)
            chown = 'sudo chown $(id -u):$(id -g) $HOME/.kube/config'
            self.executor.execute(chown)
            flannel = 'kubectl apply -f https://raw.githubusercontent.com' \
                      '/coreos/flannel/master/Documentation/kube-flannel.yml'
            self.executor.execute(flannel)
            generate_api_token = "kubectl get secret $(kubectl get " \
                                 "serviceaccount default -o jsonpath=" \
                                 "'{.secrets[0].name}') -o jsonpath=" \
                                 "'{.data.token}' | base64 --decode"
            status, stdout, stderr = self.executor.execute_with_output(
                generate_api_token)
            if status != 0 or len(stderr.decode('utf-8')):
                raise CommandExecutionFailedException(
                    "Token generation failed")
            token = stdout.decode("utf-8")
            self.persistence_manager.update("nodes", {"address": master_ip},
                                            {"token": token})
            api_access = 'kubectl create clusterrolebinding permissive-binding \
                                  --clusterrole=cluster-admin \
                                  --user=admin \
                                  --user=kubelet \
                                  --group=system:serviceaccounts'

            self.executor.execute(api_access)
            docker_secret = \
                'kubectl create secret docker-registry dockerkey ' \
                '--docker-server https://dockerregistry.xpresso.ai/ ' \
                '--docker-username xprdocker --docker-password Abz00ba@123'
            self.executor.execute(docker_secret)

        except CommandExecutionFailedException as e:
            logger.error("Failed to initialise master. \n{}".format(str(e)))
            return False
        return True
예제 #7
0
class PackageDependency:
    """
    Created a  directed acyclic package dependency graph
    using a given dependency json.
    """

    NONE_PACKAGE = "None"
    DEPENDENCY_SECTION = "pkg_dependency"
    DEPENDENCY_CONFIG_FILE = "dependency_config_file"

    def __init__(self, config_path=XprConfigParser.DEFAULT_CONFIG_PATH):
        super().__init__()
        self.config = XprConfigParser(config_path)["packages_setup"]
        self.logger = XprLogger()
        dependency_config_file = self.config[self.DEPENDENCY_SECTION][
            self.DEPENDENCY_CONFIG_FILE]

        if not os.path.exists(dependency_config_file):
            self.logger.error(("Unable to find the dependency js"
                               "file at the mentioned path"))
            raise PackageFailedException("Invalid dependency  config file")

        try:
            with open(dependency_config_file) as config_fs:
                dependency_config = json.load(config_fs)
        except EnvironmentError as err:
            self.logger.fatal(err)
            raise PackageFailedException("Invalid config file")

        self.graph = nx.DiGraph()
        edges = list()

        for key in dependency_config:
            for value in dependency_config[key]:
                edges.append((key, value))

        self.graph.add_edges_from(edges)
        if not nx.is_directed_acyclic_graph(self.graph):
            self.logger.fatal(("Unable to handle dependencies due to cyclic "
                               "loop"))
            self.graph = None
            raise PackageFailedException("Cyclic Dependency Found")

    def visualize_dependency_graph(self):
        """
        Created a plot for the directed dependency graph
        """
        if self.graph is None:
            self.logger.error("Graph value none cannot be plotted")
            return

        nx.draw(self.graph, cmap=plt.get_cmap('jet'), with_labels=True)
        plt.show()

    def check_if_supported(self, package_name: str):
        """
        Args:
            package_name(str)

        :return:
            bool: Return True if supported. False, otherwise
        """
        return bool(self.graph.has_node(package_name))

    def list_all(self):
        """
        Extracts the value of all nodes(packages) present in graph

        Returns:
            list: Array consisting of all node(packages) value
        """
        if self.graph is None:
            self.logger.error("Graph value none cannot be iterated")
            return list()

        nodes = list()
        for node in self.graph.nodes():
            if node == self.NONE_PACKAGE:
                continue
            nodes.append(node)
        return nodes

    def get_dependency(self, package_name: str) -> list:
        """
        List of dependencies

        Args:
            package_name(str): Name of the package

        Returns:
            list: List of dependencies required for the package_name
                  installation
        """

        if not self.check_if_supported(package_name=package_name):
            self.logger.error(
                "{} package not present in config".format(package_name))
            return list()

        self.logger.info(("Running Topological sorting on "
                          "Package Dependency Graph"))

        try:
            topological_sort_list = list(
                reversed(list(nx.topological_sort(self.graph))))
        except nx.NetworkXError as error:
            self.logger.error(error)
            raise PackageFailedException("Topological sort is defined for "
                                         "directed graphs only")
        except nx.NetworkXUnfeasible as error:
            self.logger.error(error)
            raise PackageFailedException(
                "Not a directed acyclic graph (DAG) "
                "and hence no topological sort exists")

        descendants = nx.descendants(self.graph, package_name)
        dependent_packages = []
        for pkg in topological_sort_list:
            if pkg in descendants and pkg != self.NONE_PACKAGE:
                dependent_packages.append(pkg)
        if package_name != self.NONE_PACKAGE:
            dependent_packages.append(package_name)

        return dependent_packages