本文整理汇总了Python中sm.log.LOG类的典型用法代码示例。如果您正苦于以下问题:Python LOG类的具体用法?Python LOG怎么用?Python LOG使用的例子?那么恭喜您, 这里精选的类代码示例或许可以为您提供帮助。
在下文中一共展示了LOG类的20个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于我们的系统推荐出更棒的Python代码示例。
示例1: run
def run(self):
# 1. dispose the active SO, essentially kills the STG/ITG
# 2. dispose the resources used to run the SO
# example request to the SO
# curl -v -X DELETE http://localhost:8051/orchestrator/default \
# -H 'X-Auth-Token: '$KID \
# -H 'X-Tenant-Name: '$TENANT
url = HTTP + self.host + '/orchestrator/default'
heads = {'X-Auth-Token': self.extras['token'],
'X-Tenant-Name': self.extras['tenant_name']}
occi_attrs = self.extras['srv_prms'].service_parameters(self.state)
if len(occi_attrs) > 0:
LOG.info('Adding service-specific parameters to call... X-OCCI-Attribute:' + occi_attrs)
heads['X-OCCI-Attribute'] = occi_attrs
LOG.info('Disposing service orchestrator with: ' + url)
LOG.info('Sending headers: ' + heads.__repr__())
http_retriable_request('DELETE', url, headers=heads)
url = self.nburl + self.entity.identifier.replace('/' + self.entity.kind.term + '/', '/app/')
heads = {'Content-Type': 'text/occi',
'X-Auth-Token': self.extras['token'],
'X-Tenant-Name': self.extras['tenant_name']}
LOG.info('Disposing service orchestrator container via CC... ' + url)
LOG.info('Sending headers: ' + heads.__repr__())
http_retriable_request('DELETE', url, headers=heads, authenticate=True)
return self.entity, self.extras
开发者ID:MobileCloudNetworking,项目名称:dssaas,代码行数:28,代码来源:so_manager.py
示例2: run
def run(self):
self.app.register_backend(self.srv_type, self.service_backend)
if self.reg_srv:
self.register_service()
# setup shutdown handler for de-registration of service
for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]:
signal.signal(sig, self.shutdown_handler)
up = urlparse(self.stg["service_endpoint"])
dep_port = CONFIG.get("general", "port")
if dep_port != "":
LOG.warn(
"DEPRECATED: parameter general: port in service manager config. "
"Service port number (" + str(up.port) + ") is taken from the service manifest"
)
if self.DEBUG:
from wsgiref.simple_server import make_server
httpd = make_server("", int(up.port), self.app)
httpd.serve_forever()
else:
container = wsgi.WSGIContainer(self.app)
http_server = httpserver.HTTPServer(container)
http_server.listen(int(up.port))
ioloop.IOLoop.instance().start()
LOG.info("Service Manager running on interfaces, running on port: " + int(up.port))
开发者ID:MobileCloudNetworking,项目名称:dssaas,代码行数:30,代码来源:service.py
示例3: deploy_complete
def deploy_complete(self, url):
# XXX fugly - code copied from Resolver
heads = {
'Content-type': 'text/occi',
'Accept': 'application/occi+json',
'X-Auth-Token': self.extras['token'],
'X-Tenant-Name': self.extras['tenant_name'],
}
LOG.info('checking service state at: ' + url)
LOG.info('sending headers: ' + heads.__repr__())
r = http_retriable_request('GET', url, headers=heads)
attrs = json.loads(r.content)
if len(attrs['attributes']) > 0:
attr_hash = attrs['attributes']
stack_state = ''
try:
stack_state = attr_hash['occi.mcn.stack.state']
except KeyError:
pass
LOG.info('Current service state: ' + str(stack_state))
if stack_state == 'CREATE_COMPLETE' or stack_state == 'UPDATE_COMPLETE':
LOG.info('Stack is ready')
return True
elif stack_state == 'CREATE_FAILED':
raise RuntimeError('Heat stack creation failed.')
else:
LOG.info('Stack is not ready. Current state state: ' + stack_state)
return False
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:32,代码来源:so_manager.py
示例4: __is_complete
def __is_complete(self, url):
# XXX copy/paste code - merge the two places!
heads = {
'Content-type': 'text/occi',
'Accept': 'application/occi+json',
'X-Auth-Token': self.extras['token'],
'X-Tenant-Name': self.extras['tenant_name'],
}
LOG.info('Checking app state at: ' + url)
LOG.info('Sending headers: ' + heads.__repr__())
r = http_retriable_request('GET', url, headers=heads, authenticate=True)
attrs = json.loads(r.content)
if len(attrs['attributes']) > 0:
attr_hash = attrs['attributes']
app_state = ''
try:
app_state = attr_hash['occi.app.state']
except KeyError:
pass
LOG.info('Current service state: ' + str(app_state))
if app_state == 'active':
LOG.info('App is ready')
return True
else:
LOG.info('App is not ready. Current state state: ' + app_state)
return False
开发者ID:MobileCloudNetworking,项目名称:dssaas,代码行数:30,代码来源:so_manager.py
示例5: __create_app
def __create_app(self):
# name must be A-Za-z0-9 and <=32 chars
app_name = self.entity.kind.term[0:4] + 'srvinst' + ''.join(random.choice('0123456789ABCDEF') for i in range(16))
heads = {
'Content-Type': 'text/occi',
'Category': 'app; scheme="http://schemas.ogf.org/occi/platform#", '
'python-2.7; scheme="http://schemas.openshift.com/template/app#", '
'small; scheme="http://schemas.openshift.com/template/app#"',
'X-OCCI-Attribute': 'occi.app.name=' + app_name
}
url = self.nburl + '/app/'
LOG.debug('Requesting container to execute SO Bundle: ' + url)
LOG.info('Sending headers: ' + heads.__repr__())
r = http_retriable_request('POST', url, headers=heads, authenticate=True)
loc = r.headers.get('Location', '')
if loc == '':
raise AttributeError("No OCCI Location attribute found in request")
app_uri_path = urlparse(loc).path
LOG.debug('SO container created: ' + app_uri_path)
LOG.debug('Updating OCCI entity.identifier from: ' + self.entity.identifier + ' to: '
+ app_uri_path.replace('/app/', self.entity.kind.location))
self.entity.identifier = app_uri_path.replace('/app/', self.entity.kind.location)
LOG.debug('Setting occi.core.id to: ' + app_uri_path.replace('/app/', ''))
self.entity.attributes['occi.core.id'] = app_uri_path.replace('/app/', '')
# get git uri. this is where our bundle is pushed to
return self.__git_uri(app_uri_path)
开发者ID:MobileCloudNetworking,项目名称:mobaas,代码行数:32,代码来源:so_manager.py
示例6: run
def run(self):
self.start_time = time.time()
infoDict = {
'sm_name': self.entity.kind.term,
'phase': 'init',
'phase_event': 'start',
'response_time': 0,
}
LOG.debug(json.dumps(infoDict))
self.entity.attributes['mcn.service.state'] = 'initialise'
# Do init work here
self.entity.extras = {}
self.entity.extras['loc'] = 'foobar'
self.entity.extras['tenant_name'] = self.extras['tenant_name']
elapsed_time = time.time() - self.start_time
infoDict = {
'sm_name': self.entity.kind.term,
'phase': 'init',
'phase_event': 'done',
'response_time': elapsed_time,
}
LOG.debug(json.dumps(infoDict))
return self.entity, self.extras
开发者ID:Pentadactylus,项目名称:sm_openstack,代码行数:26,代码来源:openbaton_manager.py
示例7: run
def run(self):
super(AsychExe, self).run()
LOG.debug('Starting AsychExe thread')
for task in self.tasks:
entity, extras = task.run()
if self.registry:
LOG.debug('Updating entity in registry')
self.registry.add_resource(key=entity.identifier, resource=entity, extras=extras)
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:9,代码来源:so_manager.py
示例8: deregister_service
def deregister_service(self):
if not self.reg_srv:
return
if self.srv_ep:
LOG.debug('De-registering the service with the keystone service...')
keystone = client.Client(token=self.token, tenant_name=self.tenant_name, auth_url=self.design_uri)
keystone.services.delete(self.srv_ep.id) # deletes endpoint too
if not self.DEBUG:
ioloop.IOLoop.instance().stop()
else:
sys.exit(0)
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:11,代码来源:service.py
示例9: run
def run(self):
# get the code of the bundle and push it to the git facilities
# offered by OpenShift
LOG.debug('Deploying SO Bundle to: ' + self.repo_uri)
self.__deploy_app()
LOG.debug('Activating the SO...')
self.__init_so()
self.entity.attributes['mcn.service.state'] = 'activate'
return self.entity, self.extras
开发者ID:MobileCloudNetworking,项目名称:mobaas,代码行数:12,代码来源:so_manager.py
示例10: run
def run(self):
# TODO: bad practise
global stateNumber
global stateDescription
global soStackId
global stackName
LOG.debug("running deploy")
self.start_time = time.time()
infoDict = {
'sm_name': self.entity.kind.term,
'phase': 'deploy',
'phase_event': 'start',
'response_time': 0,
}
LOG.debug(json.dumps(infoDict))
self.entity.attributes['mcn.service.state'] = 'deploy'
# status update
self.__status(1,"started deployment of VM on OpenStack for SO")
# Do deploy work here
self.__deploy_so_vm()
# status update
self.__status(2,"SO's VM deployment initiated; waiting to finish & start SO")
# after the deployment, we have to wait until the VM is setup and the
# SO is listening for connections
# TODO: this is going to result in a problem if the SO couldn't be deployed successfully! there should be a timeout with the iteration and a treatment of each outcome
iteration = 0
while not self.__so_complete():
iteration += 1
# wait some seconds with each iteration - 5 was chosen just
# randomly in order to not make the communication too frequent but
# still get the result quite fast. It also depends on the OpenStack
# installation where the SO is to be deployed. (If the deployment
# speed is low, there is no need to test it too frequently and vice
# versa)
time.sleep(5)
# the second count might not be very accurate, but it gives an estimate
LOG.debug("it took me "+str(time.time() - self.start_time)+" seconds to deploy the SO")
# status update
self.__status(3,"SO running; sending deploy command to it")
# send the deploy command to the freshly instantiated SO
self.__deploy_to_so()
elapsed_time = time.time() - self.start_time
infoDict = {
'sm_name': self.entity.kind.term,
'phase': 'deploy',
'phase_event': 'done',
'response_time': elapsed_time,
}
LOG.debug(json.dumps(infoDict))
return self.entity, self.extras
开发者ID:zioproto,项目名称:sm_openstack,代码行数:60,代码来源:openstack_so_manager.py
示例11: register_service
def register_service(self):
self.srv_ep = util.services.get_service_endpoint(identifier=self.srv_type.term, token=self.token,
endpoint=self.design_uri, tenant_name=self.tenant_name,
url_type='public')
if self.srv_ep is None or self.srv_ep == '':
LOG.debug('RRRegistering the service with the keystone service...')
keystone = client.Client(token=self.token, tenant_name=self.tenant_name, auth_url=self.design_uri)
# taken from the kind definition
self.srv_ep = keystone.services.create(self.srv_type.scheme+self.srv_type.term,
self.srv_type.scheme+self.srv_type.term,
self.srv_type.title)
internal_url = admin_url = public_url = self.service_endpoint
self.ep = keystone.endpoints.create(self.region, self.srv_ep.id, public_url, admin_url, internal_url)
LOG.info(self.service_endpoint)
LOG.info('Service is now registered with keystone: ' +
'Region: ' + self.ep.region +
' Public URL:' + self.ep.publicurl +
' Service ID: ' + self.srv_ep.id +
' Endpoint ID: ' + self.ep.id)
else:
LOG.info('Service is already registered with keystone. Service endpoint is: ' + self.srv_ep)
开发者ID:MobileCloudNetworking,项目名称:mobaas,代码行数:29,代码来源:service.py
示例12: run
def run(self):
self.app.register_backend(self.srv_type, self.service_backend)
if self.reg_srv:
self.register_service()
# setup shutdown handler for de-registration of service
for sig in [signal.SIGTERM, signal.SIGINT, signal.SIGHUP, signal.SIGQUIT]:
signal.signal(sig, self.shutdown_handler)
up = urlparse(self.stg['service_endpoint'])
dep_port = CONFIG.get('general', 'port')
if dep_port != '':
LOG.warn('DEPRECATED: parameter general: port in service manager config. '
'Service port number (' + str(up.port) + ') is taken from the service manifest')
if self.DEBUG:
LOG.debug('Using WSGI reference implementation')
httpd = make_server('', int(up.port), self.app)
httpd.serve_forever()
else:
LOG.debug('Using tornado implementation')
container = wsgi.WSGIContainer(self.app)
http_server = httpserver.HTTPServer(container)
http_server.listen(int(up.port))
ioloop.IOLoop.instance().start()
LOG.info('Service Manager running on interfaces, running on port: ' + str(up.port))
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:28,代码来源:service.py
示例13: __init_so
def __init_so(self):
url = HTTP + self.host + '/orchestrator/default'
heads = {
'Category': 'orchestrator; scheme="http://schemas.mobile-cloud-networking.eu/occi/service#"',
'Content-Type': 'text/occi',
'X-Auth-Token': self.extras['token'],
'X-Tenant-Name': self.extras['tenant_name'],
'X-OCCI-Attribute': 'occi.mcn.app.url="' + HTTP + self.host + '/orchestrator/default"'
}
occi_attrs = self.extras['srv_prms'].service_parameters(self.state)
if len(occi_attrs) > 0:
LOG.info('Adding service-specific parameters to call... X-OCCI-Attribute: ' + occi_attrs)
heads['X-OCCI-Attribute'] = occi_attrs
LOG.debug('Initialising SO with: ' + url)
LOG.info('Sending headers: ' + heads.__repr__())
http_retriable_request('PUT', url, headers=heads)
elapsed_time = time.time() - self.start_time
infoDict = {
'so_id': self.entity.attributes['occi.core.id'],
'sm_name': self.entity.kind.term,
'so_phase': 'activate',
'phase_event': 'done',
'response_time': elapsed_time,
'tenant': self.extras['tenant_name']
}
tmpJSON = json.dumps(infoDict)
LOG.debug(tmpJSON)
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:29,代码来源:so_manager.py
示例14: run
def run(self):
LOG.debug("running retrieve")
self.start_time = time.time()
infoDict = {
'sm_name': self.entity.kind.term,
'phase': 'retrieve',
'phase_event': 'start',
'response_time': 0,
}
LOG.debug(json.dumps(infoDict))
self.entity.attributes['mcn.service.state'] = 'retrieve'
argument = {
'design_uri': CONFIG.get('service_manager', 'design_uri', ''),
'username': self.entity.attributes['icclab.disco.deployer.username'],
'tenant_name': self.extras['tenant_name'],
'password': self.entity.attributes['icclab.disco.deployer.password'],
'stack_name': 'disco_' + str(uuid.uuid1()),
'region': self.entity.attributes['icclab.disco.deployer.region'],
'token': self.extras['token']
}
deployer = OpenstackDeployer(argument)
framework_directory = CONFIG.get('disco','framework_directory','')
disco_config = {"deployer": deployer, "framework_directory": framework_directory, "root_component": "heat", "root_component_state": "end"}
discoinst = OpenstackDisco(disco_config, self.entity.attributes)
if 'stackid' in self.entity.attributes and \
self.entity.attributes['stackid'] is not "":
stackinfo = discoinst.retrieve(self.entity.attributes['stackid'])
try:
for output in stackinfo:
if output['output_value'] == None:
output['output_value'] = ""
self.entity.attributes[output['output_key']] = output['output_value']
current_stack = deployer.hc.stacks.get( self.entity.attributes['stackid'])
self.entity.attributes['stack_status'] = copy.deepcopy( current_stack.stack_status)
except:
self.entity.attributes['external_ip'] = 'none'
else:
self.entity.attributes['disco_status'] = 'nothing here right now'
# this has to be done because Hurtle doesn't convert a multiline string into a valid JSON
if "ssh_private_key" in self.entity.attributes:
self.entity.attributes["ssh_private_key"] = self.entity.attributes["ssh_private_key"].replace("\n","\\n")
return self.entity, self.extras
开发者ID:icclab,项目名称:disco,代码行数:49,代码来源:hurtledisco.py
示例15: __init__
def __init__(self, app, srv_type=None):
# openstack objects tracking the keystone service and endpoint
self.srv_ep = None
self.ep = None
self.DEBUG = True
self.app = app
self.service_backend = ServiceBackend(app)
LOG.info("Using configuration file: " + CONFIG_PATH)
self.token, self.tenant_name = self.get_service_credentials()
self.design_uri = CONFIG.get("service_manager", "design_uri", "")
if self.design_uri == "":
LOG.fatal("No design_uri parameter supplied in sm.cfg")
raise Exception("No design_uri parameter supplied in sm.cfg")
self.stg = None
stg_path = CONFIG.get("service_manager", "manifest", "")
if stg_path == "":
raise RuntimeError("No STG specified in the configuration file.")
with open(stg_path) as stg_content:
self.stg = json.load(stg_content)
stg_content.close()
if not srv_type:
srv_type = self.create_service_type()
self.srv_type = srv_type
self.reg_srv = CONFIG.getboolean("service_manager_admin", "register_service")
if self.reg_srv:
self.region = CONFIG.get("service_manager_admin", "region", "")
if self.region == "":
LOG.info("No region parameter specified in sm.cfg, defaulting to an OpenStack default: RegionOne")
self.region = "RegionOne"
self.service_endpoint = CONFIG.get("service_manager_admin", "service_endpoint")
if self.service_endpoint != "":
LOG.warn(
"DEPRECATED: service_endpoint parameter supplied in sm.cfg! Endpoint is now specified in "
"service manifest as service_endpoint"
)
LOG.info(
"Using " + self.stg["service_endpoint"] + " as the service_endpoint value " "from service manifest"
)
up = urlparse(self.stg["service_endpoint"])
self.service_endpoint = up.scheme + "://" + up.hostname + ":" + str(up.port)
开发者ID:MobileCloudNetworking,项目名称:dssaas,代码行数:45,代码来源:service.py
示例16: __ensure_ssh_key
def __ensure_ssh_key(self):
url = self.nburl + '/public_key/'
heads = {'Accept': 'text/occi'}
resp = http_retriable_request('GET', url, headers=heads, authenticate=True)
locs = resp.headers.get('x-occi-location', '')
# Split on spaces, test if there is at least one key registered
if len(locs.split()) < 1:
LOG.debug('No SM SSH registered. Registering default SM SSH key.')
occi_key_name, occi_key_content = self.__extract_public_key()
create_key_headers = {'Content-Type': 'text/occi',
'Category': 'public_key; scheme="http://schemas.ogf.org/occi/security/credentials#"',
'X-OCCI-Attribute': 'occi.key.name="' + occi_key_name + '", occi.key.content="' +
occi_key_content + '"'
}
http_retriable_request('POST', url, headers=create_key_headers, authenticate=True)
else:
LOG.debug('Valid SM SSH is registered with OpenShift.')
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:18,代码来源:so_manager.py
示例17: __init__
def __init__(self, app, srv_type=None):
# openstack objects tracking the keystone service and endpoint
self.srv_ep = None
self.ep = None
self.DEBUG = True
self.app = app
self.service_backend = ServiceBackend(app)
LOG.info('Using configuration file: ' + CONFIG_PATH)
self.token, self.tenant_name = self.get_service_credentials()
self.design_uri = CONFIG.get('service_manager', 'design_uri', '')
if self.design_uri == '':
LOG.fatal('No design_uri parameter supplied in sm.cfg')
raise Exception('No design_uri parameter supplied in sm.cfg')
self.stg = None
stg_path = CONFIG.get('service_manager', 'manifest', '')
if stg_path == '':
raise RuntimeError('No STG specified in the configuration file.')
with open(stg_path) as stg_content:
self.stg = json.load(stg_content)
stg_content.close()
if not srv_type:
srv_type = self.create_service_type()
self.srv_type = srv_type
self.reg_srv = CONFIG.getboolean('service_manager_admin', 'register_service')
if self.reg_srv:
self.region = CONFIG.get('service_manager_admin', 'region', '')
if self.region == '':
LOG.info('No region parameter specified in sm.cfg, defaulting to an OpenStack default: RegionOne')
self.region = 'RegionOne'
self.service_endpoint = CONFIG.get('service_manager_admin', 'service_endpoint')
if self.service_endpoint != '':
LOG.warn('DEPRECATED: service_endpoint parameter supplied in sm.cfg! Endpoint is now specified in '
'service manifest as service_endpoint')
LOG.info('Using ' + self.stg['service_endpoint'] + ' as the service_endpoint value '
'from service manifest')
up = urlparse(self.stg['service_endpoint'])
self.service_endpoint = up.scheme + '://' + up.hostname + ':' + str(up.port)
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:42,代码来源:service.py
示例18: __call__
def __call__(self, environ, response):
token = environ.get('HTTP_X_AUTH_TOKEN', '')
# design_uri is needed for the case that no token was given
design_uri = CONFIG.get('service_manager', 'design_uri', '')
if design_uri == '':
LOG.fatal('No design_uri parameter supplied in sm.cfg')
raise Exception('No design_uri parameter supplied in sm.cfg')
tenantname = environ.get('HTTP_X_TENANT_NAME', '')
region = environ.get('HTTP_X_REGION_NAME','')
username = environ.get('HTTP_X_USER_NAME','')
password = environ.get('HTTP_X_PASSWORD','')
# for checking the authenticity
auth = KeyStoneAuthService(design_uri)
# get the token from username, tenant and region combination from HTTP
# headers
if token is '':
try:
# get all the required variables - as the tenant name has a
# special role, it's queried separately
kc = client.Client(auth_url=design_uri,
username=username,
password=password,
tenant_name=tenantname
)
environ['HTTP_X_AUTH_TOKEN'] = kc.auth_token
token = kc.auth_token
except:
raise Exception('Either no design uri, username, '
'password, or tenant name respectively '
'provided or the login didn\'t succeed')
else:
if not auth.verify(token=token, tenant_name=tenantname):
LOG.error('Token has probably expired')
raise HTTPError(401, 'Token is not valid. You likely need an updated token.')
# the arguments at the back will become the extras variable within the individual SM classes
return self._call_occi(environ, response, username=username, design_uri=design_uri, password=password, token=token, tenant_name=tenantname, registry=self.registry, region=region)
开发者ID:Pentadactylus,项目名称:sm_openstack,代码行数:41,代码来源:service.py
示例19: __extract_public_key
def __extract_public_key(self):
ssh_key_file = CONFIG.get('service_manager', 'ssh_key_location', '')
if ssh_key_file == '':
raise Exception('No ssh_key_location parameter supplied in sm.cfg')
LOG.debug('Using SSH key file: ' + ssh_key_file)
with open(ssh_key_file, 'r') as content_file:
content = content_file.read()
content = content.split()
if content[0] == 'ssh-dsa':
raise Exception("The supplied key is not a RSA ssh key. Location: " + ssh_key_file)
key_content = content[1]
key_name = 'servicemanager'
if len(content) == 3:
key_name = content[2]
return key_name, key_content
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:21,代码来源:so_manager.py
示例20: service_parameters
def service_parameters(self, state='', content_type='text/occi'):
# takes the internal parameters defined for the lifecycle phase...
# and combines them with the client supplied parameters
if content_type == 'text/occi':
params = []
# get the state specific internal parameters
try:
params = self.service_params[state]
except KeyError: # as err:
LOG.warn('The requested states parameters are not available: "' + state + '"')
# get the client supplied parameters if any
try:
for param in self.service_params['client_params']:
params.append(param)
except KeyError: # as err:
LOG.info('No client params')
header = ''
for param in params:
if param['type'] == 'string':
value = '"' + param['value'] + '"'
else:
value = str(param['value'])
header = header + param['name'] + '=' + value + ', '
return header[0:-2]
else:
LOG.error('Content type not supported: ' + content_type)
开发者ID:AleDanish,项目名称:sm-0.4,代码行数:30,代码来源:so_manager.py
注:本文中的sm.log.LOG类示例由纯净天空整理自Github/MSDocs等源码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。 |
请发表评论