晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
| DIR:/usr/lib/python3.9/site-packages/glances/plugins/ |
| Current File : //usr/lib/python3.9/site-packages/glances/plugins/glances_cloud.py |
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# SPDX-FileCopyrightText: 2022 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#
"""Cloud plugin.
Supported Cloud API:
- OpenStack meta data (class ThreadOpenStack) - Vanilla OpenStack
- OpenStackEC2 meta data (class ThreadOpenStackEC2) - Amazon EC2 compatible
"""
import threading
from glances.compat import iteritems, to_ascii
from glances.plugins.glances_plugin import GlancesPlugin
from glances.logger import logger
# Import plugin specific dependency
try:
import requests
except ImportError as e:
import_error_tag = True
# Display debug message if import error
logger.warning("Missing Python Lib ({}), Cloud plugin is disabled".format(e))
else:
import_error_tag = False
class Plugin(GlancesPlugin):
"""Glances' cloud plugin.
The goal of this plugin is to retrieve additional information
concerning the datacenter where the host is connected.
See https://github.com/nicolargo/glances/issues/1029
stats is a dict
"""
def __init__(self, args=None, config=None):
"""Init the plugin."""
super(Plugin, self).__init__(args=args, config=config)
# We want to display the stat in the curse interface
self.display_curse = True
# Init the stats
self.reset()
# Init thread to grab OpenStack stats asynchronously
self.OPENSTACK = ThreadOpenStack()
self.OPENSTACKEC2 = ThreadOpenStackEC2()
# Run the thread
self.OPENSTACK.start()
self.OPENSTACKEC2.start()
def exit(self):
"""Overwrite the exit method to close threads."""
self.OPENSTACK.stop()
self.OPENSTACKEC2.stop()
# Call the father class
super(Plugin, self).exit()
@GlancesPlugin._check_decorator
@GlancesPlugin._log_result_decorator
def update(self):
"""Update the cloud stats.
Return the stats (dict)
"""
# Init new stats
stats = self.get_init_value()
# Requests lib is needed to get stats from the Cloud API
if import_error_tag:
return stats
# Update the stats
if self.input_method == 'local':
stats = self.OPENSTACK.stats
if not stats:
stats = self.OPENSTACKEC2.stats
# Example:
# Uncomment to test on physical computer (only for test purpose)
# stats = {'id': 'ami-id',
# 'name': 'My VM',
# 'type': 'Gold',
# 'region': 'France',
# 'platform': 'OpenStack'}
# Update the stats
self.stats = stats
return self.stats
def msg_curse(self, args=None, max_width=None):
"""Return the string to display in the curse interface."""
# Init the return message
ret = []
if not self.stats or self.stats == {} or self.is_disabled():
return ret
# Generate the output
msg = self.stats.get('platform', 'Unknown')
ret.append(self.curse_add_line(msg, "TITLE"))
msg = ' {} instance {} ({})'.format(
self.stats.get('type', 'Unknown'), self.stats.get('name', 'Unknown'), self.stats.get('region', 'Unknown')
)
ret.append(self.curse_add_line(msg))
# Return the message with decoration
# logger.info(ret)
return ret
class ThreadOpenStack(threading.Thread):
"""
Specific thread to grab OpenStack stats.
stats is a dict
"""
# The metadata service provides a way for instances to retrieve
# instance-specific data via a REST API. Instances access this
# service at 169.254.169.254 or at fe80::a9fe:a9fe.
# All types of metadata, be it user-, nova- or vendor-provided,
# can be accessed via this service.
# https://docs.openstack.org/nova/latest/user/metadata-service.html
OPENSTACK_PLATFORM = "OpenStack"
OPENSTACK_API_URL = 'http://169.254.169.254/openstack/latest/meta-data'
OPENSTACK_API_METADATA = {
'id': 'project_id',
'name': 'name',
'type': 'meta/role',
'region': 'availability_zone',
}
def __init__(self):
"""Init the class."""
logger.debug("cloud plugin - Create thread for OpenStack metadata")
super(ThreadOpenStack, self).__init__()
# Event needed to stop properly the thread
self._stopper = threading.Event()
# The class return the stats as a dict
self._stats = {}
def run(self):
"""Grab plugin's stats.
Infinite loop, should be stopped by calling the stop() method
"""
if import_error_tag:
self.stop()
return False
for k, v in iteritems(self.OPENSTACK_API_METADATA):
r_url = '{}/{}'.format(self.OPENSTACK_API_URL, v)
try:
# Local request, a timeout of 3 seconds is OK
r = requests.get(r_url, timeout=3)
except Exception as e:
logger.debug('cloud plugin - Cannot connect to the OpenStack metadata API {}: {}'.format(r_url, e))
break
else:
if r.ok:
self._stats[k] = to_ascii(r.content)
else:
# No break during the loop, so we can set the platform
self._stats['platform'] = self.OPENSTACK_PLATFORM
return True
@property
def stats(self):
"""Stats getter."""
return self._stats
@stats.setter
def stats(self, value):
"""Stats setter."""
self._stats = value
def stop(self, timeout=None):
"""Stop the thread."""
logger.debug("cloud plugin - Close thread for OpenStack metadata")
self._stopper.set()
def stopped(self):
"""Return True is the thread is stopped."""
return self._stopper.is_set()
class ThreadOpenStackEC2(ThreadOpenStack):
"""
Specific thread to grab OpenStack EC2 (Amazon cloud) stats.
stats is a dict
"""
# The metadata service provides a way for instances to retrieve
# instance-specific data via a REST API. Instances access this
# service at 169.254.169.254 or at fe80::a9fe:a9fe.
# All types of metadata, be it user-, nova- or vendor-provided,
# can be accessed via this service.
# https://docs.openstack.org/nova/latest/user/metadata-service.html
OPENSTACK_PLATFORM = "Amazon EC2"
OPENSTACK_API_URL = 'http://169.254.169.254/latest/meta-data'
OPENSTACK_API_METADATA = {
'id': 'ami-id',
'name': 'instance-id',
'type': 'instance-type',
'region': 'placement/availability-zone',
}
|