Exemplo n.º 1
0
    def _update_vms_and_gateways(self, specific_vm_name: str = None,
                                 specific_gateway_name: str = None):
        with self._update_lock:
            d, timestamp = _vine_net_exec('vineservice.list.vms',
                                          {
                                              'testbed_id': str(self.testbed_id)
                                          })

            for gateway in self.gateways.values():  # type: MutableVineGateway
                if str(gateway.gateway_id) in d['gateways']:
                    gateway.gateway_details = objectify(d['gateways'][str(gateway.gateway_id)],
                                                        VineserviceGatewayDetails)

            for vm in self.vms.values():  # type: MutableVineVm
                if str(vm.testbed_id) in d['vms']:
                    vm.vm_details = objectify(d['vms'][str(vm.vm_id)], VineVmDetails)

            if specific_gateway_name is not None:
                gateway_id = list({k for k in d['gateways'] if d['gateways'][k]['name'] == specific_gateway_name})[0]
                gateway_details = objectify(d['gateways'][gateway_id], VineserviceGatewayDetails)
                gateway = MutableVineGateway(testbed_id=int(self.testbed_id), gateway_id=int(gateway_id),
                                             gateway_details=gateway_details)
                self.gateways[gateway_details.gateway_name] = gateway

            if specific_vm_name is not None:
                vm_id = list({k for k in d['vms'] if d['vms'][k]['vm_name'] == specific_vm_name})[0]
                vm_details = objectify(d['vms'][vm_id], VineVmDetails)
                vm = MutableVineVm(testbed_id=int(self.testbed_id), vm_id=int(vm_id), vm_details=vm_details)
                self.vms[vm_details.vm_name] = vm
Exemplo n.º 2
0
    async def _make_request(command: str, machine_readable: bool, request_params: Dict):
        global _last_msg, _stdout_websocket_identifier

        await _connect_stdout()

        param_tuples = ()
        for key in request_params:
            param_tuples = param_tuples + ((key, request_params[key]),)

        if _stdout_websocket_identifier is not None:
            param_tuples = param_tuples + (('stdout_identifier', _stdout_websocket_identifier),)

        msg = None

        async with websockets.connect(
                SERVER_URL + '/' + command + '?' + parse.urlencode(param_tuples), timeout=86400) as websocket:
            try:
                while True:
                    msg = await websocket.recv()
                    if machine_readable:
                        print(msg)
                    else:
                        rcv_data = objectify(msg, StatusNotification)  # type: StatusNotification
                        print(rcv_data.message)
            except websockets.ConnectionClosed:
                if _stdout_websocket is not None:
                    await _stdout_websocket.close()

        _last_msg = msg
Exemplo n.º 3
0
async def _wait_for_update(testbed_id: int, since: int, source_type: str, source_id: int, finished_message_regex: str,
                           timeout_s: int, failed_message_regex: str = None):
    # TODO: Increment the "since" value for each check

    elapsed = 0
    while elapsed < timeout_s:
        response, timestamp = _vine_net_exec('vineservice.get.updates',
                                             {
                                                 'since': since,
                                                 'testbed_id': testbed_id
                                             })

        for event_dict in response['events']:
            event = objectify(event_dict, VineserviceEvent)  # type: VineserviceEvent
            if event.source_type == source_type and event.source_id == source_id:
                if re.match(finished_message_regex, event.message) is not None:
                    return
                elif failed_message_regex is not None and re.match(failed_message_regex, event.message) is not None:
                    raise Exception('Failed occurred while waiting for update! testbed_id: ' + str(testbed_id) +
                                    ', source_type: ' + source_type + ', source_id: ' + str(source_id) +
                                    ', message_regex: ' + failed_message_regex)
        await asyncio.sleep(1)
        elapsed = elapsed + 1

    raise Exception('Timeout of ' + str(timeout_s) + ' occurred while waiting for update! testbed_id: ' +
                    str(testbed_id) + ', source_type: ' + source_type + ', source_id: ' + str(source_id) +
                    ', message_regex: ' + finished_message_regex)
Exemplo n.º 4
0
def _get_gateway(gateway_name: str, testbed_id: int):
    d, timestamp = _vine_net_exec('vineservice.list.gateways',
                                  {
                                      'testbed_id': testbed_id
                                  })
    gateway_id = list(filter(lambda x: d['gateways'][x]['name'] == gateway_name, d['gateways'].keys()))[0]
    gateway_details = objectify(d['gateways'][gateway_id], VineserviceGatewayDetails)
    return MutableVineGateway(gateway_id=gateway_id, testbed_id=testbed_id, gateway_details=gateway_details)
Exemplo n.º 5
0
def _get_vm(testbed_id: int, vm_name: str) -> MutableVineVm:
    d, timestamp = _vine_net_exec('vineservice.list.vms',
                                  {
                                      'testbed_id': str(testbed_id)
                                  })
    vm_id = list(filter(lambda x: d['vms'][x]['vm_name'] == vm_name, d['vms'].keys()))[0]
    vm_details = objectify(d['vms'][vm_id], VineVmDetails)

    return MutableVineVm(vm_id=int(vm_id), testbed_id=testbed_id, vm_details=vm_details)
Exemplo n.º 6
0
    async def add_vms(self, vms: List[MutableVineVm], node_numbers: List[int]):
        timestamp = str(int(time.time() * 1000))

        _vine_net_exec('vineservice.get.updates',
                       {
                           'since': timestamp,
                           'testbed_id': self.testbed_id
                       })

        pending_entities = {}

        for idx in range(0, len(vms)):
            vm = vms[idx]
            ip_address = self.gateway_details.gateway[0:self.gateway_details.gateway.rfind('.') + 1] + str(
                node_numbers[idx])
            pending_entities[vm.vm_id] = {
                "vm_name": vm.vm_details.vm_name,
                "ni_obj": {
                    "pending_add_auto": {},
                    "pending_add_user": {
                        "nic0": {
                            "gateway_id": str(
                                self.gateway_id),
                            "ip_address": ip_address,
                            "status": "pending_add"
                        }
                    },
                    "pending_delete": {}
                },
                "status": "pending_edit_nw"}

        data, timestamp = _vine_net_exec('vineservice.apply.testbed',
                                         {"testbed_id": self.testbed_id,
                                          "pending_entities": pending_entities
                                          })

        _vine_net_exec('vineservice.edit.gateway',
                       {
                           "net_address": self.gateway_details.net_address,
                           "is_vm": False,
                           "max_hosts": self.gateway_details.max_hosts,
                           "gateway": self.gateway_details.gateway,
                           "used_hosts": self.gateway_details.used_hosts,
                           "bcast_address": self.gateway_details.bcast_address,
                           "netmask": self.gateway_details.netmask,
                           "name": self.gateway_details.name,
                           "uuid": self.gateway_details.uuid,
                           "created": None,
                           "modified": None,
                           "dummy": False,
                           "id": str(self.gateway_id)
                       })

        task = objectify(data, VineTask)  # type: VineTask
        return await _wait_for_task_finish(vine_task=task)
Exemplo n.º 7
0
def create_testbed(testbed_name: str, testbed_desc: str) -> MutableVineTestbed:
    d, timestamp = _vine_net_exec('vineservice.add.testbed',
                                  {
                                      "testbed_name": testbed_name,
                                      "testbed_group": VINE_GROUP,
                                      "testbed_desc": testbed_desc})

    # def __init__(self, testbed_id: int, testbed: Dict[str, VineTestbedDetails], status: int):
    testbed_id = d['testbed_id']
    testbed_details = objectify(d['testbed'][str(testbed_id)], VineTestbedDetails)
    return MutableVineTestbed(testbed_id=testbed_id, testbed_details=testbed_details, vms=dict(), gateways=dict())
Exemplo n.º 8
0
def get_testbed(testbed_name: str) -> MutableVineTestbed:
    try:
        d, timestamp = _vine_net_exec('vineservice.list.testbeds', None)

        testbed_id = list(filter(lambda x: d['testbeds'][x]['testbed_name'] == testbed_name, d['testbeds'].keys()))[0]
        return MutableVineTestbed(testbed_id=int(testbed_id),
                                  testbed_details=objectify(d['testbeds'][testbed_id], VineTestbedDetails),
                                  vms=dict(), gateways=dict())
    except Exception as e:
        print(str(e))
        traceback.print_exc()
        raise BuildServiceException(ActivityStatus.SERVER_ERROR, testbed_name,
                                    message='Could not get testbed with the name "' + testbed_name + "'!")
Exemplo n.º 9
0
def get_vms_by_id(testbed_id: int) -> List[MutableVineVm]:
    rval = list()
    d, timestamp = _vine_net_exec('vineservice.list.vms',
                                  {
                                      'testbed_id': str(testbed_id)
                                  })

    for vm_id in d['vms'].keys():
        vm_details = objectify(d['vms'][str(vm_id)], VineVmDetails)
        rval.append(MutableVineVm(
            vm_id=int(vm_id),
            testbed_id=testbed_id,
            vm_details=vm_details

        ))

    return rval
Exemplo n.º 10
0
def get_testbeds_by_ids(testbed_ids: List[int]) -> List[MutableVineTestbed]:
    rval = list()

    d, timestamp = _vine_net_exec('vineservice.list.testbeds', None)

    for testbed_id in testbed_ids:
        if str(testbed_id) in d['testbeds']:
            testbed_vms = get_vms_by_id(testbed_id=testbed_id)
            testbed_dict = dict()
            for testbed_vm in testbed_vms:
                testbed_dict[testbed_vm.vm_details.vm_name] = testbed_vm

            rval.append(MutableVineTestbed(testbed_id=int(testbed_id),
                                           testbed_details=objectify(d['testbeds'][str(testbed_id)], VineTestbedDetails),
                                           vms=testbed_dict,
                                           gateways=dict()))

        else:
            print('Testbed with id ' + str(testbed_id) + ' no longer exists on the vine cluster.')
    return rval
Exemplo n.º 11
0
    def create_unmanaged_testbed(include_android: bool, autoconf: bool):
        if autoconf and not os.path.exists(SSH_KEY_PATH):
            print('ERROR: Please add an authorized key to testbed images and ensure the private key exists at "' +
                  SSH_KEY_PATH + '"!')
            exit(1)

        asyncio.get_event_loop().run_until_complete(_make_request(
            'createTestbed', mm,
            {'testbed_name': user + '_' + parser_args.testbed_name,
             'include_android': include_android}
        ))

        if autoconf:
            rx_msg_data = json.loads(_last_msg)

            if 'status' not in rx_msg_data or rx_msg_data['status'] != 'TESTBED_READY' or rx_msg_data['data'] is None:
                print('Cannot create autoconf file since the server did not return all required information!')

            rx_data = rx_msg_data['data']
            rx_tb = objectify(rx_data, DasTestbed)
            save_ssh_config_and_display_usage(rx_tb, parser_args.testbed_name.lower())
Exemplo n.º 12
0
def _get_latest_matching_images(regex_match_strings: List[str]) -> Dict[str, VineImage]:
    rval = dict()

    existing_image_data = _vine_net_exec('vineservice.list.images', {'show_passwords': False})[0]['images']

    for regex in regex_match_strings:
        latest_image_dict = None

        for key in existing_image_data:
            image_name = existing_image_data[key]['image_name']  # type: str
            if re.match(regex, image_name) and (
                    latest_image_dict is None or image_name >= latest_image_dict['image_name']):
                latest_image_dict = existing_image_data[key]
                latest_image_dict['image_id'] = key

        if latest_image_dict is None:
            raise Exception("Could not find an image matching regex '" + regex + "'!")

        rval[regex] = objectify(latest_image_dict, VineImage)

    return rval
Exemplo n.º 13
0
def update_testbeds_details(testbeds: List[MutableVineTestbed]):
    d, timestamp = _vine_net_exec('vineservice.list.testbeds', None)

    for tb in testbeds:
        if str(tb.testbed_id) in d['testbeds']:
            tb.testbed_details = objectify(d['testbeds'][str(tb.testbed_id)], VineTestbedDetails)
Exemplo n.º 14
0
def _get_testbed_by_id(testbed_id: int):
    d, timestamp = _vine_net_exec('vineservice.list.testbeds', None)

    return MutableVineTestbed(testbed_id=testbed_id,
                              testbed_details=objectify(d['testbeds'][str(testbed_id)], VineTestbedDetails),
                              vms=dict(), gateways=dict())
Exemplo n.º 15
0
async def _vine_net_exec_wait_for_task_finish(method: str, params: Dict[str, object] = None) \
        -> Tuple[VineTaskStatus, int]:
    data, timestamp = _vine_net_exec(method=method, params=params)
    task = objectify(data, VineTask)  # type: VineTask
    # task_id = data['task_id']
    return await _wait_for_task_finish(vine_task=task)
Exemplo n.º 16
0
def main(parser_args):
    import importlib.util
    missing_libs = list()
    if importlib.util.find_spec('requests') is None:
        missing_libs.append('requests==2.18.4')
    if importlib.util.find_spec('sanic') is None:
        missing_libs.append('sanic==0.7.0')
    if importlib.util.find_spec('websockets') is None:
        missing_libs.append('websockets==6.0')

    if len(missing_libs) > 0:
        print("ERROR: Missing required libraries! Please install using the following command::")
        print('    ' + sys.executable + ' -m pip install ' + ' '.join(missing_libs))
        exit(1)

    import websockets
    from buildsystem.datatypes import objectify, StatusNotification
    from buildsystem.testbedmanager import DasTestbed
    from buildsystem.vine import VINE_ROOT_URL

    if parser_args.verbose:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.INFO)

    async def _connect_stdout():
        global _stdout_websocket, _stdout_websocket_identifier

        async def print_from_websocket(ws):

            try:
                while True:
                    msg = await ws.recv()
                    print(msg)

            except websockets.ConnectionClosed:
                pass

        websocket = await websockets.connect(SERVER_URL + '/stdoutListener', timeout=86400)
        _stdout_websocket = websocket
        _stdout_websocket_identifier = await websocket.recv()
        asyncio.ensure_future(print_from_websocket(websocket))

    async def _make_request(command: str, machine_readable: bool, request_params: Dict):
        global _last_msg, _stdout_websocket_identifier

        await _connect_stdout()

        param_tuples = ()
        for key in request_params:
            param_tuples = param_tuples + ((key, request_params[key]),)

        if _stdout_websocket_identifier is not None:
            param_tuples = param_tuples + (('stdout_identifier', _stdout_websocket_identifier),)

        msg = None

        async with websockets.connect(
                SERVER_URL + '/' + command + '?' + parse.urlencode(param_tuples), timeout=86400) as websocket:
            try:
                while True:
                    msg = await websocket.recv()
                    if machine_readable:
                        print(msg)
                    else:
                        rcv_data = objectify(msg, StatusNotification)  # type: StatusNotification
                        print(rcv_data.message)
            except websockets.ConnectionClosed:
                if _stdout_websocket is not None:
                    await _stdout_websocket.close()

        _last_msg = msg

    def create_unmanaged_testbed(include_android: bool, autoconf: bool):
        if autoconf and not os.path.exists(SSH_KEY_PATH):
            print('ERROR: Please add an authorized key to testbed images and ensure the private key exists at "' +
                  SSH_KEY_PATH + '"!')
            exit(1)

        asyncio.get_event_loop().run_until_complete(_make_request(
            'createTestbed', mm,
            {'testbed_name': user + '_' + parser_args.testbed_name,
             'include_android': include_android}
        ))

        if autoconf:
            rx_msg_data = json.loads(_last_msg)

            if 'status' not in rx_msg_data or rx_msg_data['status'] != 'TESTBED_READY' or rx_msg_data['data'] is None:
                print('Cannot create autoconf file since the server did not return all required information!')

            rx_data = rx_msg_data['data']
            rx_tb = objectify(rx_data, DasTestbed)
            save_ssh_config_and_display_usage(rx_tb, parser_args.testbed_name.lower())

    def save_ssh_config_and_display_usage(target_testbed: DasTestbed, config_identifier: str = None):
        if not os.path.exists(SSH_PATH):
            print('Cannot create autoconf file since the directory "' + SSH_PATH + '" does not exist!')
            return

        das_ip = target_testbed.get_das_vm().vm_details.public_ip
        has_android = target_testbed.has_android_vms()
        testbed_id = target_testbed.testbed.testbed_id
        testbed_name = target_testbed.testbed.testbed_details.testbed_name

        if config_identifier is None:
            config_identifier = testbed_name.lower()

        ssh_file_lines = list()

        ssh_file_lines.append('Host ' + config_identifier + 'das\n')
        ssh_file_lines.append('  HostName ' + das_ip + '\n')
        ssh_file_lines.append('  IdentityFile ' + SSH_KEY_PATH + '\n')
        ssh_file_lines.append('  User ubuntu\n')
        ssh_file_lines.append('  StrictHostKeyChecking no\n')

        if has_android:
            android0_ip = target_testbed.get_android0_vm().vm_details.public_ip
            android1_ip = target_testbed.get_android1_vm().vm_details.public_ip

            ssh_file_lines.append('Host ' + config_identifier + 'android0\n')
            ssh_file_lines.append('  HostName ' + android0_ip + '\n')
            ssh_file_lines.append('  IdentityFile ' + SSH_KEY_PATH + '\n')
            ssh_file_lines.append('  User ubuntu\n')
            ssh_file_lines.append('  StrictHostKeyChecking no\n')

            ssh_file_lines.append('Host ' + config_identifier + 'android1\n')
            ssh_file_lines.append('  HostName ' + android1_ip + '\n')
            ssh_file_lines.append('  IdentityFile ' + SSH_KEY_PATH + '\n')
            ssh_file_lines.append('  User ubuntu\n')
            ssh_file_lines.append('  StrictHostKeyChecking no\n')

            display_msg = _create_testbed_android_autoconf_msg % (
                config_identifier, config_identifier, config_identifier, config_identifier, android1_ip, android0_ip,
                VINE_ROOT_URL,
                str(testbed_id))

        else:
            display_msg = _create_testbed_plain_autoconf_msg % (
                config_identifier, config_identifier, VINE_ROOT_URL, str(testbed_id))

        if len(ssh_file_lines) > 0:
            with open(os.path.join(SSH_PATH,
                                   'immortals_vine_' + config_identifier + '_config'),
                      'w') as file:
                file.writelines(ssh_file_lines)

            print(display_msg)

    if re.search('^[a-zA-Z0-9_]*$', parser_args.testbed_name) is None:
        print("ERROR: Testbed Must contain only nunbers, letters, or an underscore!")
        exit(1)

    if parser_args.testbed_name == "null" or parser_args.testbed_name == "None":
        print('ERROR: "null" and "None" cannot be used for testbed names!')
        exit(1)

    mm = parser_args.machine_mode

    user = os.environ['USER']
    if user is None:
        user = '******' + str(uuid.uuid4())[0:8]

    # Jekins specific commands
    if parser_args.jenkins_add_plain_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'addPlainTestbedToBuildPool', mm,
            {}
        ))

    elif parser_args.jenkins_add_android_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'addAndroidTestbedToBuildPool', mm,
            {}
        ))

    elif parser_args.jenkins_replace_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'replaceTestbedInBuildPool', mm,
            {'testbed_name': 'jenkins_' + parser_args.testbed_name}
        ))

    elif parser_args.jenkins_replace_testbed_nowait:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'replaceTestbedInBuildPoolNoWait', mm,
            {'testbed_name': 'jenkins_' + parser_args.testbed_name}
        ))

    elif parser_args.jenkins_claim_plain_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'claimBuildpoolPlainTestbed', mm,
            {'testbed_name': 'jenkins_' + parser_args.testbed_name}
        ))

    elif parser_args.jenkins_claim_android_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'claimBuildpoolAndroidTestbed', mm,
            {'testbed_name': 'jenkins_' + parser_args.testbed_name}
        ))

    elif parser_args.jenkins_start_testbed_coordinator:
        from buildsystem import server
        server.main()

    elif parser_args.jenkins_perform_predeploy_rebuild:
        raise NotImplementedError
        # asyncio.get_event_loop().run_until_complete(_make_request(
        #     'rebuildPredeployImage', mm,
        #     {'testbed_name': user + '_' + parser_args.testbed_name}
        # ))

    elif parser_args.jenkins_autoconf:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'getExistingTestbed', mm,
            {'testbed_name': 'jenkins_' + parser_args.testbed_name}
        ))

        msg_data = json.loads(_last_msg)

        if 'status' not in msg_data or msg_data['status'] != 'TESTBED_READY' or msg_data['data'] is None:
            print('Cannot create autoconf file since the server did not return all required information!')

        data = msg_data['data']
        testbed = objectify(data, DasTestbed)
        save_ssh_config_and_display_usage(testbed, 'jenkinstemp')

    # General commands
    elif parser_args.create_testbed:
        create_unmanaged_testbed(False, False)

    elif parser_args.create_android_testbed:
        create_unmanaged_testbed(True, False)

    elif parser_args.delete_testbed:
        asyncio.get_event_loop().run_until_complete(_make_request(
            'deleteTestbed', mm,
            {'testbed_name': user + '_' + parser_args.testbed_name}
        ))

    elif parser_args.create_testbed_autoconf:
        create_unmanaged_testbed(False, True)

    elif parser_args.create_android_testbed_autoconf:
        create_unmanaged_testbed(True, True)

    elif parser_args.das_repo_update:
        params = {
            'testbed_name': user + '_' + parser_args.testbed_name
        }

        if parser_args.branch is not None:
            params['branch'] = parser_args.branch

        asyncio.get_event_loop().run_until_complete(_make_request('updateRepo', mm, params))

    elif parser_args.das_execute_test is not None:
        params = {
            'testbed_name': user + '_' + parser_args.testbed_name,
            'test_identifier': parser_args.das_execute_test
        }
        if parser_args.specify_cp_profile is not None:
            params['cp_profile'] = parser_args.specify_cp_profile
        if parser_args.branch is not None:
            params['branch'] = parser_args.branch

        asyncio.get_event_loop().run_until_complete(_make_request('dasExecuteTest', mm, params))

    elif parser_args.das_deploy:
        params = {
            'testbed_name': user + '_' + parser_args.testbed_name,
        }
        if parser_args.specify_cp_profile is not None:
            params['cp_profile'] = parser_args.specify_cp_profile
        if parser_args.branch is not None:
            params['branch'] = parser_args.branch
        asyncio.get_event_loop().run_until_complete(_make_request(
            'dasDeploy', mm,
            params
        ))

    else:
        print('Unexpected parameters.')
        exit(1)

    notification = objectify(json.loads(_last_msg), StatusNotification)  # type: StatusNotification
    exit(notification.status.error_code)
Exemplo n.º 17
0
def ping() -> VineservicePingResponse:
    d, timestamp = _vine_net_exec('vineservice.admin',
                                  {
                                      'action': 'ping'
                                  })
    return objectify(d, VineservicePingResponse)  # type: VineservicePingResponse