File: endpoint_resouces_samples.py

package info (click to toggle)
python-coriolisclient 1.0.9-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 596 kB
  • sloc: python: 5,614; makefile: 23; sh: 2
file content (220 lines) | stat: -rw-r--r-- 8,031 bytes parent folder | download
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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
"""
Module showcasing various operations on resources exposed
through Coriolis' endpoints API.
"""

import json
import jsonschema

from keystoneauth1.identity import v3
from keystoneauth1 import session as ksession

from coriolisclient import client as coriolis_client


CORIOLIS_CONNECTION_INFO = {
    "auth_url": "http://127.0.0.1:5000/v3",
    "username": "admin",
    "password": "foCVs9hnoSB32dMVNtMLHLaOLDquJUoz1N3p53dd",
    "project_name": "admin",
    "user_domain_name": "default",
    "project_domain_name": "default"
}


# IDs of pre-existing Coriolis endpoints for both platforms.
# Samples relating to endpoint management can be found in 'endpoint_samples.py'
AZURE_ENDPOINT_ID = "67ae217c-d125-498d-82bc-690916900258"
OCI_ENDPOINT_ID = "885fe551-4502-4f55-b24c-1aae96b9ae24"

# Set of options related to the source Azure environment:
AZURE_SOURCE_OPTIONS = {
    "location": "westus",
    "resource_group": "testing-resgroup"
}

# Set of options related to the destination OCI environment:
OCI_DESTINATION_OPTIONS = {
    "availability_domain": "mQqX:EU-FRANKFURT-1-AD-3",
    "compartment": "<OCID of compartment>",
    "vcn_compartment": "<OCID of compartment housing VCNs>",
}

# Mapping between identifiers of networks on the source Azure to VCNs
# in the destination OCI to be used for the NICs of the Migrated VM(s):
NETWORK_MAP = {
    "azure-test-network/azure-test-subnet": "<OCI network OCID>"
}

# Mappings between identifiers of storage elements on the source Azure
# and  available storage typs on the destination OCI to be used for the
# disks of the Migrated VM(s):
STORAGE_MAPPINGS = {
    "default": "standard",
    "backend_mappings": {
        "Premium_LRS": "standard"
    },
    "disk_mappings": {
        "<ID of disk>": "<mapping for specific disk>"
    }
}


def get_schema_for_plugin(coriolis, platform_type, schema_type):
    """
    Returns a JSON schema detailing params expected by a given plugin.

    :param platform_type: type of platform (e.g. 'openstack', 'oci', 'azure')
    :param schema_type: schema type(e.g. 'connection', 'source', 'destination')
    :return: dict() containiGng the requrested JSON schema
    """
    provider_schema_type_map = {
        "destination": 1,
        "source": 2,
        "connection": 16
    }

    return coriolis.providers.schemas_list(
        platform_type, provider_schema_type_map[schema_type]).to_dict()


def check_mapped_networks_exist(coriolis, destination_endpoint, network_map,
                                destination_environment=None):
    """
    Checks whether all of the mapped networks exist on the destination.

    :param destination_endpoint: destination endpoint object or ID
    :param network_map: network mapping dict
    :param destination_environment: optional environment options for target
    :raises: Exception if a network is not found.
    """
    networks = coriolis.endpoint_networks.list(
        destination_endpoint, environment=destination_environment)

    for mapped_net in network_map.values():
        matches = [
            net for net in networks
            if net.id == mapped_net or net.name == mapped_net]

        if not matches:
            raise Exception(
                "Could not find network '%s' on the destination. Available "
                "networks are: %s" % (mapped_net, networks))


def check_mapped_storage_exists(coriolis, destination_endpoint,
                                storage_mappings,
                                destination_environment=None):
    """
    Checks whether all of the mapped storage types exist on the destination.

    :param destination_endpoint: destination endpoint object or ID
    :param storage_mappings: storage mappings dict
    :param destination_environment: optional environment options for target
    :raises: Exception if storage is not found.
    """
    storage = coriolis.endpoint_storage.list(
        destination_endpoint, environment=destination_environment)

    def _check_stor(storage_name_or_id):
        matches = [
            stor for stor in storage
            if (stor.id == storage_name_or_id or
                stor.name == storage_name_or_id)]
        if not matches:
            raise Exception(
                "Could not find storage type '%s' in: %s" % (
                    storage_name_or_id, storage))
        return matches[0]

    # check default:
    default = storage_mappings.get('default')
    if default is not None:
        _check_stor(default)

    # check backend mappings:
    backend_mappings = storage_mappings.get('backend_mappings', {})
    for mapped_storage in backend_mappings.values():
        _check_stor(mapped_storage)

    # check per-disk mappings:
    for mapped_storage in storage_mappings.get('disk_mappings', {}).values():
        _check_stor(mapped_storage)


def get_linux_vms_for_endpoint(coriolis, source_endpoint, source_options=None):
    """ Returns a list of the names/IDs of Linux VMs on a source endpoint """
    vms = coriolis.endpoint_instances.list(
        source_endpoint, env=source_options)

    return [vm for vm in vms if vm.os_type == 'linux']


def check_vm_network_mapping(coriolis, source_endpoint, vm_name_or_id,
                             network_map, source_options=None):
    """
    Fetches detailed info on the given source VM and checks that all of its
    NICs have an appropriate mapping in the given network_map

    :param source_endpoint: source endpoint name or ID
    :param vm_id: identifier (name or ID) of the the VM on the source
    :param network_map: network mapping
    :param source_options: added source environment options
    """
    vm_info = coriolis.endpoint_instances.get(
        source_endpoint, vm_name_or_id, env=source_options)

    for nic in vm_info['devices']['nics']:
        if nic['network_name'] not in network_map.values():
            raise Exception(
                "Mapped network for NIC with MAC '%s' not found: %s" % (
                    nic['mac_address'], nic['network_name']))


def main():
    session = ksession.Session(
        auth=v3.Password(**CORIOLIS_CONNECTION_INFO))

    coriolis = coriolis_client.Client(session=session)

    # fetch and validate options for Azure:
    azure_schema = get_schema_for_plugin(
        'coriolis', 'azure', 'source')
    # NOTE: this parameter validation is also done in any API
    # call involving the Azure source options:
    jsonschema.validate(AZURE_SOURCE_OPTIONS, azure_schema)

    # fetch and validate options schema for OCI:
    oci_schema = get_schema_for_plugin(
        'coriolis', 'oci', 'destination')
    # NOTE: this parameter validation is also done in any API
    # call involving the OCI destination options:
    jsonschema.validate(OCI_DESTINATION_OPTIONS, oci_schema)

    # list all available options on source or target:
    azure_options = coriolis.endpoint_source_options.list(
        AZURE_ENDPOINT_ID, environment=AZURE_SOURCE_OPTIONS)
    print("Avaialble Azure options are: ", json.dumps(azure_options, indent=4))
    oci_options = coriolis.endpoint_destination_options.list(
        OCI_ENDPOINT_ID, environment=OCI_DESTINATION_OPTIONS)
    print("Avaialble OCI options are: ", json.dumps(oci_options, indent=4))

    # check all mapped networks and storage exist:
    check_mapped_networks_exist(
        coriolis, OCI_ENDPOINT_ID, NETWORK_MAP,
        destination_environment=OCI_DESTINATION_OPTIONS)
    check_mapped_storage_exists(
        coriolis, OCI_ENDPOINT_ID, NETWORK_MAP,
        destination_environment=OCI_DESTINATION_OPTIONS)

    # get list of Linux VMs off of Azure:
    azure_linux_vms = get_linux_vms_for_endpoint(
        coriolis, AZURE_ENDPOINT_ID, source_options=AZURE_SOURCE_OPTIONS)
    print("Linux VMs currently on Azure: %s" % azure_linux_vms)

    # check network mapping:
    if azure_linux_vms:
        vm_name = azure_linux_vms[0].instance_name
        check_vm_network_mapping(
            coriolis, AZURE_ENDPOINT_ID, vm_name, NETWORK_MAP,
            source_options=AZURE_SOURCE_OPTIONS)