コード例 #1
0
def cse_restore_session(ctx, vdc_required=False) -> None:
    """Restores the session with vcd client with right server api version.

    Replace the vcd client in ctx.obj with new client created with server api
    version. Also saves the server api version in profiles.

    :param <click.core.Context> ctx: click context
    :param bool vdc_required: is vdc required or not
    :return:
    """
    # Always override the vcd_client by new client with CSE server api version.
    if type(ctx.obj) is not dict or not ctx.obj.get('client'):
        profiles = Profiles.load()
        token = profiles.get('token')
        if token is None or len(token) == 0:
            raise Exception('Can\'t restore session, please login again.')
        if not profiles.get('verify'):
            if not profiles.get('disable_warnings'):
                click.secho(
                    'InsecureRequestWarning: '
                    'Unverified HTTPS request is being made. '
                    'Adding certificate verification is strongly '
                    'advised.',
                    fg='yellow',
                    err=True)
            requests.packages.urllib3.disable_warnings()

        client = Client(
            profiles.get('host'),
            api_version=profiles.get('api_version'),
            verify_ssl_certs=profiles.get('verify'),
            log_file='vcd.log',
            log_requests=profiles.get('log_request'),
            log_headers=profiles.get('log_header'),
            log_bodies=profiles.get('log_body'))
        client.rehydrate_from_token(
            profiles.get('token'), profiles.get('is_jwt_token'))

        ctx.obj = {}
        ctx.obj['client'] = client

    _override_client(ctx)

    if vdc_required:
        if not ctx.obj['profiles'].get('vdc_in_use') or \
                not ctx.obj['profiles'].get('vdc_href'):
            raise Exception('select a virtual datacenter')
コード例 #2
0
def _override_client(ctx) -> None:
    """Replace the vcd client in ctx.obj with new one.

    New vcd client takes the CSE server_api_version as api_version param.
    Save profile also with 'cse_server_api_version' for subsequent commands.

    :param <click.core.Context> ctx: click context
    """
    profiles = Profiles.load()
    # if the key CSE_SERVER_RUNNING is not present in the profiles.yaml,
    # we make an assumption that CSE server is running
    is_cse_server_running = profiles.get(CSE_SERVER_RUNNING, default=True)
    cse_server_api_version = profiles.get(CSE_SERVER_API_VERSION)
    if not is_cse_server_running:
        restrict_cli_to_tkg_operations()
        ctx.obj['profiles'] = profiles
        return

    # Get server_api_version; save it in profiles if doesn't exist
    if not cse_server_api_version:
        try:
            system = syst.System(ctx.obj['client'])
            sys_info = system.get_info()
            cse_server_api_version = sys_info.get(CSE_SERVER_API_VERSION)
            profiles.set(CSE_SERVER_API_VERSION, cse_server_api_version)
            profiles.set(CSE_SERVER_RUNNING, True)
            profiles.save()
        except CseResponseError:
            # If request to CSE server times out
            profiles.set(CSE_SERVER_RUNNING, False)
            # restrict CLI for only TKG operations
            restrict_cli_to_tkg_operations()
            ctx.obj['profiles'] = profiles
            profiles.save()
            return
    client = Client(profiles.get('host'),
                    api_version=cse_server_api_version,
                    verify_ssl_certs=profiles.get('verify'),
                    log_file='vcd.log',
                    log_requests=profiles.get('log_request'),
                    log_headers=profiles.get('log_header'),
                    log_bodies=profiles.get('log_body'))
    client.rehydrate_from_token(profiles.get('token'),
                                profiles.get('is_jwt_token'))  # noqa: E501
    ctx.obj['client'] = client
    ctx.obj['profiles'] = profiles
コード例 #3
0
def cse_restore_session(ctx) -> None:
    """Restores the session with vcd client with right server api version.

    Replace the vcd client in ctx.obj with new client created with server api
    version. Also saves the server api version in profiles.

    :param <click.core.Context> ctx: click context

    :return:
    """
    # Always override the vcd_client by new client with CSE server api version.
    if type(ctx.obj) is not dict or not ctx.obj.get('client'):
        CLIENT_LOGGER.debug('Restoring client from profile.')
        profiles = Profiles.load()
        token = profiles.get('token')
        if token is None or len(token) == 0:
            msg = "Can't restore session, please login again."
            CLIENT_LOGGER.debug(f"Missing Token : {msg}")
            raise Exception(msg)
        if not profiles.get('verify'):
            if not profiles.get('disable_warnings'):
                click.secho(
                    'InsecureRequestWarning: '
                    'Unverified HTTPS request is being made. '
                    'Adding certificate verification is strongly '
                    'advised.',
                    fg='yellow',
                    err=True)
            requests.packages.urllib3.disable_warnings()

        client = Client(profiles.get('host'),
                        api_version=profiles.get('api_version'),
                        verify_ssl_certs=profiles.get('verify'),
                        log_file='vcd.log',
                        log_requests=profiles.get('log_request'),
                        log_headers=profiles.get('log_header'),
                        log_bodies=profiles.get('log_body'))
        client.rehydrate_from_token(profiles.get('token'),
                                    profiles.get('is_jwt_token'))

        ctx.obj = {'client': client}
    else:
        CLIENT_LOGGER.debug('Reusing client from context.')

    _override_client(ctx)
コード例 #4
0
def vcd_login_with_token(host):
    logging.basicConfig(level=logging.DEBUG)
    logging.info("INIT vcd_login_with_token")
    profiles = Profiles.load()
    token = profiles.get('token')
    client = Client(host,
                    api_version="27.0",
                    verify_ssl_certs=False,
                    log_file='vcd.log',
                    log_requests=True,
                    log_headers=True,
                    log_bodies=True)
    try:
        client.rehydrate_from_token(token)
        x = client._session.headers['x-vcloud-authorization']
        logging.info(" =====  X VCloud ========\n  \n" + x + "\n \n")
    except Exception as e:
        print('error occured', e)
コード例 #5
0
def vcd_login_with_token(host):
    logging.basicConfig(level=logging.DEBUG)
    logging.info("INIT vcd_login_with_token")
    profiles = Profiles.load()
    token = profiles.get('token')
    client = Client(
        host,
        api_version="27.0",
        verify_ssl_certs=False,
        log_file='vcd.log',
        log_requests=True,
        log_headers=True,
        log_bodies=True)
    try:
        client.rehydrate_from_token(token)
        x = client._session.headers['x-vcloud-authorization']
        logging.info(" =====  X VCloud ========\n  \n" + x + "\n \n")
    except Exception as e:
        print('error occured', e)
コード例 #6
0
def login(session_id=None):
    log_requests = True if config['log'] == True else False
    log_headers = True if config['log'] == True else False
    log_bodies = True if config['log'] == True else False

    client = Client(config['host'],
                    api_version=config['api_version'],
                    verify_ssl_certs=config['verify_ssl_certs'],
                    log_file=config['log_file'],
                    log_requests=log_requests,
                    log_headers=log_headers,
                    log_bodies=log_bodies)

    if not config['verify_ssl_certs']:
        requests.packages.urllib3.disable_warnings()

    try:
        if session_id is not None:
            client.rehydrate_from_token(session_id)
        else:
            client.set_credentials(
                BasicLoginCredentials(config['username'], config['org'],
                                      config['password']))

        logged_in_org = client.get_org()
        org = Org(client, resource=logged_in_org)
        org_url = "https://%s/cloud/org/%s" % (config['host'], logged_in_org)
        the_vdc = org.get_vdc(config['vdc'])

        # Set contextual data:
        ctx.client = client
        ctx.vdc = VDC(client, href=the_vdc.get('href'))
        ctx.token = client._session.headers['x-vcloud-authorization']
    except Exception as e:
        if config['debug'] == True:
            print("Exception: {}\n".format(e))
        return False
    return True
コード例 #7
0
def restore_session(ctx, vdc_required=False):
    if type(ctx.obj) is dict and 'client' in ctx.obj and ctx.obj['client']:
        return
    profiles = Profiles.load()
    token = profiles.get('token')
    if token is None or len(token) == 0:
        raise Exception('Can\'t restore session, please login again.')
    if not profiles.get('verify'):
        if profiles.get('disable_warnings'):
            pass
        else:
            click.secho(
                'InsecureRequestWarning: '
                'Unverified HTTPS request is being made. '
                'Adding certificate verification is strongly '
                'advised.',
                fg='yellow',
                err=True)
        requests.packages.urllib3.disable_warnings()

    client = Client(
        profiles.get('host'),
        api_version=profiles.get('api_version'),
        verify_ssl_certs=profiles.get('verify'),
        log_file='vcd.log',
        log_requests=profiles.get('log_request'),
        log_headers=profiles.get('log_header'),
        log_bodies=profiles.get('log_body'))
    client.rehydrate_from_token(
        profiles.get('token'), profiles.get('is_jwt_token'))

    ctx.obj = {}
    ctx.obj['client'] = client
    ctx.obj['profiles'] = profiles
    if vdc_required:
        if not ctx.obj['profiles'].get('vdc_in_use') or \
           not ctx.obj['profiles'].get('vdc_href'):
            raise Exception('select a virtual datacenter')
コード例 #8
0
def connect_vcd_user_via_token(tenant_auth_token):
    server_config = get_server_runtime_config()
    vcd_uri = server_config['vcd']['host']
    version = server_config['vcd']['api_version']
    verify_ssl_certs = server_config['vcd']['verify']
    client_tenant = Client(uri=vcd_uri,
                           api_version=version,
                           verify_ssl_certs=verify_ssl_certs,
                           log_file=SERVER_DEBUG_WIRELOG_FILEPATH,
                           log_requests=True,
                           log_headers=True,
                           log_bodies=True)
    session = client_tenant.rehydrate_from_token(tenant_auth_token)
    return (client_tenant, session)
コード例 #9
0
 def connect_tenant(self, headers):
     token = headers.get('x-vcloud-authorization')
     accept_header = headers.get('Accept')
     version = accept_header.split('version=')[1]
     client_tenant = Client(uri=self.config['vcd']['host'],
                            api_version=version,
                            verify_ssl_certs=self.config['vcd']['verify'],
                            log_headers=True,
                            log_bodies=True)
     session = client_tenant.rehydrate_from_token(token)
     return (
         client_tenant,
         session,
     )
コード例 #10
0
def vcd_login(context, lc):
    logging.info("__INIT__vcd_login [%s]", lc)
    login_path = ""
    client = Client(
        lc.ip,
        api_version="27.0",
        verify_ssl_certs=not lc.allow_insecure_flag,
        log_file='vcd.log',
        log_requests=True,
        log_headers=True,
        log_bodies=True)
    try:
        if lc.use_vcd_cli_profile:
            login_path = "rehydrate_from_token"
            profiles = Profiles.load()
            token = profiles.get('token')
            client.rehydrate_from_token(token)

        else:
            login_path = "set_credentials"
            client.set_credentials(
                BasicLoginCredentials(lc.username, lc.org, lc.password))

        vref = VCDClientRef()
        vref.set_ref(client)
        logging.debug('LOGIN VIA :[{0}] ARG :[{1}]'.format(
            login_path, str(lc)))

        return client
    except Exception as e:
        traceback.print_exc()
        error_message = 'ERROR IN LOGIN .. Exception [{0}] LOGIN VIA :[{1}] ARG :[{2}]'.format(
            str(e), login_path, str(lc))
        error_message = error_message.replace('\n', ' ')
        context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
        context.set_details(error_message)
        raise
コード例 #11
0
def vcd_login(context, lc):
    logging.info("__INIT__vcd_login [%s]", lc)
    login_path = ""
    client = Client(lc.ip,
                    api_version="27.0",
                    verify_ssl_certs=not lc.allow_insecure_flag,
                    log_file='vcd.log',
                    log_requests=True,
                    log_headers=True,
                    log_bodies=True)
    try:
        if lc.use_vcd_cli_profile:
            login_path = "rehydrate_from_token"
            profiles = Profiles.load()
            token = profiles.get('token')
            client.rehydrate_from_token(token)

        else:
            login_path = "set_credentials"
            client.set_credentials(
                BasicLoginCredentials(lc.username, lc.org, lc.password))

        vref = VCDClientRef()
        vref.set_ref(client)
        logging.debug('LOGIN VIA :[{0}] ARG :[{1}]'.format(
            login_path, str(lc)))

        return client
    except Exception as e:
        traceback.print_exc()
        error_message = 'ERROR IN LOGIN .. Exception [{0}] LOGIN VIA :[{1}] ARG :[{2}]'.format(
            str(e), login_path, str(lc))
        error_message = error_message.replace('\n', ' ')
        context.set_code(grpc.StatusCode.INVALID_ARGUMENT)
        context.set_details(error_message)
        raise
コード例 #12
0
def connect_vcd_user_via_token(tenant_auth_token):
    server_config = get_server_runtime_config()
    vcd_uri = server_config['vcd']['host']
    version = server_config['vcd']['api_version']
    verify_ssl_certs = server_config['vcd']['verify']
    log_filename = None
    log_wire = str_to_bool(server_config['service'].get('log_wire'))
    if log_wire:
        log_filename = SERVER_DEBUG_WIRELOG_FILEPATH
    client_tenant = Client(uri=vcd_uri,
                           api_version=version,
                           verify_ssl_certs=verify_ssl_certs,
                           log_file=log_filename,
                           log_requests=log_wire,
                           log_headers=log_wire,
                           log_bodies=log_wire)
    session = client_tenant.rehydrate_from_token(tenant_auth_token)
    return (client_tenant, session)
コード例 #13
0
ファイル: vcd_utils.py プロジェクト: lrivallain/vcdextproxy
def login_from_token(token):
    """Return a client session to use with the user's token.

    Args:
        token (string): Auth token provided by user.

    Returns:
        pyvcloud.vcd.client.Client: Session to use with the user's token.
    """
    client = Client(conf('global.vcloud.hostname'),
                    api_version=conf('global.vcloud.api_version'),
                    verify_ssl_certs=conf('global.vcloud.ssl_verify', True),
                    log_file=conf("global.pyvcloud.log_file"),
                    log_requests=conf("global.pyvcloud.log_requests"),
                    log_headers=conf("global.pyvcloud.log_headers"),
                    log_bodies=conf("global.pyvcloud.log_bodies"))
    session = client.rehydrate_from_token(token)
    return client, session
コード例 #14
0
def connect_vcd_user_via_token(vcd_uri, headers, verify_ssl_certs=True):
    if not verify_ssl_certs:
        LOGGER.warning("InsecureRequestWarning: Unverified HTTPS request is "
                       "being made. Adding certificate verification is "
                       "strongly advised.")
        requests.packages.urllib3.disable_warnings()
    token = headers.get('x-vcloud-authorization')
    accept_header = headers.get('Accept')
    version = accept_header.split('version=')[1]
    client_tenant = Client(uri=vcd_uri,
                           api_version=version,
                           verify_ssl_certs=verify_ssl_certs,
                           log_file=SERVER_DEBUG_WIRELOG_FILEPATH,
                           log_requests=True,
                           log_headers=True,
                           log_bodies=True)
    session = client_tenant.rehydrate_from_token(token)
    return (
        client_tenant,
        session,
    )
コード例 #15
0
def login(ctx, user, host, password, api_version, org, verify_ssl_certs,
          disable_warnings, vdc, session_id, use_browser_session):
    """Login to vCloud Director

\b
    Login to a vCloud Director service.
\b
    Examples
        vcd login mysp.com org1 usr1
            Login to host 'mysp.com'.
\b
        vcd login test.mysp.com org1 usr1 -i -w
            Login to a host with self-signed SSL certificate.
\b
        vcd login mysp.com org1 usr1 --use-browser-session
            Login using active session from browser.
\b
        vcd login session list chrome
            List active session ids from browser.
\b
        vcd login mysp.com org1 usr1 \\
            --session-id ee968665bf3412d581bbc6192508eec4
            Login using active session id.
\b
    Environment Variables
        VCD_PASSWORD
            If this environment variable is set, the command will use its value
            as the password to login and will not ask for one. The --password
            option has precedence over the environment variable.

    """

    if not verify_ssl_certs:
        if disable_warnings:
            pass
        else:
            click.secho(
                'InsecureRequestWarning: '
                'Unverified HTTPS request is being made. '
                'Adding certificate verification is strongly '
                'advised.',
                fg='yellow',
                err=True)
        requests.packages.urllib3.disable_warnings()

    if host == 'session' and org == 'list':
        sessions = []
        if user == 'chrome':
            cookies = browsercookie.chrome()
            for c in cookies:
                if c.name == 'vcloud_session_id':
                    sessions.append({'host': c.domain, 'session_id': c.value})
        stdout(sessions, ctx)
        return

    client = Client(
        host,
        api_version=api_version,
        verify_ssl_certs=verify_ssl_certs,
        log_file='vcd.log',
        log_requests=True,
        log_headers=True,
        log_bodies=True)
    try:
        if session_id is not None or use_browser_session:
            if use_browser_session:
                browser_session_id = None
                cookies = browsercookie.chrome()
                for c in cookies:
                    if c.name == 'vcloud_session_id' and \
                       c.domain == host:
                        browser_session_id = c.value
                        break
                if browser_session_id is None:
                    raise Exception('Session not found in browser.')
                session_id = browser_session_id
            client.rehydrate_from_token(session_id)
        else:
            if password is None:
                password = click.prompt('Password', hide_input=True, type=str)
            client.set_credentials(BasicLoginCredentials(user, org, password))

        negotiated_api_version = client.get_api_version()

        profiles = Profiles.load()
        logged_in_org = client.get_org()
        org_href = logged_in_org.get('href')
        vdc_href = ''
        in_use_vdc = ''

        links = []
        if float(negotiated_api_version) < float(ApiVersion.VERSION_33.value):
            links = get_links(logged_in_org, media_type=EntityType.VDC.value)
        else:
            if logged_in_org.get('name') != 'System':
                links = client.get_resource_link_from_query_object(
                    logged_in_org, media_type=EntityType.RECORDS.value,
                    type='vdc')

        if vdc is None:
            if len(links) > 0:
                in_use_vdc = links[0].name
                vdc_href = links[0].href
        else:
            for v in links:
                if vdc == v.name:
                    in_use_vdc = v.name
                    vdc_href = v.href
                    break
            if len(in_use_vdc) == 0:
                raise Exception('VDC not found')

        token = client.get_access_token()
        is_jwt_token = True
        if not token:
            token = client.get_xvcloud_authorization_token()
            is_jwt_token = False

        profiles.update(
            host,
            org,
            user,
            token,
            negotiated_api_version,
            verify_ssl_certs,
            disable_warnings,
            vdc=in_use_vdc,
            org_href=org_href,
            vdc_href=vdc_href,
            log_request=True,
            log_header=True,
            log_body=True,
            vapp='',
            vapp_href='',
            is_jwt_token=is_jwt_token)

        alt_text = f"{user} logged in, org: '{org}', vdc: '{in_use_vdc}'"
        d = {
            'user': user,
            'org': org,
            'vdc': in_use_vdc,
            'logged_in': True
        }
        stdout(d, ctx, alt_text)
    except Exception as e:
        try:
            profiles = Profiles.load()
            profiles.set('token', '')
        except Exception:
            pass
        stderr(e, ctx)
コード例 #16
0
class DefaultBroker(threading.Thread):
    def __init__(self, config):
        threading.Thread.__init__(self)
        self.config = config
        self.host = config['vcd']['host']
        self.username = config['vcd']['username']
        self.password = config['vcd']['password']
        self.version = config['vcd']['api_version']
        self.verify = config['vcd']['verify']
        self.log = config['vcd']['log']

    def _connect_sysadmin(self):
        if not self.verify:
            LOGGER.warning('InsecureRequestWarning: '
                           'Unverified HTTPS request is being made. '
                           'Adding certificate verification is strongly '
                           'advised.')
            requests.packages.urllib3.disable_warnings()
        self.client_sysadmin = Client(uri=self.host,
                                      api_version=self.version,
                                      verify_ssl_certs=self.verify,
                                      log_headers=True,
                                      log_bodies=True)
        self.client_sysadmin.set_credentials(
            BasicLoginCredentials(self.username, 'System', self.password))

    def _connect_tenant(self, headers):
        token = headers.get('x-vcloud-authorization')
        accept_header = headers.get('Accept')
        version = accept_header.split('version=')[1]
        self.client_tenant = Client(uri=self.host,
                                    api_version=version,
                                    verify_ssl_certs=self.verify,
                                    log_headers=True,
                                    log_bodies=True)
        session = self.client_tenant.rehydrate_from_token(token)
        return {
            'user_name':
            session.get('user'),
            'user_id':
            session.get('userId'),
            'org_name':
            session.get('org'),
            'org_href':
            self.client_tenant._get_wk_endpoint(
                _WellKnownEndpoint.LOGGED_IN_ORG)
        }

    def _to_message(self, e):
        if hasattr(e, 'message'):
            return {'message': e.message}
        else:
            return {'message': str(e)}

    def update_task(self, status, message=None, error_message=None):
        if not hasattr(self, 'task'):
            self.task = Task(self.client_sysadmin)
        if message is None:
            message = OP_MESSAGE[self.op]
        if hasattr(self, 'task_resource'):
            task_href = self.task_resource.get('href')
        else:
            task_href = None
        self.task_resource = self.task.update(
            status.value,
            'vcloud.cse',
            message,
            self.op,
            '',
            None,
            'urn:cse:cluster:%s' % self.cluster_id,
            self.cluster_name,
            'application/vcloud.cse.cluster+xml',
            self.tenant_info['user_id'],
            self.tenant_info['user_name'],
            org_href=self.tenant_info['org_href'],
            task_href=task_href,
            error_message=error_message)

    def is_valid_name(self, name):
        """Validate that the cluster name against the pattern."""
        if len(name) > MAX_HOST_NAME_LENGTH:
            return False
        if name[-1] == '.':
            name = name[:-1]
        allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
        return all(allowed.match(x) for x in name.split("."))

    def get_template(self, name=None):
        if name is None:
            if 'template' in self.body and self.body['template'] is not None:
                name = self.body['template']
            else:
                name = self.config['broker']['default_template']
        for template in self.config['broker']['templates']:
            if template['name'] == name:
                return template
        raise Exception('Template %s not found' % name)

    def run(self):
        LOGGER.debug('thread started op=%s' % self.op)
        if self.op == OP_CREATE_CLUSTER:
            self.create_cluster_thread()
        elif self.op == OP_DELETE_CLUSTER:
            self.delete_cluster_thread()
        elif self.op == OP_CREATE_NODES:
            self.create_nodes_thread()
        elif self.op == OP_DELETE_NODES:
            self.delete_nodes_thread()

    def list_clusters(self, headers, body):
        result = {}
        try:
            result['body'] = []
            result['status_code'] = OK
            self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant)
            result['body'] = clusters
        except Exception:
            LOGGER.error(traceback.format_exc())
            result['body'] = []
            result['status_code'] = INTERNAL_SERVER_ERROR
            result['message'] = traceback.format_exc()
        return result

    def get_cluster_info(self, name, headers, body):
        result = {}
        try:
            result['body'] = []
            result['status_code'] = OK
            self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant, name=name)
            if len(clusters) == 0:
                raise Exception('Cluster \'%s\' not found.' % name)
            vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
            vms = vapp.get_all_vms()
            for vm in vms:
                node_info = {
                    'name': vm.get('name'),
                    'numberOfCpus': '',
                    'memoryMB': '',
                    'status': VCLOUD_STATUS_MAP.get(int(vm.get('status'))),
                    'ipAddress': ''
                }
                if hasattr(vm, 'VmSpecSection'):
                    node_info['numberOfCpus'] = vm.VmSpecSection.NumCpus.text
                    node_info[
                        'memoryMB'] = \
                        vm.VmSpecSection.MemoryResourceMb.Configured.text
                try:
                    node_info['ipAddress'] = vapp.get_primary_ip(
                        vm.get('name'))
                except Exception:
                    LOGGER.debug('cannot get ip address for node %s' %
                                 vm.get('name'))
                if vm.get('name').startswith(TYPE_MASTER):
                    node_info['node_type'] = 'master'
                    clusters[0].get('master_nodes').append(node_info)
                elif vm.get('name').startswith(TYPE_NODE):
                    node_info['node_type'] = 'node'
                    clusters[0].get('nodes').append(node_info)
            result['body'] = clusters[0]
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            result['body'] = []
            result['status_code'] = INTERNAL_SERVER_ERROR
            result['message'] = str(e)
        return result

    def create_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        cluster_name = body['name']
        vdc_name = body['vdc']
        node_count = body['node_count']
        LOGGER.debug('about to create cluster %s on %s with %s nodes, sp=%s',
                     cluster_name, vdc_name, node_count,
                     body['storage_profile'])
        result['body'] = {
            'message': 'can\'t create cluster \'%s\'' % cluster_name
        }
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            if not self.is_valid_name(cluster_name):
                raise Exception('Invalid cluster name')
            self.tenant_info = self._connect_tenant(headers)
            self.headers = headers
            self.body = body
            self.cluster_name = cluster_name
            self.cluster_id = str(uuid.uuid4())
            self.op = OP_CREATE_CLUSTER
            self._connect_sysadmin()
            self.update_task(TaskStatus.RUNNING,
                             message='Creating cluster %s(%s)' %
                             (cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['name'] = self.cluster_name
            response_body['cluster_id'] = self.cluster_id
            response_body['task_href'] = self.task_resource.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            result['body'] = self._to_message(e)
            LOGGER.error(traceback.format_exc())
        return result

    def create_cluster_thread(self):
        network_name = self.body['network']
        try:
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 0:
                raise Exception('Cluster already exists.')
            org_resource = self.client_tenant.get_org()
            org = Org(self.client_tenant, resource=org_resource)
            vdc_resource = org.get_vdc(self.body['vdc'])
            vdc = VDC(self.client_tenant, resource=vdc_resource)
            template = self.get_template()
            self.update_task(TaskStatus.RUNNING,
                             message='Creating cluster vApp %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp_resource = vdc.create_vapp(self.cluster_name,
                                            description='cluster %s' %
                                            self.cluster_name,
                                            network=network_name,
                                            fence_mode='bridged')
            self.client_tenant.get_task_monitor().wait_for_status(
                vapp_resource.Tasks.Task[0])
            tags = {}
            tags['cse.cluster.id'] = self.cluster_id
            tags['cse.version'] = pkg_resources.require(
                'container-service-extension')[0].version
            tags['cse.template'] = template['name']
            vapp = VApp(self.client_tenant, href=vapp_resource.get('href'))
            for k, v in tags.items():
                task = vapp.set_metadata('GENERAL', 'READWRITE', k, v)
                self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(TaskStatus.RUNNING,
                             message='Creating master node for %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp.reload()
            add_nodes(1, template, TYPE_MASTER, self.config,
                      self.client_tenant, org, vdc, vapp, self.body)
            self.update_task(TaskStatus.RUNNING,
                             message='Initializing cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp.reload()
            init_cluster(self.config, vapp, template)
            master_ip = get_master_ip(self.config, vapp, template)
            task = vapp.set_metadata('GENERAL', 'READWRITE', 'cse.master.ip',
                                     master_ip)
            self.client_tenant.get_task_monitor().wait_for_status(task)
            if self.body['node_count'] > 0:
                self.update_task(TaskStatus.RUNNING,
                                 message='Creating %s node(s) for %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                add_nodes(self.body['node_count'], template, TYPE_NODE,
                          self.config, self.client_tenant, org, vdc, vapp,
                          self.body)
                self.update_task(TaskStatus.RUNNING,
                                 message='Adding %s node(s) to %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                vapp.reload()
                join_cluster(self.config, vapp, template)
            self.update_task(TaskStatus.SUCCESS,
                             message='Created cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))

    def delete_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        LOGGER.debug('about to delete cluster with name: %s' % body['name'])
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            self.cluster_name = body['name']
            self.tenant_info = self._connect_tenant(headers)
            self.headers = headers
            self.body = body
            self.op = OP_DELETE_CLUSTER
            self._connect_sysadmin()
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster %s not found.' % self.cluster_name)
            self.cluster = clusters[0]
            self.cluster_id = self.cluster['cluster_id']
            self.update_task(TaskStatus.RUNNING,
                             message='Deleting cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['cluster_name'] = self.cluster_name
            response_body['task_href'] = self.task_resource.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            result['body'] = self._to_message(e)
            LOGGER.error(traceback.format_exc())
        return result

    def delete_cluster_thread(self):
        LOGGER.debug('about to delete cluster with name: %s',
                     self.cluster_name)
        try:
            vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
            task = vdc.delete_vapp(self.cluster['name'], force=True)
            self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(TaskStatus.SUCCESS,
                             message='Deleted cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))

    def get_cluster_config(self, cluster_name, headers):
        result = {}
        try:
            self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant,
                                          name=cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster \'%s\' not found' % cluster_name)
            vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
            template = self.get_template(name=clusters[0]['template'])
            result['body'] = get_cluster_config(self.config, vapp,
                                                template['admin_password'])
            result['status_code'] = OK
        except Exception as e:
            result['body'] = self._to_message(e)
            result['status_code'] = INTERNAL_SERVER_ERROR
        return result

    def create_nodes(self, headers, body):
        result = {'body': {}}
        self.cluster_name = body['name']
        LOGGER.debug('about to add %s nodes to cluster %s on VDC %s, sp=%s',
                     body['node_count'], self.cluster_name, body['vdc'],
                     body['storage_profile'])
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            if body['node_count'] < 1:
                raise Exception('Invalid node count: %s.' % body['node_count'])
            self.tenant_info = self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster \'%s\' not found.' %
                                self.cluster_name)
            self.cluster = clusters[0]
            self.headers = headers
            self.body = body
            self.op = OP_CREATE_NODES
            self._connect_sysadmin()
            self.cluster_id = self.cluster['cluster_id']
            self.update_task(
                TaskStatus.RUNNING,
                message='Adding %s node(s) to cluster %s(%s)' %
                (body['node_count'], self.cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['cluster_name'] = self.cluster_name
            response_body['task_href'] = self.task_resource.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            result['body'] = self._to_message(e)
            LOGGER.error(traceback.format_exc())
        return result

    def create_nodes_thread(self):
        LOGGER.debug('about to add nodes to cluster with name: %s',
                     self.cluster_name)
        try:
            org_resource = self.client_tenant.get_org()
            org = Org(self.client_tenant, resource=org_resource)
            vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
            vapp = VApp(self.client_tenant, href=self.cluster['vapp_href'])
            template = self.get_template()
            self.update_task(
                TaskStatus.RUNNING,
                message='Creating %s node(s) for %s(%s)' %
                (self.body['node_count'], self.cluster_name, self.cluster_id))
            new_nodes = add_nodes(self.body['node_count'], template, TYPE_NODE,
                                  self.config, self.client_tenant, org, vdc,
                                  vapp, self.body)
            self.update_task(
                TaskStatus.RUNNING,
                message='Adding %s node(s) to %s(%s)' %
                (self.body['node_count'], self.cluster_name, self.cluster_id))
            target_nodes = []
            for spec in new_nodes['specs']:
                target_nodes.append(spec['target_vm_name'])
            vapp.reload()
            join_cluster(self.config, vapp, template, target_nodes)
            self.update_task(
                TaskStatus.SUCCESS,
                message='Added %s node(s) to cluster %s(%s)' %
                (self.body['node_count'], self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))

    def delete_nodes(self, headers, body):
        result = {'body': {}}
        self.cluster_name = body['name']
        LOGGER.debug('about to delete nodes from cluster with name: %s' %
                     body['name'])
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            if len(body['nodes']) < 1:
                raise Exception('Invalid list of nodes: %s.' % body['nodes'])
            for node in body['nodes']:
                if node.startswith(TYPE_MASTER):
                    raise Exception('Can\'t delete a master node: \'%s\'.' %
                                    node)
            self.tenant_info = self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster \'%s\' not found.' %
                                self.cluster_name)
            self.cluster = clusters[0]
            self.headers = headers
            self.body = body
            self.op = OP_DELETE_NODES
            self._connect_sysadmin()
            self.cluster_id = self.cluster['cluster_id']
            self.update_task(
                TaskStatus.RUNNING,
                message='Deleting %s node(s) from cluster %s(%s)' %
                (len(body['nodes']), self.cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['cluster_name'] = self.cluster_name
            response_body['task_href'] = self.task_resource.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            result['body'] = self._to_message(e)
            LOGGER.error(traceback.format_exc())
        return result

    def delete_nodes_thread(self):
        LOGGER.debug('about to delete nodes from cluster with name: %s',
                     self.cluster_name)
        try:
            vapp = VApp(self.client_tenant, href=self.cluster['vapp_href'])
            template = self.get_template()
            self.update_task(
                TaskStatus.RUNNING,
                message='Deleting %s node(s) from %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            delete_nodes_from_cluster(self.config, vapp, template,
                                      self.body['nodes'], self.body['force'])
            self.update_task(
                TaskStatus.RUNNING,
                message='Undeploying %s node(s) for %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            for vm_name in self.body['nodes']:
                vm = VM(self.client_tenant, resource=vapp.get_vm(vm_name))
                try:
                    task = vm.undeploy()
                    self.client_tenant.get_task_monitor().wait_for_status(task)
                except Exception as e:
                    LOGGER.warning('couldn\'t undeploy VM %s' % vm_name)
            self.update_task(
                TaskStatus.RUNNING,
                message='Deleting %s VM(s) for %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            task = vapp.delete_vms(self.body['nodes'])
            self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(
                TaskStatus.SUCCESS,
                message='Deleted %s node(s) to cluster %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))
コード例 #17
0
ファイル: login.py プロジェクト: tjecheva/vcd-cli
def login(ctx, user, host, password, api_version, org,
          verify_ssl_certs, disable_warnings, vdc, session_id,
          use_browser_session):
    """Login to vCloud Director

\b
    Login to a vCloud Director service.
\b
    Examples
        vcd login mysp.com org1 usr1
            Login to host 'mysp.com'.
\b
        vcd login test.mysp.com org1 usr1 -i -w
            Login to a host with self-signed SSL certificate.
\b
        vcd login mysp.com org1 usr1 --use-browser-session
            Login using active session from browser.
\b
        vcd login session list chrome
            List active session ids from browser.
\b
        vcd login mysp.com org1 usr1 \\
            --session-id ee968665bf3412d581bbc6192508eec4
            Login using active session id.
\b
    Environment Variables
        VCD_PASSWORD
            If this environment variable is set, the command will use its value
            as the password to login and will not ask for one. The --password
            option has precedence over the environment variable.

    """

    if not verify_ssl_certs:
        if disable_warnings:
            pass
        else:
            click.secho('InsecureRequestWarning: '
                        'Unverified HTTPS request is being made. '
                        'Adding certificate verification is strongly '
                        'advised.', fg='yellow', err=True)
        requests.packages.urllib3.disable_warnings()
    if host == 'session' and org == 'list':
        sessions = []
        if user == 'chrome':
            cookies = browsercookie.chrome()
            for c in cookies:
                if c.name == 'vcloud_session_id':
                    sessions.append({'host': c.domain, 'session_id': c.value})
        stdout(sessions, ctx)
        return

    client = Client(host,
                    api_version=api_version,
                    verify_ssl_certs=verify_ssl_certs,
                    log_file='vcd.log',
                    log_requests=True,
                    log_headers=True,
                    log_bodies=True
                    )
    try:
        if api_version is None:
            api_version = client.set_highest_supported_version()

        if session_id is not None or use_browser_session:
            if use_browser_session:
                browser_session_id = None
                cookies = browsercookie.chrome()
                for c in cookies:
                    if c.name == 'vcloud_session_id' and \
                       c.domain == host:
                        browser_session_id = c.value
                        break
                if browser_session_id is None:
                    raise Exception('Session not found in browser.')
                session_id = browser_session_id
            client.rehydrate_from_token(session_id)
        else:
            if password is None:
                password = click.prompt('Password', hide_input=True, type=str)
            client.set_credentials(BasicLoginCredentials(user, org, password))
        wkep = {}
        for endpoint in _WellKnownEndpoint:
            if endpoint in client._session_endpoints:
                wkep[endpoint.name] = client._session_endpoints[endpoint]
        profiles = Profiles.load()
        logged_in_org = client.get_org()
        org_href = logged_in_org.get('href')
        vdc_href = ''
        in_use_vdc = ''
        if vdc is None:
            for v in get_links(logged_in_org, media_type=EntityType.VDC.value):
                in_use_vdc = v.name
                vdc_href = v.href
                break
        else:
            for v in get_links(logged_in_org, media_type=EntityType.VDC.value):
                if vdc == v.name:
                    in_use_vdc = v.name
                    vdc_href = v.href
                    break
            if len(in_use_vdc) == 0:
                raise Exception('VDC not found')
        profiles.update(host,
                        org,
                        user,
                        client._session.headers['x-vcloud-authorization'],
                        api_version,
                        wkep,
                        verify_ssl_certs,
                        disable_warnings,
                        vdc=in_use_vdc,
                        org_href=org_href,
                        vdc_href=vdc_href,
                        log_request=profiles.get('log_request', default=False),
                        log_header=profiles.get('log_header', default=False),
                        log_body=profiles.get('log_body', default=False),
                        vapp='',
                        vapp_href='')
        alt_text = '%s logged in, org: \'%s\', vdc: \'%s\'' % \
                   (user, org, in_use_vdc)
        stdout({'user': user, 'org': org,
                'vdc': in_use_vdc, 'logged_in': True}, ctx, alt_text)
    except Exception as e:
        try:
            profiles = Profiles.load()
            profiles.set('token', '')
        except Exception:
            pass
        stderr(e, ctx)
コード例 #18
0
ファイル: login.py プロジェクト: vmware/vca-cli
def login(ctx, user, host, password, api_version, org, verify_ssl_certs,
          disable_warnings, vdc, session_id, use_browser_session):
    """Login to vCloud Director

\b
    Login to a vCloud Director service.
\b
    Examples
        vcd login mysp.com org1 usr1
            Login to host 'mysp.com'.
\b
        vcd login test.mysp.com org1 usr1 -i -w
            Login to a host with self-signed SSL certificate.
\b
        vcd login mysp.com org1 usr1 --use-browser-session
            Login using active session from browser.
\b
        vcd login session list chrome
            List active session ids from browser.
\b
        vcd login mysp.com org1 usr1 \\
            --session-id ee968665bf3412d581bbc6192508eec4
            Login using active session id.
\b
    Environment Variables
        VCD_PASSWORD
            If this environment variable is set, the command will use its value
            as the password to login and will not ask for one. The --password
            option has precedence over the environment variable.

    """

    if not verify_ssl_certs:
        if disable_warnings:
            pass
        else:
            click.secho(
                'InsecureRequestWarning: '
                'Unverified HTTPS request is being made. '
                'Adding certificate verification is strongly '
                'advised.',
                fg='yellow',
                err=True)
        requests.packages.urllib3.disable_warnings()
    if host == 'session' and org == 'list':
        sessions = []
        if user == 'chrome':
            cookies = browsercookie.chrome()
            for c in cookies:
                if c.name == 'vcloud_session_id':
                    sessions.append({'host': c.domain, 'session_id': c.value})
        stdout(sessions, ctx)
        return

    client = Client(
        host,
        api_version=api_version,
        verify_ssl_certs=verify_ssl_certs,
        log_file='vcd.log',
        log_requests=True,
        log_headers=True,
        log_bodies=True)
    try:
        if api_version is None:
            api_version = client.set_highest_supported_version()

        if session_id is not None or use_browser_session:
            if use_browser_session:
                browser_session_id = None
                cookies = browsercookie.chrome()
                for c in cookies:
                    if c.name == 'vcloud_session_id' and \
                       c.domain == host:
                        browser_session_id = c.value
                        break
                if browser_session_id is None:
                    raise Exception('Session not found in browser.')
                session_id = browser_session_id
            client.rehydrate_from_token(session_id)
        else:
            if password is None:
                password = click.prompt('Password', hide_input=True, type=str)
            client.set_credentials(BasicLoginCredentials(user, org, password))
        wkep = {}
        for endpoint in _WellKnownEndpoint:
            if endpoint in client._session_endpoints:
                wkep[endpoint.name] = client._session_endpoints[endpoint]
        profiles = Profiles.load()
        logged_in_org = client.get_org()
        org_href = logged_in_org.get('href')
        vdc_href = ''
        in_use_vdc = ''
        if vdc is None:
            for v in get_links(logged_in_org, media_type=EntityType.VDC.value):
                in_use_vdc = v.name
                vdc_href = v.href
                break
        else:
            for v in get_links(logged_in_org, media_type=EntityType.VDC.value):
                if vdc == v.name:
                    in_use_vdc = v.name
                    vdc_href = v.href
                    break
            if len(in_use_vdc) == 0:
                raise Exception('VDC not found')
        profiles.update(
            host,
            org,
            user,
            client._session.headers['x-vcloud-authorization'],
            api_version,
            wkep,
            verify_ssl_certs,
            disable_warnings,
            vdc=in_use_vdc,
            org_href=org_href,
            vdc_href=vdc_href,
            log_request=True,
            log_header=True,
            log_body=True,
            vapp='',
            vapp_href='')
        alt_text = '%s logged in, org: \'%s\', vdc: \'%s\'' % \
                   (user, org, in_use_vdc)
        stdout({
            'user': user,
            'org': org,
            'vdc': in_use_vdc,
            'logged_in': True
        }, ctx, alt_text)
    except Exception as e:
        try:
            profiles = Profiles.load()
            profiles.set('token', '')
        except Exception:
            pass
        stderr(e, ctx)
コード例 #19
0
def _override_client(ctx) -> None:
    """Replace the vcd client in ctx.obj with new one.

    New vcd client takes the CSE server_api_version as api_version param.
    Save profile also with 'cse_server_api_version' for subsequent commands.

    :param <click.core.Context> ctx: click context
    """
    profiles = Profiles.load()
    # if the key CSE_SERVER_RUNNING is not present in the profiles.yaml,
    # we make an assumption that CSE server is running
    is_cse_server_running = profiles.get(CSE_SERVER_RUNNING, default=True)
    cse_server_api_version = profiles.get(CSE_SERVER_API_VERSION)
    if not is_cse_server_running:
        CLIENT_LOGGER.debug(
            "CSE server not running as per profile, restricting CLI to only TKG operations."
        )  # noqa: E501
        restrict_cli_to_tkg_s_operations()
        ctx.obj['profiles'] = profiles
        return

    # Get server_api_version; save it in profiles if doesn't exist
    if not cse_server_api_version:
        try:
            system = syst.System(ctx.obj['client'])
            sys_info = system.get_info()

            is_pre_cse_3_1_server = False
            if CSE_SERVER_LEGACY_MODE not in sys_info or \
                    CSE_SERVER_SUPPORTED_API_VERSIONS not in sys_info:
                is_pre_cse_3_1_server = True

            if not is_pre_cse_3_1_server:
                is_cse_server_running_in_legacy_mode = \
                    sys_info.get(CSE_SERVER_LEGACY_MODE)
                cse_server_supported_api_versions = \
                    set(sys_info.get(CSE_SERVER_SUPPORTED_API_VERSIONS))
                cse_client_supported_api_versions = \
                    set(shared_constants.SUPPORTED_VCD_API_VERSIONS)

                common_supported_api_versions = \
                    list(cse_server_supported_api_versions.intersection(
                        cse_client_supported_api_versions))

                # ToDo: Instead of float use proper version comparison
                if is_cse_server_running_in_legacy_mode:
                    common_supported_api_versions = \
                        [float(x) for x in common_supported_api_versions
                            if float(x) < 35.0]
                else:
                    common_supported_api_versions = \
                        [float(x) for x in common_supported_api_versions
                            if float(x) >= 35.0]

                cse_server_api_version = \
                    str(max(common_supported_api_versions))
                CLIENT_LOGGER.debug(
                    f"Server api versions : {cse_server_supported_api_versions}, "  # noqa: E501
                    f"Client api versions : {cse_client_supported_api_versions}, "  # noqa: E501
                    f"Server in Legacy mode : {is_cse_server_running_in_legacy_mode}, "  # noqa: E501
                    f"Selected api version : {cse_server_api_version}.")
            else:
                cse_server_api_version = \
                    sys_info.get(CSE_SERVER_API_VERSION)
                CLIENT_LOGGER.debug(
                    "Pre CSE 3.1 server detected. Selected api version : "
                    f"{cse_server_api_version}.")

            profiles.set(CSE_SERVER_API_VERSION, cse_server_api_version)
            profiles.set(CSE_SERVER_RUNNING, True)
            profiles.save()
        except (requests.exceptions.Timeout, CseResponseError) as err:
            CLIENT_LOGGER.error(err, exc_info=True)
            CLIENT_LOGGER.debug(
                "Request to CSE server timed out. Restricting CLI to only TKG operations."
            )  # noqa: E501

            profiles.set(CSE_SERVER_RUNNING, False)
            restrict_cli_to_tkg_s_operations()
            ctx.obj['profiles'] = profiles
            profiles.save()
            return
    client = Client(profiles.get('host'),
                    api_version=cse_server_api_version,
                    verify_ssl_certs=profiles.get('verify'),
                    log_file='vcd.log',
                    log_requests=profiles.get('log_request'),
                    log_headers=profiles.get('log_header'),
                    log_bodies=profiles.get('log_body'))
    client.rehydrate_from_token(profiles.get('token'),
                                profiles.get('is_jwt_token'))  # noqa: E501
    ctx.obj['client'] = client
    ctx.obj['profiles'] = profiles
コード例 #20
0
class DefaultBroker(threading.Thread):
    def __init__(self, config):
        threading.Thread.__init__(self)
        self.config = config
        self.host = config['vcd']['host']
        self.username = config['vcd']['username']
        self.password = config['vcd']['password']
        self.version = config['vcd']['api_version']
        self.verify = config['vcd']['verify']
        self.log = config['vcd']['log']

    def _connect_sysadmin(self):
        if not self.verify:
            LOGGER.warning('InsecureRequestWarning: '
                           'Unverified HTTPS request is being made. '
                           'Adding certificate verification is strongly '
                           'advised.')
            requests.packages.urllib3.disable_warnings()
        self.client_sysadmin = Client(uri=self.host,
                                      api_version=self.version,
                                      verify_ssl_certs=self.verify,
                                      log_file='sysadmin.log',
                                      log_headers=True,
                                      log_bodies=True)
        self.client_sysadmin.set_credentials(
            BasicLoginCredentials(self.username, 'System', self.password))

    def _connect_tenant(self, headers):
        token = headers.get('x-vcloud-authorization')
        accept_header = headers.get('Accept')
        version = accept_header.split('version=')[1]
        self.client_tenant = Client(uri=self.host,
                                    api_version=version,
                                    verify_ssl_certs=self.verify,
                                    log_file='tenant.log',
                                    log_headers=True,
                                    log_bodies=True)
        session = self.client_tenant.rehydrate_from_token(token)
        return {
            'user_name':
            session.get('user'),
            'user_id':
            session.get('userId'),
            'org_name':
            session.get('org'),
            'org_href':
            self.client_tenant._get_wk_endpoint(
                _WellKnownEndpoint.LOGGED_IN_ORG)
        }

    def update_task(self, status, operation, message=None, error_message=None):
        if not hasattr(self, 'task'):
            self.task = Task(self.client_sysadmin)
        if message is None:
            message = OP_MESSAGE[operation]
        if hasattr(self, 't'):
            task_href = self.t.get('href')
        else:
            task_href = None
        self.t = self.task.update(status.value,
                                  'vcloud.cse',
                                  message,
                                  operation,
                                  '',
                                  None,
                                  'urn:cse:cluster:%s' % self.cluster_id,
                                  self.cluster_name,
                                  'application/vcloud.cse.cluster+xml',
                                  self.tenant_info['user_id'],
                                  self.tenant_info['user_name'],
                                  org_href=self.tenant_info['org_href'],
                                  task_href=task_href,
                                  error_message=error_message)

    def is_valid_name(self, name):
        """Validates that the cluster name against the pattern.

        """
        if len(name) > MAX_HOST_NAME_LENGTH:
            return False
        if name[-1] == '.':
            name = name[:-1]
        allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
        return all(allowed.match(x) for x in name.split("."))

    def get_template(self, name=None):
        if name is None:
            if 'template' in self.body and self.body['template'] is not None:
                name = self.body['template']
            else:
                name = self.config['broker']['default_template']
        for template in self.config['broker']['templates']:
            if template['name'] == name:
                return template
        raise Exception('Template %s not found' % name)

    def run(self):
        LOGGER.debug('thread started op=%s' % self.op)
        if self.op == OP_CREATE_CLUSTER:
            self.create_cluster_thread()
        elif self.op == OP_DELETE_CLUSTER:
            self.delete_cluster_thread()

    def list_clusters(self, headers, body):
        result = {}
        try:
            result['body'] = []
            result['status_code'] = OK
            self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant,
                                          get_leader_ip=True)
            result['body'] = clusters
        except Exception:
            LOGGER.error(traceback.format_exc())
            result['body'] = []
            result['status_code'] = INTERNAL_SERVER_ERROR
            result['message'] = traceback.format_exc()
        return result

    def create_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        cluster_name = body['name']
        vdc_name = body['vdc']
        node_count = body['node_count']
        LOGGER.debug('about to create cluster %s on %s with %s nodes, sp=%s',
                     cluster_name, vdc_name, node_count,
                     body['storage_profile'])
        result['body'] = {'message': 'can\'t create cluster %s' % cluster_name}
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            if not self.is_valid_name(cluster_name):
                raise Exception('Invalid cluster name')
            self.tenant_info = self._connect_tenant(headers)
            self.headers = headers
            self.body = body
            self.cluster_name = cluster_name
            self.cluster_id = str(uuid.uuid4())
            self.op = OP_CREATE_CLUSTER
            self._connect_sysadmin()
            self.update_task(TaskStatus.RUNNING,
                             self.op,
                             message='Creating cluster %s(%s)' %
                             (cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['name'] = self.cluster_name
            response_body['cluster_id'] = self.cluster_id
            response_body['task_href'] = self.t.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            result['body'] = {'message': e.message}
            LOGGER.error(traceback.format_exc())
        return result

    def create_cluster_thread(self):
        network_name = self.body['network']
        try:
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 0:
                raise Exception('Cluster already exists.')
            org_resource = self.client_tenant.get_org()
            org = Org(self.client_tenant, resource=org_resource)
            vdc_resource = org.get_vdc(self.body['vdc'])
            vdc = VDC(self.client_tenant, resource=vdc_resource)
            template = self.get_template()
            self.update_task(TaskStatus.RUNNING,
                             self.op,
                             message='Creating cluster vApp %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp_resource = vdc.create_vapp(self.cluster_name,
                                            description='cluster %s' %
                                            self.cluster_name,
                                            network=network_name,
                                            fence_mode='bridged')
            t = self.client_tenant.get_task_monitor().wait_for_status(
                task=vapp_resource.Tasks.Task[0],
                timeout=60,
                poll_frequency=2,
                fail_on_status=None,
                expected_target_statuses=[
                    TaskStatus.SUCCESS, TaskStatus.ABORTED, TaskStatus.ERROR,
                    TaskStatus.CANCELED
                ],
                callback=None)
            assert t.get('status').lower() == TaskStatus.SUCCESS.value
            tags = {}
            tags['cse.cluster.id'] = self.cluster_id
            tags['cse.version'] = pkg_resources.require(
                'container-service-extension')[0].version
            tags['cse.template'] = template['name']
            vapp = VApp(self.client_tenant, href=vapp_resource.get('href'))
            for k, v in tags.items():
                t = vapp.set_metadata('GENERAL', 'READWRITE', k, v)
                self.client_tenant.get_task_monitor().\
                    wait_for_status(
                        task=t,
                        timeout=600,
                        poll_frequency=5,
                        fail_on_status=None,
                        expected_target_statuses=[TaskStatus.SUCCESS],
                        callback=None)
            self.update_task(TaskStatus.RUNNING,
                             self.op,
                             message='Creating master node for %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp.reload()
            add_nodes(1,
                      template,
                      TYPE_MASTER,
                      self.config,
                      self.client_tenant,
                      org,
                      vdc,
                      vapp,
                      self.body,
                      wait=True)

            self.update_task(TaskStatus.RUNNING,
                             self.op,
                             message='Initializing cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))

            vapp.reload()
            init_cluster(self.config, vapp, template)

            master_ip = get_master_ip(self.config, vapp, template)
            t = vapp.set_metadata('GENERAL', 'READWRITE', 'cse.master.ip',
                                  master_ip)
            self.client_tenant.get_task_monitor().\
                wait_for_status(
                    task=t,
                    timeout=600,
                    poll_frequency=5,
                    fail_on_status=None,
                    expected_target_statuses=[TaskStatus.SUCCESS],
                    callback=None)

            if self.body['node_count'] > 0:

                self.update_task(TaskStatus.RUNNING,
                                 self.op,
                                 message='Creating %s node(s) for %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                add_nodes(self.body['node_count'],
                          template,
                          TYPE_NODE,
                          self.config,
                          self.client_tenant,
                          org,
                          vdc,
                          vapp,
                          self.body,
                          wait=True)
                self.update_task(TaskStatus.RUNNING,
                                 self.op,
                                 message='Adding %s node(s) to %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                vapp.reload()
                join_cluster(self.config, vapp, template)

            self.update_task(TaskStatus.SUCCESS,
                             self.op,
                             message='Created cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))

        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, self.op, error_message=str(e))

    def delete_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        LOGGER.debug('about to delete cluster with name: %s' % body['name'])
        result['status_code'] = INTERNAL_SERVER_ERROR
        try:
            self.cluster_name = body['name']
            self.tenant_info = self._connect_tenant(headers)
            self.headers = headers
            self.body = body
            self.op = OP_DELETE_CLUSTER
            self._connect_sysadmin()
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster %s not found.' % self.cluster_name)
            self.cluster = clusters[0]
            self.cluster_id = self.cluster['cluster_id']

            self.update_task(TaskStatus.RUNNING,
                             self.op,
                             message='Deleting cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            self.daemon = True
            self.start()
            response_body = {}
            response_body['cluster_name'] = self.cluster_name
            response_body['task_href'] = self.t.get('href')
            result['body'] = response_body
            result['status_code'] = ACCEPTED
        except Exception as e:
            if hasattr(e, 'message'):
                result['body'] = {'message': e.message}
            else:
                result['body'] = {'message': str(e)}
            LOGGER.error(traceback.format_exc())
        return result

    def delete_cluster_thread(self):
        LOGGER.debug('about to delete cluster with name: %s',
                     self.cluster_name)
        try:
            vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
            delete_task = vdc.delete_vapp(self.cluster['name'], force=True)
            self.client_tenant.get_task_monitor().\
                wait_for_status(
                    task=delete_task,
                    timeout=600,
                    poll_frequency=5,
                    fail_on_status=None,
                    expected_target_statuses=[TaskStatus.SUCCESS],
                    callback=None)
            self.update_task(TaskStatus.SUCCESS,
                             self.op,
                             message='Deleted cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(self.cluster_name,
                             self.cluster_id,
                             TaskStatus.ERROR,
                             self.op,
                             error_message=str(e))

    def get_cluster_config(self, cluster_name, headers):
        result = {}
        try:
            self._connect_tenant(headers)
            clusters = load_from_metadata(self.client_tenant,
                                          name=cluster_name)
            if len(clusters) != 1:
                raise Exception('Cluster \'%s\' not found' % cluster_name)
            vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
            template = self.get_template(name=clusters[0]['template'])
            result['body'] = get_cluster_config(self.config, vapp,
                                                template['admin_password'])
            result['status_code'] = OK
        except Exception as e:
            result['body'] = str(e)
            result['status_code'] = INTERNAL_SERVER_ERROR
        return result
コード例 #21
0
class DefaultBroker(threading.Thread):
    def __init__(self, config):
        threading.Thread.__init__(self)
        self.config = config
        self.host = config['vcd']['host']
        self.username = config['vcd']['username']
        self.password = config['vcd']['password']
        self.version = config['vcd']['api_version']
        self.verify = config['vcd']['verify']
        self.log = config['vcd']['log']

    def _connect_sysadmin(self):
        if not self.verify:
            LOGGER.warning('InsecureRequestWarning: '
                           'Unverified HTTPS request is being made. '
                           'Adding certificate verification is strongly '
                           'advised.')
            requests.packages.urllib3.disable_warnings()
        self.client_sysadmin = Client(uri=self.host,
                                      api_version=self.version,
                                      verify_ssl_certs=self.verify,
                                      log_headers=True,
                                      log_bodies=True)
        credentials = BasicLoginCredentials(self.username, SYSTEM_ORG_NAME,
                                            self.password)
        self.client_sysadmin.set_credentials(credentials)

    def _connect_tenant(self, headers):
        token = headers.get('x-vcloud-authorization')
        accept_header = headers.get('Accept')
        version = accept_header.split('version=')[1]
        self.client_tenant = Client(uri=self.host,
                                    api_version=version,
                                    verify_ssl_certs=self.verify,
                                    log_headers=True,
                                    log_bodies=True)
        session = self.client_tenant.rehydrate_from_token(token)
        return {
            'user_name':
            session.get('user'),
            'user_id':
            session.get('userId'),
            'org_name':
            session.get('org'),
            'org_href':
            self.client_tenant._get_wk_endpoint(
                _WellKnownEndpoint.LOGGED_IN_ORG)
        }

    def _to_message(self, e):
        if hasattr(e, 'message'):
            return {'message': e.message}
        else:
            return {'message': str(e)}

    def update_task(self, status, message=None, error_message=None):
        if not hasattr(self, 'task'):
            self.task = Task(self.client_sysadmin)
        if message is None:
            message = OP_MESSAGE[self.op]
        if hasattr(self, 'task_resource'):
            task_href = self.task_resource.get('href')
        else:
            task_href = None
        self.task_resource = self.task.update(
            status.value,
            'vcloud.cse',
            message,
            self.op,
            '',
            None,
            'urn:cse:cluster:%s' % self.cluster_id,
            self.cluster_name,
            'application/vcloud.cse.cluster+xml',
            self.tenant_info['user_id'],
            self.tenant_info['user_name'],
            org_href=self.tenant_info['org_href'],
            task_href=task_href,
            error_message=error_message)

    def is_valid_name(self, name):
        """Validate that the cluster name against the pattern."""
        if len(name) > MAX_HOST_NAME_LENGTH:
            return False
        if name[-1] == '.':
            name = name[:-1]
        allowed = re.compile("(?!-)[A-Z\d-]{1,63}(?<!-)$", re.IGNORECASE)
        return all(allowed.match(x) for x in name.split("."))

    def get_template(self, name=None):
        if name is None:
            if 'template' in self.body and self.body['template'] is not None:
                name = self.body['template']
            else:
                name = self.config['broker']['default_template']
        for template in self.config['broker']['templates']:
            if template['name'] == name:
                return template
        raise Exception('Template %s not found' % name)

    def run(self):
        LOGGER.debug('thread started op=%s' % self.op)
        if self.op == OP_CREATE_CLUSTER:
            self.create_cluster_thread()
        elif self.op == OP_DELETE_CLUSTER:
            self.delete_cluster_thread()
        elif self.op == OP_CREATE_NODES:
            self.create_nodes_thread()
        elif self.op == OP_DELETE_NODES:
            self.delete_nodes_thread()

    @exception_handler
    def list_clusters(self, headers, body):
        result = {}
        result['body'] = []
        result['status_code'] = OK
        self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant)
        result['body'] = clusters
        return result

    @exception_handler
    def get_cluster_info(self, name, headers, body):
        """Get the info of the cluster.

        :param cluster_name: (str): Name of the cluster
        :param headers: (str): Request headers

        :return: (dict): Info of the cluster.
        """

        result = {}
        result['body'] = []
        result['status_code'] = OK
        self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant, name=name)
        if len(clusters) == 0:
            raise CseServerError('Cluster \'%s\' not found.' % name)
        vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
        vms = vapp.get_all_vms()
        for vm in vms:
            node_info = {'name': vm.get('name'), 'ipAddress': ''}
            try:
                node_info['ipAddress'] = vapp.get_primary_ip(vm.get('name'))
            except Exception:
                LOGGER.debug('cannot get ip address for node %s' %
                             vm.get('name'))
            if vm.get('name').startswith(TYPE_MASTER):
                clusters[0].get('master_nodes').append(node_info)
            elif vm.get('name').startswith(TYPE_NODE):
                clusters[0].get('nodes').append(node_info)
            elif vm.get('name').startswith(TYPE_NFS):
                clusters[0].get('nfs_nodes').append(node_info)
        result['body'] = clusters[0]
        return result

    @exception_handler
    def get_node_info(self, cluster_name, node_name, headers):
        """Get the info of a given node in the cluster.

        :param cluster_name: (str): Name of the cluster
        :param node_name: (str): Name of the node
        :param headers: (str): Request headers

        :return: (dict): Info of the node.
        """
        result = {}

        result['body'] = []
        result['status_code'] = OK
        self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant, name=cluster_name)
        if len(clusters) == 0:
            raise CseServerError('Cluster \'%s\' not found.' % cluster_name)
        vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
        vms = vapp.get_all_vms()
        node_info = None
        for vm in vms:
            if (node_name == vm.get('name')):
                node_info = {
                    'name': vm.get('name'),
                    'numberOfCpus': '',
                    'memoryMB': '',
                    'status': VCLOUD_STATUS_MAP.get(int(vm.get('status'))),
                    'ipAddress': ''
                }
                if hasattr(vm, 'VmSpecSection'):
                    node_info['numberOfCpus'] = vm.VmSpecSection.NumCpus.text
                    node_info[
                        'memoryMB'] = \
                        vm.VmSpecSection.MemoryResourceMb.Configured.text
                try:
                    node_info['ipAddress'] = vapp.get_primary_ip(
                        vm.get('name'))
                except Exception:
                    LOGGER.debug('cannot get ip address '
                                 'for node %s' % vm.get('name'))
                if vm.get('name').startswith(TYPE_MASTER):
                    node_info['node_type'] = 'master'
                elif vm.get('name').startswith(TYPE_NODE):
                    node_info['node_type'] = 'node'
                elif vm.get('name').startswith(TYPE_NFS):
                    node_info['node_type'] = 'nfsd'
                    exports = self._get_nfs_exports(node_info['ipAddress'],
                                                    vapp, vm)
                    node_info['exports'] = exports
        if node_info is None:
            raise CseServerError('Node \'%s\' not found in cluster \'%s\'' %
                                 (node_name, cluster_name))
        result['body'] = node_info
        return result

    def _get_nfs_exports(self, ip, vapp, node):
        """Get the exports from remote NFS server (helper method).

        :param ip: (str): IP address of the NFS server
        :param vapp: (pyvcloud.vcd.vapp.VApp): The vApp or cluster
         to which node belongs
        :param node: (str): IP address of the NFS server
        :param node: (`lxml.objectify.StringElement`) object
        representing the vm resource.

        :return: (List): List of exports
        """
        # TODO(right template) find a right way to retrieve
        # the template from which nfs node was created.
        template = self.config['broker']['templates'][0]
        script = '#!/usr/bin/env bash\nshowmount -e %s' % ip
        result = execute_script_in_nodes(self.config,
                                         vapp,
                                         template['admin_password'],
                                         script,
                                         nodes=[node],
                                         check_tools=False)
        lines = result[0][1].content.decode().split('\n')
        exports = []
        for index in range(1, len(lines) - 1):
            export = lines[index].strip().split()[0]
            exports.append(export)
        return exports

    @exception_handler
    def create_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        cluster_name = body['name']
        vdc_name = body['vdc']
        node_count = body['node_count']
        LOGGER.debug('about to create cluster %s on %s with %s nodes, sp=%s',
                     cluster_name, vdc_name, node_count,
                     body['storage_profile'])
        result['body'] = {
            'message': 'can\'t create cluster \'%s\'' % cluster_name
        }

        if not self.is_valid_name(cluster_name):
            raise CseServerError(f"Invalid cluster name \'{cluster_name}\'")
        self.tenant_info = self._connect_tenant(headers)
        self.headers = headers
        self.body = body
        self.cluster_name = cluster_name
        self.cluster_id = str(uuid.uuid4())
        self.op = OP_CREATE_CLUSTER
        self._connect_sysadmin()
        self.update_task(TaskStatus.RUNNING,
                         message='Creating cluster %s(%s)' %
                         (cluster_name, self.cluster_id))
        self.daemon = True
        self.start()
        response_body = {}
        response_body['name'] = self.cluster_name
        response_body['cluster_id'] = self.cluster_id
        response_body['task_href'] = self.task_resource.get('href')
        result['body'] = response_body
        result['status_code'] = ACCEPTED
        return result

    @rollback
    def create_cluster_thread(self):
        network_name = self.body['network']
        try:
            clusters = load_from_metadata(self.client_tenant,
                                          name=self.cluster_name)
            if len(clusters) != 0:
                raise ClusterAlreadyExistsError(
                    f'Cluster {self.cluster_name} already exists.')
            org_resource = self.client_tenant.get_org()
            org = Org(self.client_tenant, resource=org_resource)
            vdc_resource = org.get_vdc(self.body['vdc'])
            vdc = VDC(self.client_tenant, resource=vdc_resource)
            template = self.get_template()
            self.update_task(TaskStatus.RUNNING,
                             message='Creating cluster vApp %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            try:
                vapp_resource = vdc.create_vapp(self.cluster_name,
                                                description='cluster %s' %
                                                self.cluster_name,
                                                network=network_name,
                                                fence_mode='bridged')
            except Exception as e:
                raise ClusterOperationError('Error while creating vApp:',
                                            str(e))

            self.client_tenant.get_task_monitor().wait_for_status(
                vapp_resource.Tasks.Task[0])
            tags = {}
            tags['cse.cluster.id'] = self.cluster_id
            tags['cse.version'] = pkg_resources.require(
                'container-service-extension')[0].version
            tags['cse.template'] = template['name']
            vapp = VApp(self.client_tenant, href=vapp_resource.get('href'))
            for k, v in tags.items():
                task = vapp.set_metadata('GENERAL', 'READWRITE', k, v)
                self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(TaskStatus.RUNNING,
                             message='Creating master node for %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp.reload()

            try:
                add_nodes(1, template, TYPE_MASTER, self.config,
                          self.client_tenant, org, vdc, vapp, self.body)
            except Exception as e:
                raise MasterNodeCreationError(
                    "Error while adding master node:", str(e))

            self.update_task(TaskStatus.RUNNING,
                             message='Initializing cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
            vapp.reload()
            init_cluster(self.config, vapp, template)
            master_ip = get_master_ip(self.config, vapp, template)
            task = vapp.set_metadata('GENERAL', 'READWRITE', 'cse.master.ip',
                                     master_ip)
            self.client_tenant.get_task_monitor().wait_for_status(task)
            if self.body['node_count'] > 0:
                self.update_task(TaskStatus.RUNNING,
                                 message='Creating %s node(s) for %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                try:
                    add_nodes(self.body['node_count'], template, TYPE_NODE,
                              self.config, self.client_tenant, org, vdc, vapp,
                              self.body)
                except Exception as e:
                    raise WorkerNodeCreationError(
                        "Error while creating worker node:", str(e))

                self.update_task(TaskStatus.RUNNING,
                                 message='Adding %s node(s) to %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                vapp.reload()
                join_cluster(self.config, vapp, template)
            if self.body['enable_nfs']:
                self.update_task(TaskStatus.RUNNING,
                                 message='Creating NFS node for %s(%s)' %
                                 (self.cluster_name, self.cluster_id))
                try:
                    add_nodes(1, template, TYPE_NFS, self.config,
                              self.client_tenant, org, vdc, vapp, self.body)
                except Exception as e:
                    raise NFSNodeCreationError(
                        "Error while creating NFS node:", str(e))

            self.update_task(TaskStatus.SUCCESS,
                             message='Created cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
        except (MasterNodeCreationError, WorkerNodeCreationError,
                NFSNodeCreationError, ClusterJoiningError,
                ClusterInitializationError, ClusterOperationError) as e:
            LOGGER.error(traceback.format_exc())
            error_obj = error_to_json(e)
            self.update_task(
                TaskStatus.ERROR,
                error_message=error_obj[ERROR_MESSAGE][ERROR_DESCRIPTION])
            raise e
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            error_obj = error_to_json(e)
            self.update_task(
                TaskStatus.ERROR,
                error_message=error_obj[ERROR_MESSAGE][ERROR_DESCRIPTION])

    @exception_handler
    def delete_cluster(self, headers, body):
        result = {}
        result['body'] = {}
        LOGGER.debug('about to delete cluster with name: %s' % body['name'])
        result['status_code'] = INTERNAL_SERVER_ERROR

        self.cluster_name = body['name']
        self.tenant_info = self._connect_tenant(headers)
        self.headers = headers
        self.body = body
        self.op = OP_DELETE_CLUSTER
        self._connect_sysadmin()
        clusters = load_from_metadata(self.client_tenant,
                                      name=self.cluster_name)
        if len(clusters) != 1:
            raise CseServerError('Cluster %s not found.' % self.cluster_name)
        self.cluster = clusters[0]
        self.cluster_id = self.cluster['cluster_id']
        self.update_task(TaskStatus.RUNNING,
                         message='Deleting cluster %s(%s)' %
                         (self.cluster_name, self.cluster_id))
        self.daemon = True
        self.start()
        response_body = {}
        response_body['cluster_name'] = self.cluster_name
        response_body['task_href'] = self.task_resource.get('href')
        result['body'] = response_body
        result['status_code'] = ACCEPTED
        return result

    def delete_cluster_thread(self):
        LOGGER.debug('about to delete cluster with name: %s',
                     self.cluster_name)
        try:
            vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
            task = vdc.delete_vapp(self.cluster['name'], force=True)
            self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(TaskStatus.SUCCESS,
                             message='Deleted cluster %s(%s)' %
                             (self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))

    @exception_handler
    def get_cluster_config(self, cluster_name, headers):
        result = {}
        self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant, name=cluster_name)
        if len(clusters) != 1:
            raise CseServerError('Cluster \'%s\' not found' % cluster_name)
        vapp = VApp(self.client_tenant, href=clusters[0]['vapp_href'])
        template = self.get_template(name=clusters[0]['template'])
        result['body'] = get_cluster_config(self.config, vapp,
                                            template['admin_password'])
        result['status_code'] = OK
        return result

    @exception_handler
    def create_nodes(self, headers, body):
        result = {'body': {}}
        self.cluster_name = body['name']
        LOGGER.debug('about to add %s nodes to cluster %s on VDC %s, sp=%s',
                     body['node_count'], self.cluster_name, body['vdc'],
                     body['storage_profile'])
        if body['node_count'] < 1:
            raise CseServerError('Invalid node count: %s.' %
                                 body['node_count'])
        self.tenant_info = self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant,
                                      name=self.cluster_name)
        if len(clusters) != 1:
            raise CseServerError('Cluster \'%s\' not found.' %
                                 self.cluster_name)
        self.cluster = clusters[0]
        self.headers = headers
        self.body = body
        self.op = OP_CREATE_NODES
        self._connect_sysadmin()
        self.cluster_id = self.cluster['cluster_id']
        self.update_task(
            TaskStatus.RUNNING,
            message='Adding %s node(s) to cluster %s(%s)' %
            (body['node_count'], self.cluster_name, self.cluster_id))
        self.daemon = True
        self.start()
        response_body = {}
        response_body['cluster_name'] = self.cluster_name
        response_body['task_href'] = self.task_resource.get('href')
        result['body'] = response_body
        result['status_code'] = ACCEPTED
        return result

    @rollback
    def create_nodes_thread(self):
        LOGGER.debug('about to add nodes to cluster with name: %s',
                     self.cluster_name)
        try:
            org_resource = self.client_tenant.get_org()
            org = Org(self.client_tenant, resource=org_resource)
            vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
            vapp = VApp(self.client_tenant, href=self.cluster['vapp_href'])
            template = self.get_template()
            self.update_task(
                TaskStatus.RUNNING,
                message='Creating %s node(s) for %s(%s)' %
                (self.body['node_count'], self.cluster_name, self.cluster_id))
            new_nodes = add_nodes(self.body['node_count'], template,
                                  self.body['node_type'], self.config,
                                  self.client_tenant, org, vdc, vapp,
                                  self.body)
            if self.body['node_type'] == TYPE_NFS:
                self.update_task(TaskStatus.SUCCESS,
                                 message='Created %s node(s) for %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
            elif self.body['node_type'] == TYPE_NODE:
                self.update_task(TaskStatus.RUNNING,
                                 message='Adding %s node(s) to %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
                target_nodes = []
                for spec in new_nodes['specs']:
                    target_nodes.append(spec['target_vm_name'])
                vapp.reload()
                join_cluster(self.config, vapp, template, target_nodes)
                self.update_task(TaskStatus.SUCCESS,
                                 message='Added %s node(s) to cluster %s(%s)' %
                                 (self.body['node_count'], self.cluster_name,
                                  self.cluster_id))
        except NodeCreationError as e:
            error_obj = error_to_json(e)
            LOGGER.error(traceback.format_exc())
            self.update_task(
                TaskStatus.ERROR,
                error_message=error_obj[ERROR_MESSAGE][ERROR_DESCRIPTION])
            raise
        except Exception as e:
            error_obj = error_to_json(e)
            LOGGER.error(traceback.format_exc())
            self.update_task(
                TaskStatus.ERROR,
                error_message=error_obj[ERROR_MESSAGE][ERROR_DESCRIPTION])

    @exception_handler
    def delete_nodes(self, headers, body):
        result = {'body': {}}
        self.cluster_name = body['name']
        LOGGER.debug('about to delete nodes from cluster with name: %s' %
                     body['name'])

        if len(body['nodes']) < 1:
            raise CseServerError('Invalid list of nodes: %s.' % body['nodes'])
        for node in body['nodes']:
            if node.startswith(TYPE_MASTER):
                raise CseServerError('Can\'t delete a master node: \'%s\'.' %
                                     node)
        self.tenant_info = self._connect_tenant(headers)
        clusters = load_from_metadata(self.client_tenant,
                                      name=self.cluster_name)
        if len(clusters) != 1:
            raise CseServerError('Cluster \'%s\' not found.' %
                                 self.cluster_name)
        self.cluster = clusters[0]
        self.headers = headers
        self.body = body
        self.op = OP_DELETE_NODES
        self._connect_sysadmin()
        self.cluster_id = self.cluster['cluster_id']
        self.update_task(
            TaskStatus.RUNNING,
            message='Deleting %s node(s) from cluster %s(%s)' %
            (len(body['nodes']), self.cluster_name, self.cluster_id))
        self.daemon = True
        self.start()
        response_body = {}
        response_body['cluster_name'] = self.cluster_name
        response_body['task_href'] = self.task_resource.get('href')
        result['body'] = response_body
        result['status_code'] = ACCEPTED
        return result

    def delete_nodes_thread(self):
        LOGGER.debug('about to delete nodes from cluster with name: %s',
                     self.cluster_name)
        try:
            vapp = VApp(self.client_tenant, href=self.cluster['vapp_href'])
            template = self.get_template()
            self.update_task(
                TaskStatus.RUNNING,
                message='Deleting %s node(s) from %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            try:
                delete_nodes_from_cluster(self.config, vapp, template,
                                          self.body['nodes'],
                                          self.body['force'])
            except Exception:
                LOGGER.error("Couldn't delete node %s from cluster:%s" %
                             (self.body['nodes'], self.cluster_name))
            self.update_task(
                TaskStatus.RUNNING,
                message='Undeploying %s node(s) for %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            for vm_name in self.body['nodes']:
                vm = VM(self.client_tenant, resource=vapp.get_vm(vm_name))
                try:
                    task = vm.undeploy()
                    self.client_tenant.get_task_monitor().wait_for_status(task)
                except Exception as e:
                    LOGGER.warning('couldn\'t undeploy VM %s' % vm_name)
            self.update_task(
                TaskStatus.RUNNING,
                message='Deleting %s VM(s) for %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
            task = vapp.delete_vms(self.body['nodes'])
            self.client_tenant.get_task_monitor().wait_for_status(task)
            self.update_task(
                TaskStatus.SUCCESS,
                message='Deleted %s node(s) to cluster %s(%s)' %
                (len(self.body['nodes']), self.cluster_name, self.cluster_id))
        except Exception as e:
            LOGGER.error(traceback.format_exc())
            self.update_task(TaskStatus.ERROR, error_message=str(e))

    def node_rollback(self, node_list):
        """Implements rollback for node creation failure

        :param list node_list: faulty nodes to be deleted
        """
        LOGGER.info('About to rollback nodes from cluster with name: %s' %
                    self.cluster_name)
        LOGGER.info('Node list to be deleted:%s' % node_list)
        vapp = VApp(self.client_tenant, href=self.cluster['vapp_href'])
        template = self.get_template()
        try:
            delete_nodes_from_cluster(self.config,
                                      vapp,
                                      template,
                                      node_list,
                                      force=True)
        except Exception:
            LOGGER.warning("Couldn't delete node %s from cluster:%s" %
                           (node_list, self.cluster_name))
        for vm_name in node_list:
            vm = VM(self.client_tenant, resource=vapp.get_vm(vm_name))
            try:
                vm.undeploy()
            except Exception:
                LOGGER.warning("Couldn't undeploy VM %s" % vm_name)
        vapp.delete_vms(node_list)
        LOGGER.info('Successfully deleted nodes: %s' % node_list)

    def cluster_rollback(self):
        """Implements rollback for cluster creation failure"""
        LOGGER.info('About to rollback cluster with name: %s' %
                    self.cluster_name)
        clusters = load_from_metadata(self.client_tenant,
                                      name=self.cluster_name)
        if len(clusters) != 1:
            LOGGER.debug('Cluster %s not found.' % self.cluster_name)
            return
        self.cluster = clusters[0]
        vdc = VDC(self.client_tenant, href=self.cluster['vdc_href'])
        vdc.delete_vapp(self.cluster['name'], force=True)
        LOGGER.info('Successfully deleted cluster: %s' % self.cluster_name)