Newer
Older
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/usr/bin/env python3
"""
OpenStack project multicloud migrator
"""
import argparse
import re
import sys
import paramiko
import keystoneauth1.session
from keystoneauth1.identity import v3
from openstack import connection
from keystoneauth1 import session
def get_openrc(file_handle):
""" parse and return OpenRC file """
openrc_vars = {}
for line in file_handle:
match = re.match(r'^export (\w+)=(.+)$', line.strip())
if match:
openrc_vars[match.group(1)] = match.group(2).strip('"')
return openrc_vars
def get_ostack_session_connection(openrc_vars):
""" """
auth_args = {
'auth_url': openrc_vars.get('OS_AUTH_URL'),
'username': openrc_vars.get('OS_USERNAME'),
'password': openrc_vars.get('OS_PASSWORD'),
'project_name': openrc_vars.get('OS_PROJECT_NAME'),
'project_domain_name': openrc_vars.get('OS_PROJECT_DOMAIN_NAME'),
'user_domain_name': openrc_vars.get('OS_USER_DOMAIN_NAME'),
'project_domain_id': openrc_vars.get('OS_PROJECT_DOMAIN_ID'),
'user_domain_id': openrc_vars.get('OS_USER_DOMAIN_ID'),
}
auth = v3.Password(**auth_args)
ostack_sess = session.Session(auth=auth)
ostack_conn = connection.Connection(session=ostack_sess)
return ostack_sess, ostack_conn
def get_ostack_project(ostack_connection, project_name):
project = None
for i_project in ostack_connection.list_projects():
if i_project.name == project_name:
project = i_project
return project
def get_ostack_project_keypairs(ostack_connection, project_name):
return ostack_connection.compute.keypairs()
def get_ostack_project_security_groups(ostack_connection, project_name):
return ostack_connection.network.security_groups()
def get_ostack_project_servers(ostack_connection, project_name):
return ostack_connection.compute.servers()
def get_ostack_project_volumes(ostack_connection, project_name):
return ostack_connection.block_store.volumes()
def remote_cmd_exec(hostname, username, key_filename, command):
# Create SSH client
ssh_client = paramiko.SSHClient()
# Automatically add untrusted hosts
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# Connect to the remote host
pkey = paramiko.RSAKey.from_private_key_file(key_filename)
ssh_client.connect(hostname, username=username, pkey=pkey, look_for_keys=False)
# Execute the command
stdin, stdout, stderr = ssh_client.exec_command(command)
# Read the output
output = stdout.read().decode().strip()
# Close the SSH connection
ssh_client.close()
return output
except Exception as e:
print("Error:", e)
return None
def main(args):
""" """
# connect to source cloud
source_openrc = get_openrc(args.source_openrc)
source_sess, source_conn = get_ostack_session_connection(source_openrc)
# connect to destination cloud
destination_openrc = get_openrc(args.destination_openrc)
destination_sess, destination_conn = get_ostack_session_connection(destination_openrc)
# check project exists in source and destination
source_project = get_ostack_project(source_conn, args.project_name)
destination_project = get_ostack_project(destination_conn, args.project_name)
# connect to migrator node
reply = remote_cmd_exec(args.ceph_migrator_host, args.ceph_migrator_user,
args.ceph_migrator_sshkeyfile.name, 'uname -a')
# get source/destination keypairs
source_keypairs = get_ostack_project_keypairs(source_conn, args.project_name)
destination_keypairs = get_ostack_project_keypairs(destination_conn, args.project_name)
# get source/destination security groups
source_security_groups = get_ostack_project_security_groups(source_conn, args.project_name)
destination_security_groups = get_ostack_project_security_groups(destination_conn, args.project_name)
# get source/destination servers in the project
source_project_servers = get_ostack_project_servers(source_conn, args.project_name)
destination_project_servers = get_ostack_project_servers(destination_conn, args.project_name)
# get source/destination volumes in the project
source_project_volumes = get_ostack_project_volumes(source_conn, args.project_name)
destination_project_volumes = get_ostack_project_volumes(destination_conn, args.project_name)
#print(dir(source_conn))
print(locals())
# connect to source cloud
# connect to ceph migrator node
pass
# main() call (argument parsing)
# ---------------------------------------------------------------------------
if __name__ == "__main__":
AP = argparse.ArgumentParser(epilog=globals().get('__doc__'),
formatter_class=argparse.RawDescriptionHelpFormatter)
AP.add_argument('--source-openrc', default=None, type=argparse.FileType('r'),
required=True, help='Source cloud authentication (OpenRC file)')
AP.add_argument('--destination-openrc', default=None, type=argparse.FileType('r'),
required=True, help='Destination cloud authentication (OpenRC file)')
AP.add_argument('--ceph-migrator-host', default='controller-ostack.stage.cloud.muni.cz',
help='OpenStack migrator ceph node host')
AP.add_argument('--ceph-migrator-user', default='root',
help='OpenStack migrator ceph node username')
AP.add_argument('--ceph-migrator-sshkeyfile', default=None, type=argparse.FileType('r'),
help='OpenStack migrator SSH keyfile')
AP.add_argument('--project-name', default=None, required=True,
help='OpenStack project name (identical in both clouds)')
AP.add_argument('--keypair-id', default=None, required=True,
help='Any keypair ID within selected OpenStack project')
#AP.add_argument('--hide-skipped-actions', default=False, action='store_true',
# help="Hide skipped ansible actions")
sys.exit(main(AP.parse_args()))