没有项目描述
python-grid5000的Python项目详细描述
python-grid5000是一个包装网格5000 rest api的python包。你可以 将它用作python项目中的库,或者可以探索grid的5000 使用嵌入式shell进行交互的资源。
警告
该代码目前正在大量开发中。跳转到贡献部分 如果你想参与的话。
1谢谢
核心代码是从python-gitlab中借用的,对 符合grid5000的api模型(使用's'!)
2贡献
- 为了贡献,你可以给我发一封电子邮件,或者为bug报告或特性请求打开一个问题。
- 有许多方面可以改进,这里列出了其中一些:
- api的完整覆盖还没有完成,但这应该相当容易实现。 大多数逻辑都在`grid5000.objects<;https://gitlab.inria.fr/msimonin/python-grid5000/blob/master/grid5000/objects.py>;`。老实说我只是 实现了我最需要的功能。
- 返回的status code尚未得到良好处理。
3与…
的比较- RESTfully: 它按照HATEOAS原则使用rest api。这允许客户 以充分发现可用的资源和操作。大部分G5K API 遵循这些原则,但是,例如Storage API没有。 restfully与grid的5000 api提供的所有特性都不兼容。 这是一个ruby库。python-grid5000借用了资源的友好语法 浏览,但使用python。
- Execo: 用python编写。api模块收集了许多利用 电网的5000 API。资源不是以语法友好的方式公开的, 相反,一些经典操作的函数是公开的(主要是getter)。 它有一种方便的方法来缓存引用api。python-grid5000是 包装在电网的5000年,寻求100%的覆盖面。python-grid5000是 资源导向。
- Raw requests: python中http库的引用。适合原型制作,但层次较低。 python-grid5000封装了这个库。
4安装和示例
- 请参阅https://api.grid5000.fr/doc/4.0/reference/spec.html了解 完整的规范。
- 所有示例都导出到examples子目录中,这样您就可以 易于测试和调整。
- 从位于主目录中的配置文件读取配置 目录(应该与restfully目录兼容)。 它可以通过以下方式创建:
echo ' username: MYLOGIN password: MYPASSWORD ' > ~/.python-grid5000.yaml
提示
在网格5000中,您可能需要设置verify_ssl: False
- 建议使用virtualenv(需要python 3.5+)
virtualenv -p python3 venv source venv/bin/activate pip install python-grid5000
4.1网格5000外壳
如果在命令行上调用grid5000,则应该在ipython shell中登录。 在开始之前,将加载文件$HOME/.python-grid5000.yaml。
$) grid5000 Python 3.6.5 (default, Jun 17 2018, 21:32:15) Type 'copyright', 'credits' or 'license' for more information IPython 7.3.0 -- An enhanced Interactive Python. Type '?' for help. In [1]: gk.sites.list() Out[1]: [<Site uid:grenoble>, <Site uid:lille>, <Site uid:luxembourg>, <Site uid:lyon>, <Site uid:nancy>, <Site uid:nantes>, <Site uid:rennes>, <Site uid:sophia>] In [2]: # gk is your entry point
4.2参考API
4.2.1获取节点信息
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)node_info=gk.sites["nancy"].clusters["grisou"].nodes["grisou-1"]print("grisou-1 has {threads} threads and has {ram} bytes of RAM".format(threads=node_info.architecture["nb_threads"],ram=node_info.main_memory["ram_size"]))
4.2.2获取资源版本
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)root_versions=gk.root.get().versions.list()print(root_versions)rennes=gk.sites["rennes"]site_versions=rennes.versions.list()print(site_versions)cluster=rennes.clusters["paravance"]cluster_versions=cluster.versions.list()print(cluster_versions)node_versions=cluster.nodes["paravance-1"]print(node_versions)
4.3监测api
4.3.1获取资源的状态
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)rennes=gk.sites["rennes"]site_statuses=rennes.status.list()print(site_statuses)cluster=rennes.clusters["paravance"]cluster_statuses=cluster.status.list()
4.4作业api
4.4.1作业筛选
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)# state=running will be placed in the query paramsrunning_jobs=gk.sites["rennes"].jobs.list(state="running")print(running_jobs)# get a specific job by its uidjob=gk.sites["rennes"].jobs.get("424242")print(job)# or using the bracket notationjob=gk.sites["rennes"].jobs["424242"]print(job)
4.4.2提交作业
importloggingimportosimporttimefromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)# This is equivalent to gk.sites.get("rennes")site=gk.sites["rennes"]job=site.jobs.create({"name":"pyg5k","command":"sleep 3600"})whilejob.state!="running":job.refresh()print("Waiting for the job [%s] to be running"%job.uid)time.sleep(10)print(job)print("Assigned nodes : %s"%job.assigned_nodes)
4.5部署api
4.5.1部署环境
importloggingimportosimporttimefromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)# This is equivalent to gk.sites.get("rennes")site=gk.sites["rennes"]job=site.jobs.create({"name":"pyg5k","command":"sleep 3600","types":["deploy"]})whilejob.state!="running":job.refresh()print("Waiting the job [%s] to be running"%job.uid)time.sleep(10)print("Assigned nodes : %s"%job.assigned_nodes)deployment=site.deployments.create({"nodes":job.assigned_nodes,"environment":"debian9-x64-min"})# To get SSH access to your nodes you can pass your public key## from pathlib import Path## key_path = Path.home().joinpath(".ssh", "id_rsa.pub")### deployment = site.deployments.create({"nodes": job.assigned_nodes,# "environment": "debian9-x64-min"# "key": key_path.read_text()})whiledeployment.status!="terminated":deployment.refresh()print("Waiting for the deployment [%s] to be finished"%deployment.uid)time.sleep(10)print(deployment.result)
4.6存储api
4.6.1获取存储访问
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)print(gk.sites["rennes"].storage["msimonin"].access.list())
4.6.2设置存储访问(例如用于虚拟机)
fromnetaddrimportIPNetworkimportloggingimportosimporttimefromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)site=gk.sites["rennes"]job=site.jobs.create({"name":"pyg5k","command":"sleep 3600","resources":"slash_22=1+nodes=1"})whilejob.state!="running":job.refresh()print("Waiting the job [%s] to be running"%job.uid)time.sleep(5)subnet=job.resources_by_type['subnets'][0]ip_network=[str(ip)foripinIPNetwork(subnet)]# create acces for all ips in the subnetaccess=site.storage["msimonin"].access.create({"ipv4":ip_network,"termination":{"job":job.uid,"site":site.uid}})
4.7 VLAN API
4.7.1获取VLAN
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)site=gk.sites["rennes"]# Get all vlansvlans=site.vlans.list()print(vlans)# Get on specificvlan=site.vlans.get("4")print(vlan)vlan=site.vlans["4"]print(vlan)# Get vlan of some nodesprint(site.vlansnodes.submit({"nodes":["paravance-1.rennes.grid5000.fr","paravance-2.rennes.grid5000.fr"]}))# Get nodes in vlanprint(site.vlans["4"].nodes.list())
4.7.2在VLAN中设置节点
将主接口放入VLAN
importloggingimportosimporttimefromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)site=gk.sites["rennes"]job=site.jobs.create({"name":"pyg5k","command":"sleep 3600","resources":"{type='kavlan'}/vlan=1+nodes=1","types":["deploy"]})whilejob.state!="running":job.refresh()print("Waiting the job [%s] to be runnning"%job.uid)time.sleep(5)deployment=site.deployments.create({"nodes":job.assigned_nodes,"environment":"debian9-x64-min","vlan":job.resources_by_type["vlans"][0]})whiledeployment.status!="terminated":deployment.refresh()print("Waiting for the deployment [%s] to be finished"%deployment.uid)time.sleep(10)print(deployment.result)
将次要接口放入VLAN
importloggingimportosimporttimefromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)def_to_network_address(host,interface):"""Translate a host to a network address e.g: paranoia-20.rennes.grid5000.fr -> paranoia-20-eth2.rennes.grid5000.fr """splitted=host.split('.')splitted[0]=splitted[0]+"-"+interfacereturn".".join(splitted)conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)site=gk.sites["rennes"]job=site.jobs.create({"name":"pyg5k","command":"sleep 3600","resources":"{type='kavlan'}/vlan=1+{cluster='paranoia'}nodes=1","types":["deploy"]})whilejob.state!="running":job.refresh()print("Waiting the job [%s] to be runnning"%job.uid)time.sleep(5)vlanid=job.resources_by_type["vlans"][0]# we hard code the interface but this can be discovered in the node info# TODO: write the code here to discovernodes=[_to_network_address(n,"eth2")forninjob.assigned_nodes]print(nodes)# set in vlansite.vlans[vlanid].submit({"nodes":nodes})
4.8更多片段
4.8.1集群的站点
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)clusters=["dahu","parasilo","chetemi"]conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)sites=gk.sites.list()matches=[]forsiteinsites:candidates=site.clusters.list()matching=[c.uidforcincandidatesifc.uidinclusters]iflen(matching)==1:matches.append((site,matching[0]))clusters.remove(matching[0])print("We found the following matches %s"%matches)
4.8.2在所有站点上获得具有给定名称的所有作业
importloggingimportosfromgrid5000importGrid5000logging.basicConfig(level=logging.DEBUG)NAME="pyg5k"conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")gk=Grid5000.from_yaml(conf_file)sites=gk.sites.list()site=gk.sites["rennes"]sites=[gk.sites["rennes"],gk.sites["nancy"],gk.sites["grenoble"]]# creates some jobsjobs=[]forsiteinsites:job=site.jobs.create({"name":"pyg5k","command":"sleep 3600"})jobs.append(job)_jobs=[]forsiteinsites:_jobs.append((site.uid,site.jobs.list(name=NAME,state="waiting,launching,running")))print("We found %s"%_jobs)# deleting the jobsforjobinjobs:job.delete()
4.8.3缓存API响应
网格的5000引用api是静态的。在这种情况下加快 请求,可以在缓存上发挥重要作用。目前 python-grid5000不执行开箱即用的缓存,而是将其推迟到 正在使用应用程序。实现缓存有很多解决方案。 其中包括lru缓存 (https://docs.python.org/3/library/functools.html#functools.lru_cache) 提供内存中的缓存功能,但不提供对 隐藏物。环库(https://ring-cache.readthedocs.io/en/stable/)是 很好,因为它为您的缓存实现了不同的后端(特别是。 跨进程缓存)并为您提供对缓存对象的控制。说够了:
importloggingimportthreadingimportosimportdiskcachefromgrid5000importGrid5000importring_api_lock=threading.Lock()# Keep track of the api client_api_client=Nonestorage=diskcache.Cache('cachedir')defget_api_client():"""Gets the reference to the API cient (singleton)."""with_api_lock:global_api_clientifnot_api_client:conf_file=os.path.join(os.environ.get("HOME"),".python-grid5000.yaml")_api_client=Grid5000.from_yaml(conf_file)return_api_client@ring.disk(storage)defget_sites_obj():"""Get all the sites."""gk=get_api_client()returngk.sites.list()@ring.disk(storage)defget_all_clusters_obj():"""Get all the clusters."""sites=get_sites_obj()clusters=[]forsiteinsites:# should we cache the list aswell ?clusters.extend(site.clusters.list())returnclustersif__name__=="__main__":logging.basicConfig(level=logging.DEBUG)clusters=get_all_clusters_obj()print(clusters)print("Known key in the cache")print(get_all_clusters_obj.get())print("Calling again the function is now faster")clusters=get_all_clusters_obj()print(clusters)