Mentions légales du service

Skip to content
Snippets Groups Projects
Commit 5e58f2b0 authored by SIMONIN Matthieu's avatar SIMONIN Matthieu
Browse files

Grid5000Offline client

parent 0f4024b0
No related branches found
No related tags found
No related merge requests found
Pipeline #239661 failed
examples/ref.yaml
.vscode/
# ring cache
......
# 1.0.3
- Introduce offline client (allow to browse the ref api offline)
# 0.3.0
- Two object are equals if they share the same id (`get_id`)
......
......@@ -178,6 +178,40 @@ In [2]: # gk is your entry point
#+END_SRC
*** Browse the reference API offline
Note that only GET like requests are accepted on the ref API.
#+BEGIN_SRC python :exports code :tangle examples/offline.py
import logging
import json
from pathlib import Path
import os
from grid5000 import Grid5000, Grid5000Offline
logging.basicConfig(level=logging.DEBUG)
# First get a copy of the reference api
# This is a one time and out-of-band process,
# here we get it by issuing a regular HTTP request
conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
gk = Grid5000.from_yaml(conf_file)
data = gk.dump_ref_api()
Path("ref.yaml").write_text(json.dumps(data))
# you can dump the data to a file
# and reuse it offline using the dedicated client
# here we reuse directly the data we got (no more HTTP requests will be issued)
ref = Grid5000Offline(json.loads(Path("ref.yaml").read_text()))
print(ref.sites["rennes"].clusters["paravance"].nodes["paravance-1"])
#+END_SRC
** Monitoring API
*** Get Statuses of resources
......@@ -849,6 +883,7 @@ one.
#+END_SRC
* Appendix :noexport:
** How to export this file
......
......@@ -187,6 +187,40 @@ Before starting, the file ``$HOME/.python-grid5000.yaml`` will be loaded.
node_versions = cluster.nodes["paravance-1"]
print(node_versions)
5.2.3 Browse the reference API offline
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Note that only GET like requests are accepted on the ref API.
.. code:: python
import logging
import json
from pathlib import Path
import os
from grid5000 import Grid5000, Grid5000Offline
logging.basicConfig(level=logging.DEBUG)
# First get a copy of the reference api
# This is a one time and out-of-band process,
# here we get it by issuing a regular HTTP request
conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
gk = Grid5000.from_yaml(conf_file)
data = gk.dump_ref_api()
Path("ref.yaml").write_text(json.dumps(data))
# you can dump the data to a file
# and reuse it offline using the dedicated client
# here we reuse directly the data we got (no more HTTP requests will be issued)
ref = Grid5000Offline(json.loads(Path("ref.yaml").read_text()))
print(ref.sites["rennes"].clusters["paravance"].nodes["paravance-1"])
5.3 Monitoring API
~~~~~~~~~~~~~~~~~~
......
import logging
import json
from pathlib import Path
import os
from grid5000 import Grid5000, Grid5000Offline
logging.basicConfig(level=logging.DEBUG)
# First get a copy of the reference api
# This is a one time and out-of-band process,
# here we get it by issuing a regular HTTP request
conf_file = os.path.join(os.environ.get("HOME"), ".python-grid5000.yaml")
gk = Grid5000.from_yaml(conf_file)
data = gk.dump_ref_api()
Path("ref.yaml").write_text(json.dumps(data))
# you can dump the data to a file
# and reuse it offline using the dedicated client
# here we reuse directly the data we got (no more HTTP requests will be issued)
ref = Grid5000Offline(json.loads(Path("ref.yaml").read_text()))
print(ref.sites["rennes"].clusters["paravance"].nodes["paravance-1"])
import copy
import json
import logging
from pathlib import Path
from typing import Dict, Union
import requests
......@@ -64,7 +67,7 @@ class Grid5000(object):
sslcert=None,
sslkey=None,
ssluser="anonymous",
**kwargs
**kwargs,
):
self._uri = uri
self.timeout = timeout
......@@ -90,11 +93,7 @@ class Grid5000(object):
if self.username and not self.client_ssl:
self._http_auth = requests.auth.HTTPBasicAuth(self.username, self.password)
self.root = RootManager(self)
self.sites = SiteManager(self)
self.stitcher = StitcherManager(self)
self.network_equipments = RootNetworkEquipmentManager(self)
self.set_initial_managers()
if not self.verify_ssl:
logger.warning(
"Unverified HTTPS request is being made. Make sure "
......@@ -105,6 +104,12 @@ class Grid5000(object):
urllib3.disable_warnings()
def set_initial_managers(self):
self.root = RootManager(self)
self.sites = SiteManager(self)
self.stitcher = StitcherManager(self)
self.network_equipments = RootNetworkEquipmentManager(self)
@classmethod
def from_yaml(cls, yaml_file):
try:
......@@ -185,7 +190,7 @@ class Grid5000(object):
streamed=False,
content_type="application/json",
accept="application/json",
**kwargs
**kwargs,
):
"""Make an HTTP request to the Grid5000 API.
......@@ -389,3 +394,68 @@ class Grid5000(object):
Grid5000HttpError: When the return code is not 2xx
"""
return self.http_request("delete", path, content_type=None, **kwargs)
def dump_ref_api(self):
"""Get the whole ref api as a dict
This is https://api.grid5000.fr/3.0?deep=1
"""
return self.http_get("/", query_data=dict(deep=1))
class Grid5000Offline(Grid5000):
"""Browse the ref API (only GET / possibly offline)."""
def __init__(self, data: Dict):
self._data = data["items"]
self._uri = ""
self.set_initial_managers()
@classmethod
def from_yaml(cls, data_path: Union[Path, str]):
if isinstance(data_path, str):
data_path = Path(data_path)
data = dict()
with data_path.open("r") as f:
data = json.load(f)
return cls(data)
def http_get(self, path, *args, **kwargs):
return self._ride_down_the_data(path)
def http_list(self, path, *args, **kwargs):
"""
There's some differences in the returned format when reading the ref
API as a whole.
"""
c = self._ride_down_the_data(path)
if isinstance(c, dict):
return list(c.values())
return c
def http_delete(self, path, *args, **kwargs):
raise ValueError("You can't delete a resource with this client")
def http_post(self, path, *args, **kwargs):
raise ValueError("You can't modify a resource with this client")
def _ride_down_the_data(self, path):
"""Retrieve an internal dict targetted by path.
/sites/rennes/cluster/paravance -> data[sites][rennes][cluster][paravance]
"""
splitted = path[1:].split("/")
node = self._data
for split in splitted:
if split in node:
node = node[split]
continue
if isinstance(node, list):
# lookup internally
node = [c for c in node if c.get("uid") == split][0]
continue
# 404 without any HTTP calls :)
raise Grid5000HttpError(
f"Impossible to follow the path {path} in the data", response_code=404
)
return node
......@@ -136,7 +136,6 @@ class RESTObject(object):
managers = getattr(self, "_managers", None)
if managers is None:
return
for attr, cls_name in self._managers:
cls = getattr(self._module, cls_name)
manager = cls(self.manager.grid5000, parent=self)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment