senlin/contrib/kubernetes/kube/base.py

276 lines
11 KiB
Python

# 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 os
import random
import string
from oslo_log import log as logging
from senlin.common import context
from senlin.common import exception as exc
from senlin.objects import cluster as cluster_obj
from senlin.profiles.os.nova import server
LOG = logging.getLogger(__name__)
def GenKubeToken():
token_id = ''.join([random.choice(
string.digits + string.ascii_lowercase) for i in range(6)])
token_secret = ''.join([random.choice(
string.digits + string.ascii_lowercase) for i in range(16)])
token = '.'.join([token_id, token_secret])
return token
def loadScript(path):
script_file = os.path.join(os.path.dirname(__file__), path)
with open(script_file, "r") as f:
content = f.read()
return content
class KubeBaseProfile(server.ServerProfile):
"""Kubernetes Base Profile."""
def __init__(self, type_name, name, **kwargs):
super(KubeBaseProfile, self).__init__(type_name, name, **kwargs)
self.server_id = None
def _generate_kubeadm_token(self, obj):
token = GenKubeToken()
# store generated token
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
data = obj.data
data[self.KUBEADM_TOKEN] = token
cluster_obj.Cluster.update(ctx, obj.id, {'data': data})
return token
def _get_kubeadm_token(self, obj):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
return cluster.data.get(self.KUBEADM_TOKEN)
return None
def _update_master_ip(self, obj, ip):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
cluster.data['kube_master_ip'] = ip
cluster.update(ctx, obj.cluster_id, {'data': cluster.data})
def _create_network(self, obj):
client = self.network(obj)
try:
net = client.network_create()
subnet = client.subnet_create(network_id=net.id,
cidr='10.7.0.0/24',
ip_version=4)
except exc.InternalError as ex:
raise exc.EResourceCreation(type='kubernetes',
message=str(ex),
resource_id=obj.id)
pub_net = client.network_get(self.properties[self.PUBLIC_NETWORK])
try:
router = client.router_create(
external_gateway_info={"network_id": pub_net.id})
client.add_interface_to_router(router, subnet_id=subnet.id)
fip = client.floatingip_create(floating_network_id=pub_net.id)
except exc.InternalError as ex:
raise exc.EResourceCreation(type='kubernetes',
message=str(ex),
resource_id=obj.id)
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
data = obj.data
data[self.PRIVATE_NETWORK] = net.id
data[self.PRIVATE_SUBNET] = subnet.id
data[self.PRIVATE_ROUTER] = router.id
data[self.KUBE_MASTER_FLOATINGIP] = fip.floating_ip_address
data[self.KUBE_MASTER_FLOATINGIP_ID] = fip.id
cluster_obj.Cluster.update(ctx, obj.id, {'data': data})
return net.id
def _delete_network(self, obj):
client = self.network(obj)
fip_id = obj.data.get(self.KUBE_MASTER_FLOATINGIP_ID)
if fip_id:
try:
# delete floating ip
client.floatingip_delete(fip_id)
except exc.InternalError as ex:
raise exc.EResourceDeletion(type='kubernetes', id=fip_id,
message=str(ex))
router = obj.data.get(self.PRIVATE_ROUTER)
subnet = obj.data.get(self.PRIVATE_SUBNET)
if router and subnet:
try:
client.remove_interface_from_router(router, subnet_id=subnet)
except exc.InternalError as ex:
raise exc.EResourceDeletion(type='kubernetes',
id=subnet,
message=str(ex))
if router:
try:
# delete router
client.router_delete(router, ignore_missing=True)
except exc.InternalError as ex:
raise exc.EResourceDeletion(type='kubernetes',
id=router,
message=str(ex))
net = obj.data.get(self.PRIVATE_NETWORK)
if net:
try:
# delete network
client.network_delete(net, ignore_missing=True)
except exc.InternalError as ex:
raise exc.EResourceDeletion(type='kubernetes',
id=net,
message=str(ex))
def _associate_floatingip(self, obj, server):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
fip = cluster.data.get(self.KUBE_MASTER_FLOATINGIP)
if fip:
try:
self.compute(obj).server_floatingip_associate(server,
fip)
except exc.InternalError as ex:
raise exc.EResourceOperation(op='floatingip',
type='kubernetes',
id=fip,
message=str(ex))
def _disassociate_floatingip(self, obj, server):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
fip = cluster.data.get(self.KUBE_MASTER_FLOATINGIP)
if fip:
try:
self.compute(obj).server_floatingip_disassociate(server,
fip)
except exc.InternalError as ex:
raise exc.EResourceOperation(op='floatingip',
type='kubernetes',
id=fip,
message=str(ex))
def _get_cluster_data(self, obj):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
return cluster.data
return {}
def _get_network(self, obj):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
return cluster.data.get(self.PRIVATE_NETWORK)
return None
def _create_security_group(self, obj):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
sgid = obj.data.get(self.SECURITY_GROUP, None)
if sgid:
return sgid
client = self.network(obj)
try:
sg = client.security_group_create(name=self.name)
except Exception as ex:
raise exc.EResourceCreation(type='kubernetes',
message=str(ex))
data = obj.data
data[self.SECURITY_GROUP] = sg.id
cluster_obj.Cluster.update(ctx, obj.id, {'data': data})
self._set_security_group_rules(obj, sg.id)
return sg.id
def _get_security_group(self, obj):
ctx = context.get_service_context(user_id=obj.user,
project_id=obj.project)
if obj.cluster_id:
cluster = cluster_obj.Cluster.get(ctx, obj.cluster_id)
return cluster.data.get(self.SECURITY_GROUP)
return None
def _set_security_group_rules(self, obj, sgid):
client = self.network(obj)
open_ports = {
'tcp': [22, 80, 8000, 8080, 6443, 8001, 8443, 443,
179, 8082, 8086],
'udp': [8285, 8472],
'icmp': [None]
}
for p in open_ports.keys():
for port in open_ports[p]:
try:
client.security_group_rule_create(sgid, port, protocol=p)
except Exception as ex:
raise exc.EResourceCreation(type='kubernetes',
message=str(ex))
def _delete_security_group(self, obj):
sgid = obj.data.get(self.SECURITY_GROUP)
if sgid:
try:
self.network(obj).security_group_delete(sgid,
ignore_missing=True)
except exc.InternalError as ex:
raise exc.EResourceDeletion(type='kubernetes',
id=sgid,
message=str(ex))
def do_validate(self, obj):
"""Validate if the spec has provided valid info for server creation.
:param obj: The node object.
"""
# validate flavor
flavor = self.properties[self.FLAVOR]
self._validate_flavor(obj, flavor)
# validate image
image = self.properties[self.IMAGE]
if image is not None:
self._validate_image(obj, image)
# validate key_name
keypair = self.properties[self.KEY_NAME]
if keypair is not None:
self._validate_keypair(obj, keypair)
return True