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
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
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')
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
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