forked from CSCfi/pebbles
-
Notifications
You must be signed in to change notification settings - Fork 0
/
openstack_driver.py
144 lines (115 loc) · 5.49 KB
/
openstack_driver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import json
from pouta_blueprints.services.openstack_service import OpenStackService
from pouta_blueprints.drivers.provisioning import base_driver
from pouta_blueprints.client import PBClient
from pouta_blueprints.models import Instance
from pouta_blueprints.utils import parse_ports_string
SLEEP_BETWEEN_POLLS = 3
POLL_MAX_WAIT = 180
class OpenStackDriver(base_driver.ProvisioningDriverBase):
def get_oss(self):
return OpenStackService({'M2M_CREDENTIAL_STORE': self.config['M2M_CREDENTIAL_STORE']})
def get_configuration(self):
from pouta_blueprints.drivers.provisioning.openstack_driver_config import CONFIG
oss = self.get_oss()
images = [x.name for x in oss.list_images()]
flavors = [x.name for x in oss.list_flavors()]
config = CONFIG.copy()
config['schema']['properties']['image']['enum'] = images
config['schema']['properties']['flavor']['enum'] = flavors
return config
def do_update_connectivity(self, token, instance_id):
oss = self.get_oss()
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
instance = pbclient.get_instance_description(instance_id)
instance_data = instance['instance_data']
security_group_id = instance_data['security_group_id']
blueprint_config = pbclient.get_blueprint_description(instance['blueprint_id'])
config = blueprint_config['config']
# Delete all existing rules and add the rules using the input port string
oss.clear_security_group_rules(security_group_id)
ports_str = config['exposed_ports']
if not ports_str:
ports_str = '22' # If the input port string is empty then use 22 as the default port
ports_list = parse_ports_string(ports_str)
for ports in ports_list:
from_port = ports[0]
to_port = ports[1]
oss.create_security_group_rule(
security_group_id,
from_port=from_port,
to_port=to_port,
cidr="%s/32" % instance['client_ip'],
ip_protocol='tcp',
group_id=None
)
def do_provision(self, token, instance_id):
self.logger.debug("do_provision %s" % instance_id)
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
instance = pbclient.get_instance_description(instance_id)
instance_name = instance['name']
instance_user = instance['user_id']
# fetch config
blueprint_config = pbclient.get_blueprint_description(instance['blueprint_id'])
config = blueprint_config['config']
log_uploader = self.create_prov_log_uploader(token, instance_id, log_type='provisioning')
log_uploader.info("Provisioning OpenStack instance (%s)\n" % instance_id)
ports_str = config['exposed_ports']
if ports_str:
try:
parse_ports_string(ports_str)
except:
error = 'Incorrect exposed ports definition in blueprint'
error_body = {'state': Instance.STATE_FAILED, 'error_msg': error}
pbclient.do_instance_patch(instance_id, error_body)
self.logger.debug(error)
raise RuntimeError(error)
# fetch user public key
key_data = pbclient.get_user_key_data(instance_user).json()
if not key_data:
error = 'user\'s public key is missing'
error_body = {'state': Instance.STATE_FAILED, 'error_msg': error}
pbclient.do_instance_patch(instance_id, error_body)
self.logger.debug(error)
raise RuntimeError(error)
oss = self.get_oss()
result = oss.provision_instance(
instance_name,
config['image'],
config['flavor'],
public_key=key_data[0]['public_key'],
userdata=config.get('userdata'))
if 'error' in result:
log_uploader.warn('Provisioning failed %s' % result['error'])
return
ip = result['address_data']['public_ip']
instance_data = {
'server_id': result['server_id'],
'floating_ip': ip,
'allocated_from_pool': result['address_data']['allocated_from_pool'],
'security_group_id': result['security_group'],
'endpoints': [
{'name': 'SSH', 'access': 'ssh cloud-user@%s' % ip},
]
}
log_uploader.info("Publishing server data\n")
pbclient.do_instance_patch(
instance_id,
{'instance_data': json.dumps(instance_data), 'public_ip': ip})
log_uploader.info("Provisioning complete\n")
def do_deprovision(self, token, instance_id):
log_uploader = self.create_prov_log_uploader(token, instance_id, log_type='deprovisioning')
log_uploader.info("Deprovisioning instance %s\n" % instance_id)
pbclient = PBClient(token, self.config['INTERNAL_API_BASE_URL'], ssl_verify=False)
oss = self.get_oss()
instance = pbclient.get_instance_description(instance_id)
instance_data = instance['instance_data']
if 'server_id' not in instance_data:
log_uploader.info("Skipping, no server id in instance data")
return
server_id = instance_data['server_id']
log_uploader.info("Destroying server instance . . ")
oss.deprovision_instance(server_id)
log_uploader.info("Deprovisioning ready\n")
def do_housekeep(self, token):
pass