blob: 04f71b90e83c667dc6d358539cd37b16a25ec4db [file] [log] [blame]
Scott Baker62c7eaf2018-05-22 15:59:26 -07001
2# Copyright 2017-present Open Networking Foundation
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import base64
17import random
18import string
19
20from synchronizers.new_base.modelaccessor import OpenStackServiceInstance, Node, NetworkSlice, Flavor
21from newopenstacksyncstep import NewOpenStackSyncStep
22
23from xosconfig import Config
24from multistructlog import create_logger
25
26log = create_logger(Config().get('logging'))
27
28class SyncOpenStackServiceInstance(NewOpenStackSyncStep):
29 provides=[OpenStackServiceInstance]
30 requested_interval=0
31 observes=OpenStackServiceInstance
32
33 def get_connected_networks(self, instance):
34 xos_networks = [ns.network for ns in NetworkSlice.objects.filter(slice_id=instance.slice.id)]
35 return xos_networks
36
37 def get_user_data(self, instance):
38 pubkeys=[]
39
40 if instance.slice.creator and instance.slice.creator.public_key:
Scott Baker004e1f12018-06-26 16:47:35 -070041 pubkeys.append(instance.slice.creator.public_key)
Scott Baker62c7eaf2018-05-22 15:59:26 -070042
43 if instance.slice.service and instance.slice.service.public_key:
Scott Baker004e1f12018-06-26 16:47:35 -070044 pubkeys.append(instance.slice.service.public_key)
Scott Baker62c7eaf2018-05-22 15:59:26 -070045
46 userdata = '#cloud-config\n\n'
47# userdata += 'opencloud:\n slicename: "%s"\n hostname: "%s"\n restapi_hostname: "%s"\n restapi_port: "%s"\n' % (
48# instance.slice.name, instance.node.name, RESTAPI_HOSTNAME, str(RESTAPI_PORT))
49 userdata += 'ssh_authorized_keys:\n'
50 for key in pubkeys:
51 userdata += ' - %s\n' % key
52
53 log.info("generated userdata", userdata=userdata)
54
55 return userdata
56
57 def sync_record(self, instance):
58 slice = instance.slice
59 if not slice.trust_domain:
60 raise Exception("Instance's slice has no trust domain")
61
62 service = instance.slice.trust_domain.owner.leaf_model
63 #conn = self.connect_openstack_slice(slice)
64 conn = self.connect_openstack_admin(service)
65
66 os_domain = conn.identity.find_domain(slice.trust_domain.name)
67 os_project = conn.identity.find_project(slice.name, domain_id=os_domain.id)
68
69 os_instances = list(conn.compute.servers(name=instance.name, project_id=os_project.id))
70 if os_instances:
71 os_instance=os_instances[0]
72 log.info("Instance already exists in openstack", instance=instance)
73 else:
74 image_name = instance.image.name
75 image_id = conn.compute.find_image(image_name).id
76
77 if instance.flavor:
78 flavor_name = instance.flavor.name
79 else:
80 # pick a sensible default
81 flavor_name = "m1.small"
82 flavor_id = conn.compute.find_flavor(flavor_name).id
83
84 xos_networks = self.get_connected_networks(instance)
85 networks = []
86 for xos_network in xos_networks:
87 networks.append({"uuid": conn.network.find_network(xos_network.name).id})
88
89 # TODO(smbaker): No ssh keys specified
90
Scott Baker14b74fd2018-06-11 17:35:58 -070091 if not instance.node:
Scott Baker818c7bd2018-06-13 16:28:01 -070092 availability_zone = "nova"
93 else:
94 availability_zone="nova:%s" % instance.node.name
Scott Baker62c7eaf2018-05-22 15:59:26 -070095
96 log.info("Creating Instance", instance=instance, image_id=image_id, flavor_id=flavor_id,
97 availability_zone=availability_zone,
98 networks=networks)
99
100 if not instance.admin_password:
101 instance.admin_password = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(8))
102 instance.save(update_fields=["admin_password"])
103
104 user_data = self.get_user_data(instance)
105
106 os_instance = conn.compute.create_server(name=instance.name,
107 image_id=image_id,
108 flavor_id=flavor_id,
109 project_domain_id=os_project.id,
110 availability_zone=availability_zone,
111 networks=networks,
112 config_drive=True,
113 user_data=base64.b64encode(user_data),
114 admin_password=instance.admin_password)
115
116 if os_instance.id != instance.backend_handle:
117 instance.backend_handle = os_instance.id
118 instance.save(update_fields=["backend_handle"])
119
120 def delete_record(self, instance):
121 slice = instance.slice
122 if not slice.trust_domain:
123 raise Exception("Instance's slice has no trust domain")
124
125 service = slice.trust_domain.owner.leaf_model
126 conn = self.connect_openstack_admin(service)
127
128 os_domain = conn.identity.find_domain(slice.trust_domain.name)
129 os_project = conn.identity.find_project(slice.name, domain_id=os_domain.id)
130
131 os_instances = list(conn.compute.servers(name=instance.name, project_id=os_project.id))
132 if (not os_instances):
133 log.info("Instance already does not exist in openstack", instance=instance)
134 else:
135 os_instance=os_instances[0]
136 log.info("Deleting Instance", instance=instance, os_id=os_instance.id)
137 conn.compute.delete_server(os_instance.id)