oaktree/oaktree/server.py

252 lines
8.0 KiB
Python

# Copyright (c) 2016 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import shade
from concurrent import futures
import logging
import time
from google.protobuf.descriptor import FieldDescriptor
import grpc
from oaktree import _clouds
from oaktreemodel import model
from oaktreemodel import oaktree_pb2
# Skipping bytes for now
_BOOL_TYPES = (FieldDescriptor.TYPE_BOOL,)
_ENUM_TYPES = (FieldDescriptor.TYPE_ENUM, )
_STR_TYPES = (FieldDescriptor.TYPE_STRING, )
_INT_TYPES = (
FieldDescriptor.TYPE_FIXED32, FieldDescriptor.TYPE_FIXED64,
FieldDescriptor.TYPE_SFIXED32, FieldDescriptor.TYPE_SFIXED64,
FieldDescriptor.TYPE_INT32, FieldDescriptor.TYPE_INT64,
FieldDescriptor.TYPE_SINT32, FieldDescriptor.TYPE_SINT64,
FieldDescriptor.TYPE_UINT32, FieldDescriptor.TYPE_UINT64,
)
_FLOAT_TYPES = (
FieldDescriptor.TYPE_DOUBLE, FieldDescriptor.TYPE_FLOAT,
)
_FIELDS_TO_STRIP = ('request_ids', 'HUMAN_ID', 'NAME_ATTR', 'human_id')
_ONE_DAY_IN_SECONDS = 60 * 60 * 24
def _get_cloud(request):
return _clouds._get_cloud(
cloud=request.location.cloud,
region=request.location.region,
project=request.location.project)
def convert_for_field(value, field):
if value is None:
return value
if field.type in _BOOL_TYPES:
return bool(value)
elif field.type in _STR_TYPES:
return str(value)
elif field.type in _INT_TYPES:
if value == '':
return 0
return int(value)
elif field.type in _FLOAT_TYPES:
return float(value)
elif field.type in _ENUM_TYPES:
return field.enum_type.values_by_name[value].number
def convert_munch_to_pb(munch, pb):
for key, value in munch.properties.items():
pb.properties[key] = str(value)
munch.pop('properties')
for key, field in pb.DESCRIPTOR.fields_by_name.items():
if field.label == field.LABEL_REPEATED:
for value in munch.pop(key, []):
converted = convert_for_field(value, field)
pb.key.append(converted)
else:
value = convert_for_field(munch.pop(key, None), field)
if value:
setattr(pb, key, value)
to_strip = set()
for key, value in munch.items():
if key in _FIELDS_TO_STRIP:
to_strip.add(key)
# TODO(mordred) this will not work for neutron, but it's fine til then
if ':' in key:
to_strip.add(key)
for key in to_strip:
munch.pop(key)
def convert_flavor(flavor):
flavor_pb = model.Flavor()
convert_munch_to_pb(flavor, flavor_pb)
for key, value in flavor.extra_specs.items():
flavor_pb.properties.setdefault(key, str(value))
return flavor_pb
def convert_flavors(flavors):
flavor_list = model.FlavorList()
for flavor in flavors:
# Why does this require a list extend? That seems silly enough that
# I feel like I'm doing something wrong
flavor_list.flavors.extend([convert_flavor(flavor)])
return flavor_list
def convert_image(image):
image_pb = model.Image()
tags = image.pop('tags', [])
for tag in tags:
image_pb.tags.append(str(tag))
convert_munch_to_pb(image, image_pb)
return image_pb
def convert_images(images):
image_list = model.ImageList()
for image in images:
# Why does this require a list extend? That seems silly enough that
# I feel like I'm doing something wrong
image_list.images.extend([convert_image(image)])
return image_list
def convert_security_groups(security_groups):
security_group_list = model.SecurityGroupList()
for security_group in security_groups:
security_group_list.extend([convert_security_group(security_group)])
return security_group_list
def convert_security_group(security_group):
secgroup_pb = model.SecurityGroup()
rules = security_group.pop('security_group_rules', [])
convert_munch_to_pb(security_group, secgroup_pb)
for rule in rules:
secgroup_pb.rules.append(convert_security_group_rule(rule))
def convert_security_group_rules(security_group_rules):
return _convert_dicts(
security_group_rules,
model.SecurityGroupRuleList,
convert_security_group_rule,
'rules')
def _convert_dicts(dicts, list_class, convert_function, attrname):
pb_list = list_class()
items = []
for item in dicts:
items.append(convert_function(item))
getattr(pb_list, attrname).extend(items)
return pb_list
def convert_security_group_rule(security_group_rule):
secgroup_rule_pb = model.SecurityGroupRule()
convert_munch_to_pb(security_group_rule, secgroup_rule_pb)
return secgroup_rule_pb
class OaktreeServicer(oaktree_pb2.OaktreeServicer):
def GetFlavor(self, request, context):
logging.info('getting flavor')
cloud = _get_cloud(request)
return convert_flavor(
cloud.get_flavor(
name_or_id=request.name_or_id,
filters=request.jmespath))
def SearchFlavors(self, request, context):
logging.info('searching flavors')
cloud = _get_cloud(request)
return convert_flavors(
cloud.search_flavors(
name_or_id=request.name_or_id,
filters=request.jmespath))
def GetImage(self, request, context):
logging.info('getting image')
cloud = _get_cloud(request)
return convert_image(
cloud.get_image(
name_or_id=request.name_or_id,
filters=request.jmespath))
def SearchImages(self, request, context):
logging.info('searching images')
cloud = _get_cloud(request)
return convert_images(
cloud.search_images(
name_or_id=request.name_or_id,
filters=request.jmespath))
def GetSecurityGroup(self, request, context):
logging.info('getting security group')
cloud = _get_cloud(request)
return convert_security_group(
cloud.get_security_group(
name_or_id=request.name_or_id,
filters=request.jmespath))
def SearchSecurityGroups(self, request, context):
logging.info('searching security groups')
cloud = _get_cloud(request)
return convert_security_groups(
cloud.search_security_groups(
name_or_id=request.name_or_id,
filters=request.jmespath))
def GetSecurityGroupRule(self, request, context):
logging.info('getting security group rule')
cloud = _get_cloud(request)
return convert_security_group_rule(
cloud.get_security_group_rule(
name_or_id=request.name_or_id,
filters=request.jmespath))
def SearchSecurityGroupRules(self, request, context):
logging.info('searching security group rules')
cloud = _get_cloud(request)
return convert_security_group_rules(
cloud.search_security_group_rules(
name_or_id=request.name_or_id,
filters=request.jmespath))
def serve():
shade.simple_logging(debug=True)
logging.getLogger().setLevel(logging.INFO)
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
oaktree_pb2.add_OaktreeServicer_to_server(OaktreeServicer(), server)
server.add_insecure_port('[::]:50051')
logging.info("Starting server")
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()