blob: 6ae91a120768639f30c7172df02c65fed41f966e [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:
41 pubkeys.add(instance.slice.creator.public_key)
42
43 if instance.slice.service and instance.slice.service.public_key:
44 pubkeys.add(instance.slice.service.public_key)
45
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
91 availability_zone="nova:%s" % instance.node.name
92
93 log.info("Creating Instance", instance=instance, image_id=image_id, flavor_id=flavor_id,
94 availability_zone=availability_zone,
95 networks=networks)
96
97 if not instance.admin_password:
98 instance.admin_password = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(8))
99 instance.save(update_fields=["admin_password"])
100
101 user_data = self.get_user_data(instance)
102
103 os_instance = conn.compute.create_server(name=instance.name,
104 image_id=image_id,
105 flavor_id=flavor_id,
106 project_domain_id=os_project.id,
107 availability_zone=availability_zone,
108 networks=networks,
109 config_drive=True,
110 user_data=base64.b64encode(user_data),
111 admin_password=instance.admin_password)
112
113 if os_instance.id != instance.backend_handle:
114 instance.backend_handle = os_instance.id
115 instance.save(update_fields=["backend_handle"])
116
117 def delete_record(self, instance):
118 slice = instance.slice
119 if not slice.trust_domain:
120 raise Exception("Instance's slice has no trust domain")
121
122 service = slice.trust_domain.owner.leaf_model
123 conn = self.connect_openstack_admin(service)
124
125 os_domain = conn.identity.find_domain(slice.trust_domain.name)
126 os_project = conn.identity.find_project(slice.name, domain_id=os_domain.id)
127
128 os_instances = list(conn.compute.servers(name=instance.name, project_id=os_project.id))
129 if (not os_instances):
130 log.info("Instance already does not exist in openstack", instance=instance)
131 else:
132 os_instance=os_instances[0]
133 log.info("Deleting Instance", instance=instance, os_id=os_instance.id)
134 conn.compute.delete_server(os_instance.id)