def test_inventory(self): HEADING() for output in ['dict', 'yaml', 'csv', 'table']: banner(output) print(self.i.list(format=output)) banner("changing values") self.i.add(host="i1", cluster="india", label="india") self.i.add(host="i2", cluster="india", label="gregor") self.i.add(host="d[1-4]", cluster="delta", label="delta") banner("saving") self.i.save() for output in ['dict', 'yaml', 'csv', 'table']: banner(output) print(self.i.list(format=output)) banner("reading") n = Inventory() n.read() t = n.list('table') print(t) assert "gregor" in str(t) assert "+" in str(t)
def do_inventory(self, args, arguments): """ :: Usage: inventory add cluster NAMES inventory add NAMES [--label=LABEL] [--services=SERVICES] [--project=PROJECT] [--owners=OWNERS] [--comment=COMMENT] [--inventory=INVENTORY] [--cluster=CLUSTER] [--ip=IP] [--service=SERVICE] [--tag=TAG] [--keyfile=KEYFILE] [--router=ROUTER] [--locale=LOCALE] [--timezone=TIMEZONE] inventory create TAG [--hostnames=NAMES] [--ip=IP] [--inventory=INVENTORY] [--keyfile=KEYFILE] inventory set NAMES ATTRIBUTE to VALUES [--inventory=INVENTORY] [--listvalue] inventory delete NAMES [--inventory=INVENTORY] inventory clone NAMES from SOURCE [--inventory=INVENTORY] inventory list [NAMES] [--format=FORMAT] [--columns=COLUMNS] [--inventory=INVENTORY] inventory info [--inventory=INVENTORY] inventory remove --inventory=INVENTORY Arguments: NAMES Name of the resources (example i[10-20]) FORMAT The format of the output is either txt, yaml, dict, table [default: table]. OWNERS a comma separated list of owners for this resource LABEL a unique label for this resource SERVICE a string that identifies the service PROJECT a string that identifies the project SOURCE a single host name to clone from COMMENT a comment Options: -v verbose mode --keyfile=KEYFILE Keyfile to assign [default: ~/.ssh/id_rsa.pub] Description: add -- adds a resource to the resource inventory list -- lists the resources in the given format delete -- deletes objects from the table clone -- copies the content of an existing object and creates new once with it set -- sets for the specified objects the attribute to the given value or values. If multiple values are used the values are assigned to the and objects in order. See examples map -- allows to set attributes on a set of objects with a set of values Examples: cms inventory add x[0-3] --service=openstack adds hosts x0, x1, x2, x3 and puts the string openstack into the service column cms inventory list lists the repository cms inventory set x[3-4] temperature to 32 sets for the resources x3, x4 the value of the temperature to 32 cms inventory set x[7-8] ip to 128.0.0.[0-1] sets the value of x7 to 128.0.0.0 sets the value of x8 to 128.0.0.1 cms inventory set x1 services to bridge,kubernetes --listvalue sets the value of x1 to [bridge, kubernetes] The --listvalue option indicates the value set is a list cms inventory clone x[5-6] from x3 clones the values for x5, x6 from x3 """ map_parameters(arguments, "columns", 'ip', 'hostnames', 'inventory', 'keyfile', 'listvalue') if arguments.info: if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() i.info() elif arguments.remove and arguments.inventory: os.system("rm -f " + path_expand(f'~/.cloudmesh/{arguments.inventory}')) elif arguments.NAMES is not None and arguments.list: hosts = Parameter.expand(arguments.NAMES) if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() d = dict(i.data) r = {} for key in d: if key in hosts: r[key] = d[key] pprint(r) i.data = r if arguments["--columns"]: order = arguments["--columns"].split(",") else: order = i.order print(i.list(format="table", order=order)) # elif arguments["set"]: # hosts = hostlist.expand_hostlist(arguments.NAMES) # i = inventory() # i.read() # element = {} # for attribute in i.order: # try: # attribute = arguments["ATTRIBUTE"] # value = arguments["VALUE"] # if value is not None: # element[attribute] = value # except: # pass # element['host'] = arguments.NAMES # i.add(**element) # print (i.list(format="table")) elif arguments.create: tag = arguments.TAG hostnames = Parameter.expand(arguments.hostnames) manager, workers = Host.get_hostnames(hostnames) ips = Parameter.expand(arguments.ip) if len(ips) != len(hostnames): Console.error( "The number of hosts does not match the number of ips") return keyfile = arguments.keyfile or '~/.ssh/id_rsa.pub' if arguments.inventory is None: arguments.inventory = "inventory.yaml" if manager is None: manager_ip = None worker_ips = ips else: manager_ip = ips[0] worker_ips = ips[1:] worker_hostnames = workers if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() inventory_name = arguments.inventory.split('.')[0] i.add(host=manager, name=manager, tag=tag, cluster=inventory_name, service='manager', ip=manager_ip, keyfile=keyfile, status="inactive") for worker, ip in zip(worker_hostnames, worker_ips): i.add(host=worker, name=worker, tag=tag, cluster=inventory_name, service='worker', ip=ip, keyfile=keyfile, status="inactive") # noqa: E124 i.save() Console.ok( f"Successfuly saved to ~/.cloudmesh/{arguments.inventory}") elif arguments.list: if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() if arguments["--columns"]: order = arguments["--columns"].split(",") else: order = i.order print(i.list(format="table", order=order)) elif arguments.set: hosts = Parameter.expand(arguments.NAMES) values = Parameter.expand(arguments.VALUES) if len(values) == 1: values = values * len(hosts) attribute = arguments.ATTRIBUTE if not arguments.listvalue and len(hosts) != len(values): Console.error( "Number of names {:} != number of values{:}".format( len(hosts), len(values))) if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() for index in range(0, len(hosts)): host = hosts[index] value = values if arguments.listvalue else values[index] if not i.has_host(host): i.add(host=host) i.set(host, attribute, value) # object = {'host': host, # attribute: value} # i.add(**object) i.save() print(i.list(format="table")) elif arguments.add and arguments.cluster: names = Parameter.expand(arguments.NAMES) manager, workers = Host.get_hostnames(names) if manager is None: Console.error( "A manager node is required. Numbers are not allowed in a manger name, " "i.e. red is an acceptable manager name, red00 is not.") return if workers: worker_base_name = ''.join( [i for i in workers[0] if not i.isdigit()]) cluster_name = manager or worker_base_name inventory = path_expand( f'~/.cloudmesh/inventory-{cluster_name}.yaml') Inventory.build_default_inventory(filename=inventory, manager=manager, workers=workers) elif arguments.add: hosts = Parameter.expand(arguments.NAMES) if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() element = {} for attribute in i.order: try: value = arguments["--" + attribute] if value is not None: element[attribute] = value except Exception as e: # noqa: F841 pass element['host'] = arguments.NAMES element['status'] = 'inactive' i.add(**element) i.save() print(i.list(format="table")) elif arguments.delete: hosts = Parameter.expand(arguments.NAMES) if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() for host in hosts: i.delete(host) i.save() elif arguments.clone: hosts = Parameter.expand(arguments.NAMES) source = arguments.SOURCE if arguments.inventory is None: i = Inventory() else: i = Inventory(f'~/.cloudmesh/{arguments.inventory}') i.read() if source in i.data: for host in hosts: i.data[host] = dict(i.data[source]) i.save() else: Console.error("The source {:} does not exist".format(source)) return ""
def do_inventory(self, args, arguments): """ :: Usage: inventory add NAMES [--label=LABEL] [--service=SERVICES] [--project=PROJECT] [--owners=OWNERS] [--comment=COMMENT] [--cluster=CLUSTER] [--ip=IP] inventory set NAMES ATTRIBUTE to VALUES inventory delete NAMES inventory clone NAMES from SOURCE inventory list [NAMES] [--format=FORMAT] [--columns=COLUMNS] inventory info Arguments: NAMES Name of the resources (example i[10-20]) FORMAT The format of the output is either txt, yaml, dict, table [default: table]. OWNERS a comma separated list of owners for this resource LABEL a unique label for this resource SERVICE a string that identifies the service PROJECT a string that identifies the project SOURCE a single host name to clone from COMMENT a comment Options: -v verbose mode Description: add -- adds a resource to the resource inventory list -- lists the resources in the given format delete -- deletes objects from the table clone -- copies the content of an existing object and creates new once with it set -- sets for the specified objects the attribute to the given value or values. If multiple values are used the values are assigned to the and objects in order. See examples map -- allows to set attributes on a set of objects with a set of values Examples: cms inventory add x[0-3] --service=openstack adds hosts x0, x1, x2, x3 and puts the string openstack into the service column cms inventory lists lists the repository cms inventory x[3-4] set temperature to 32 sets for the resources x3, x4 the value of the temperature to 32 cms inventory x[7-8] set ip 128.0.0.[0-1] sets the value of x7 to 128.0.0.0 sets the value of x8 to 128.0.0.1 cms inventory clone x[5-6] from x3 clones the values for x5, x6 from x3 """ map_parameters(arguments, "columns") # # TODO: fix config reader, use cmd4 # filename = Config(config_path="/cloudmesh_inventory.yaml") sorted_keys = True if arguments.info: i = Inventory() i.read() i.info() elif arguments.NAMES is not None and arguments.list: hosts = Parameter.expand(arguments.NAMES) print(hosts) i = Inventory() i.read() d = dict(i.data) r = {} for key in d: if key in hosts: r[key] = d[key] pprint(r) i.data = r if arguments["--columns"]: order = arguments["--columns"].split(",") else: order = i.order print(i.list(format="table", order=order)) # elif arguments["set"]: # hosts = hostlist.expand_hostlist(arguments.NAMES) # i = inventory() # i.read() # element = {} # for attribute in i.order: # try: # attribute = arguments["ATTRIBUTE"] # value = arguments["VALUE"] # if value is not None: # element[attribute] = value # except: # pass # element['host'] = arguments.NAMES # i.add(**element) # print (i.list(format="table")) elif arguments.list: i = Inventory() i.read() if arguments["--columns"]: order = arguments["--columns"].split(",") else: order = i.order print(i.list(format="table", order=order)) elif arguments.set: hosts = Parameter.expand(arguments.NAMES) values = Parameter.expand(arguments.VALUES) if len(values) == 1: values = values * len(hosts) print(hosts) print(values) attribute = arguments.ATTRIBUTE if len(hosts) != len(values): Console.error( "Number of names {:} != number of values{:}".format( len(hosts), len(values))) i = Inventory() i.read() for index in range(0, len(hosts)): host = hosts[index] value = values[index] object = {'host': host, attribute: value} i.add(**object) print(i.list(format="table")) elif arguments.add: hosts = Parameter.expand(arguments.NAMES) i = Inventory() i.read() element = {} for attribute in i.order: try: value = arguments["--" + attribute] if value is not None: element[attribute] = value except: pass element['host'] = arguments.NAMES i.add(**element) print(i.list(format="table")) elif arguments.delete: hosts = Parameter.expand(arguments.NAMES) i = Inventory() i.read() for host in hosts: del i.data[host] i.save() elif arguments.clone: hosts = Parameter.expand(arguments.NAMES) source = arguments.SOURCE i = Inventory() i.read() if source in i.data: for host in hosts: i.data[host] = dict(i.data[source]) i.save() else: Console.error("The source {:} does not exist".format(source)) return ""
def do_pi(self, args, arguments): """ :: Usage: pi ssh HOSTS pi setup1 HOSTS pi setup2 HOSTS pi setupmaster HOSTS pi cmd HOSTS pi label MASTER HOSTS Arguments: HOSTS hostlist Description: This command configures Pis for Kubernetes clusters. pi ssh HOSTS: Launch an interactive SSH session on each host. When you logout from one host, it will automatically SSH to the next host in the list. pi setup1 HOSTS: Run part 1 of Kubernetes setup on the hosts. pi setup2 HOSTS: Run part 2 of Kubernetes setup on the hosts. pi setupmaster HOSTS: Configure the HOSTS as Kubernetes masters. HOSTS will probably just be one hostname here. pi cmd HOSTS: Run CMD on every host via SSH. CMD is specified on stdin. For example: $ echo "uname -a" | cms pi cmd pi[1-5] pi label MASTER HOSTS: SSH to master node and label all worker nodes (HOSTS) as workers. """ hosts = Parameter.expand(arguments.HOSTS) inv = Inventory() inv.read() inv = inv.list() ips = self.get_host_ips(hosts, inv) if ips == None: # error return "" if arguments.ssh: self.run_many_commands(ips, ['']) elif arguments.setup1: self.setup_1(ips) elif arguments.setup2: self.setup_2(ips) elif arguments.setupmaster: self.setup_master(ips) elif arguments.cmd: # [:-1] to ignore the \n at the end of stdin self.run_many_commands(ips, [sys.stdin.read()[:-1]]) elif arguments.label: master_ip = self.get_host_ips([arguments.MASTER], inv)[0] self.label_nodes(master_ip, hosts)