Exemplo n.º 1
0
 def _uploadimage(self, pool, origin, directory, verbose=False, temp=False):
     if verbose:
         pprint("Uploading %s to %s/%s" % (origin, pool, directory))
     si = self.si
     rootFolder = self.rootFolder
     datastore = find(si, rootFolder, vim.Datastore, pool)
     if not datastore:
         return {'result': 'failure', 'reason': "Pool %s not found" % pool}
     destination = os.path.basename(origin)
     if temp:
         destination = "temp-%s" % destination
     url = "https://%s:443/folder/%s/%s?dcPath=%s&dsName=%s" % (self.vcip, directory, destination, self.dc.name,
                                                                pool)
     client_cookie = si._stub.cookie
     cookie_name = client_cookie.split("=", 1)[0]
     cookie_value = client_cookie.split("=", 1)[1].split(";", 1)[0]
     cookie_path = client_cookie.split("=", 1)[1].split(";", 1)[1].split(";", 1)[0].lstrip()
     cookie_text = " " + cookie_value + "; $" + cookie_path
     cookie = {cookie_name: cookie_text}
     headers = {'Content-Type': 'application/octet-stream'}
     with open(origin, "rb") as f:
         if hasattr(requests.packages.urllib3, 'disable_warnings'):
             requests.packages.urllib3.disable_warnings()
             r = requests.put(url, data=f, headers=headers, cookies=cookie, verify=False)
             if verbose:
                 if r.status_code not in [200, 201]:
                     error(r.status_code, r.text)
                 else:
                     success("Successfull upload of %s to %s" % (origin, pool))
Exemplo n.º 2
0
Arquivo: kbmc.py Projeto: yuvalk/kcli
 def power_on(self):
     result = self.k.start(self.name)
     if result['result'] == 'success':
         self.powerstate = 'on'
         success('%s powered on!' % self.name)
     else:
         error('%s not powered on because %s' %
               (self.name, result['reason']))
Exemplo n.º 3
0
Arquivo: kbmc.py Projeto: yuvalk/kcli
 def power_off(self):
     result = self.k.stop(self.name)
     if result['result'] == 'success':
         success('%s powered off!' % self.name)
         self.powerstate = 'off'
     else:
         error('%s not powered off because %s' %
               (self.name, result['reason']))
Exemplo n.º 4
0
def create(config, plandir, cluster, overrides, dnsconfig=None):
    k = config.k
    data = {'kubetype': 'kind'}
    data.update(overrides)
    if 'keys' not in overrides and get_ssh_pub_key() is None:
        error(
            "No usable public key found, which is required for the deployment")
        sys.exit(1)
    data['cluster'] = overrides.get(
        'cluster', cluster if cluster is not None else 'testk')
    plan = cluster if cluster is not None else data['cluster']
    data['kube'] = data['cluster']
    masters = data.get('masters', 1)
    if masters == 0:
        error("Invalid number of masters")
        sys.exit(1)
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    if os.path.exists(clusterdir):
        error("Please remove existing directory %s first..." % clusterdir)
        sys.exit(1)
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        os.mkdir("%s/auth" % clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam = overrides.copy()
            installparam['plan'] = plan
            installparam['kubetype'] = 'kind'
            yaml.safe_dump(installparam,
                           p,
                           default_flow_style=False,
                           encoding='utf-8',
                           allow_unicode=True)
    result = config.plan(plan,
                         inputfile='%s/kcli_plan.yml' % plandir,
                         overrides=data)
    if result['result'] != 'success':
        sys.exit(1)
    kindnode = "%s-kind" % cluster
    kindnodeip = "%s-kind" % cluster
    kindnodeip, kindnodevmport = _ssh_credentials(k, kindnode)[1:]
    source, destination = data['KUBECONFIG'], "%s/auth/kubeconfig" % clusterdir
    scpcmd = scp(kindnode,
                 ip=kindnodeip,
                 user='******',
                 source=source,
                 destination=destination,
                 tunnel=config.tunnel,
                 tunnelhost=config.tunnelhost,
                 tunnelport=config.tunnelport,
                 tunneluser=config.tunneluser,
                 download=True,
                 insecure=True,
                 vmport=kindnodevmport)
    os.system(scpcmd)
    success("Kubernetes cluster %s deployed!!!" % cluster)
    info2("export KUBECONFIG=$HOME/.kcli/clusters/%s/auth/kubeconfig" %
          cluster)
    info2("export PATH=$PWD:$PATH")
Exemplo n.º 5
0
def create(config, plandir, cluster, overrides):
    platform = config.type
    data = {'kubetype': 'k3s', 'sdn': 'flannel'}
    data.update(overrides)
    data['cluster'] = overrides.get(
        'cluster', cluster if cluster is not None else 'testk')
    plan = cluster if cluster is not None else data['cluster']
    data['kube'] = data['cluster']
    masters = data.get('masters', 1)
    network = data.get('network', 'default')
    sdn = None if 'sdn' in overrides and overrides[
        'sdn'] is None else data.get('sdn')
    token = data.get('token', 'supersecret')
    api_ip = data.get('api_ip')
    if masters > 1:
        if platform in cloudplatforms:
            domain = data.get('domain', 'karmalabs.com')
            api_ip = "%s-master.%s" % (cluster, domain)
        elif api_ip is None:
            if network == 'default' and platform == 'kvm':
                warning("Using 192.168.122.253 as api_ip")
                data['api_ip'] = "192.168.122.253"
                api_ip = "192.168.122.253"
            elif platform == 'kubevirt':
                selector = {'kcli/plan': plan, 'kcli/role': 'master'}
                api_ip = config.k.create_service("%s-api" % cluster,
                                                 config.k.namespace,
                                                 selector,
                                                 _type="LoadBalancer",
                                                 ports=[6443])
                if api_ip is None:
                    sys.exit(1)
                else:
                    pprint("Using api_ip %s" % api_ip)
                    data['api_ip'] = api_ip
            else:
                error("You need to define api_ip in your parameters file")
                sys.exit(1)
        if data.get('virtual_router_id') is None:
            data['virtual_router_id'] = hash(data['cluster']) % 254 + 1
            pprint("Using keepalived virtual_router_id %s" %
                   data['virtual_router_id'])
    data['basedir'] = '/workdir' if container_mode() else '.'
    install_k3s_args = []
    for arg in data:
        if arg.startswith('install_k3s'):
            install_k3s_args.append("%s=%s" % (arg.upper(), data[arg]))
    cluster = data.get('cluster')
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    firstmaster = "%s-master-0" % cluster
    if os.path.exists(clusterdir):
        error("Please remove existing directory %s first..." % clusterdir)
        sys.exit(1)
    if find_executable('kubectl') is None:
        get_kubectl()
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        os.mkdir("%s/auth" % clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam = overrides.copy()
            installparam['api_ip'] = api_ip
            installparam['plan'] = plan
            installparam['kubetype'] = 'k3s'
            yaml.safe_dump(installparam,
                           p,
                           default_flow_style=False,
                           encoding='utf-8',
                           allow_unicode=True)
    if os.path.exists("manifests") and os.path.isdir("manifests"):
        data['files'] = [{
            "path": "/root/manifests",
            "currentdir": True,
            "origin": "manifests"
        }]
    k = config.k
    bootstrap_overrides = data.copy()
    bootstrap_install_k3s_args = install_k3s_args.copy()
    if sdn is None or sdn != 'flannel':
        bootstrap_install_k3s_args.append(
            "INSTALL_K3S_EXEC='--flannel-backend=none'")
    bootstrap_install_k3s_args = ' '.join(bootstrap_install_k3s_args)
    bootstrap_overrides['install_k3s_args'] = bootstrap_install_k3s_args
    result = config.plan(plan,
                         inputfile='%s/bootstrap.yml' % plandir,
                         overrides=bootstrap_overrides)
    if result['result'] != "success":
        sys.exit(1)
    nodes_overrides = data.copy()
    nodes_install_k3s_args = install_k3s_args.copy()
    if sdn is None or sdn != 'flannel':
        nodes_install_k3s_args.append(
            "INSTALL_K3S_EXEC='--flannel-backend=none'")
    nodes_install_k3s_args = ' '.join(nodes_install_k3s_args)
    nodes_overrides['install_k3s_args'] = nodes_install_k3s_args
    if masters > 1:
        pprint("Deploying extra masters")
        threaded = data.get('threaded', False) or data.get(
            'masters_threaded', False)
        config.plan(plan,
                    inputfile='%s/masters.yml' % plandir,
                    overrides=nodes_overrides,
                    threaded=threaded)
    with open("%s/join.sh" % clusterdir, 'w') as f:
        if api_ip is None:
            api_ip = k.info(firstmaster)['ip']
        joincmd = f"curl -sfL https://get.k3s.io | K3S_URL=https://{api_ip}:6443 K3S_TOKEN={token} "
        joincmd += ' '.join(install_k3s_args)
        extra_args = data['extra_worker_args'] if data.get(
            'extra_worker_args', []) else data.get('extra_args', [])
        extra_args = ' '.join(extra_args)
        f.write("%s sh -s - agent %s \n" % (joincmd, extra_args))
    workers = data.get('workers', 0)
    if workers > 0:
        pprint("Deploying workers")
        if 'name' in data:
            del data['name']
        os.chdir(os.path.expanduser("~/.kcli"))
        threaded = data.get('threaded', False) or data.get(
            'workers_threaded', False)
        config.plan(plan,
                    inputfile='%s/workers.yml' % plandir,
                    overrides=data,
                    threaded=threaded)
    success("K3s cluster %s deployed!!!" % cluster)
    info2("export KUBECONFIG=$HOME/.kcli/clusters/%s/auth/kubeconfig" %
          cluster)
    info2("export PATH=$PWD:$PATH")
Exemplo n.º 6
0
def create(config, plandir, cluster, overrides):
    platform = config.type
    k = config.k
    data = {'kubetype': 'generic', 'xip': False, 'domain': 'karmalabs.com'}
    data.update(overrides)
    if 'keys' not in overrides and not os.path.exists(os.path.expanduser("~/.ssh/id_rsa.pub"))\
            and not os.path.exists(os.path.expanduser("~/.ssh/id_dsa.pub"))\
            and not os.path.exists(os.path.expanduser("~/.kcli/id_rsa.pub"))\
            and not os.path.exists(os.path.expanduser("~/.kcli/id_dsa.pub")):
        error(
            "No usable public key found, which is required for the deployment")
        os._exit(1)
    data['cluster'] = overrides.get(
        'cluster', cluster if cluster is not None else 'testk')
    plan = cluster if cluster is not None else data['cluster']
    data['kube'] = data['cluster']
    masters = data.get('masters', 1)
    if masters == 0:
        error("Invalid number of masters")
        os._exit(1)
    network = data.get('network', 'default')
    xip = data['xip']
    api_ip = data.get('api_ip')
    if platform in cloudplatforms:
        domain = data.get('domain', 'karmalabs.com')
        api_ip = "%s-master.%s" % (cluster, domain)
    elif api_ip is None:
        if network == 'default' and platform == 'kvm':
            warning("Using 192.168.122.253 as api_ip")
            data['api_ip'] = "192.168.122.253"
            api_ip = "192.168.122.253"
        elif platform == 'kubevirt':
            selector = {'kcli/plan': plan, 'kcli/role': 'master'}
            api_ip = config.k.create_service("%s-api" % cluster,
                                             config.k.namespace,
                                             selector,
                                             _type="LoadBalancer",
                                             ports=[6443])
            if api_ip is None:
                os._exit(1)
            else:
                pprint("Using api_ip %s" % api_ip)
                data['api_ip'] = api_ip
        else:
            error("You need to define api_ip in your parameters file")
            os._exit(1)
    if xip and platform not in cloudplatforms:
        data['domain'] = "%s.xip.io" % api_ip
    if data.get('virtual_router_id') is None:
        data['virtual_router_id'] = hash(data['cluster']) % 254 + 1
    pprint("Using keepalived virtual_router_id %s" % data['virtual_router_id'])
    version = data.get('version')
    if version is not None and not str(version).startswith('1.'):
        error("Invalid version %s" % version)
        os._exit(1)
    data['basedir'] = '/workdir' if os.path.exists(
        "/i_am_a_container") else '.'
    cluster = data.get('cluster')
    image = data.get('image', 'centos7')
    data['ubuntu'] = True if 'ubuntu' in image.lower() or [
        entry for entry in UBUNTUS if entry in image
    ] else False
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    firstmaster = "%s-master-0" % cluster
    if os.path.exists(clusterdir):
        error("Please remove existing directory %s first..." % clusterdir)
        sys.exit(1)
    if find_executable('kubectl') is None:
        get_kubectl()
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        os.mkdir("%s/auth" % clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam = overrides.copy()
            installparam['api_ip'] = api_ip
            installparam['virtual_router_id'] = data['virtual_router_id']
            installparam['plan'] = plan
            yaml.safe_dump(installparam,
                           p,
                           default_flow_style=False,
                           encoding='utf-8',
                           allow_unicode=True)
    result = config.plan(plan,
                         inputfile='%s/masters.yml' % plandir,
                         overrides=data)
    if result['result'] != "success":
        os._exit(1)
    source, destination = "/root/join.sh", "%s/join.sh" % clusterdir
    firstmasterip, firstmastervmport = _ssh_credentials(k, firstmaster)[1:]
    scpcmd = scp(firstmaster,
                 ip=firstmasterip,
                 user='******',
                 source=source,
                 destination=destination,
                 tunnel=config.tunnel,
                 tunnelhost=config.tunnelhost,
                 tunnelport=config.tunnelport,
                 tunneluser=config.tunneluser,
                 download=True,
                 insecure=True,
                 vmport=firstmastervmport)
    os.system(scpcmd)
    source, destination = "/etc/kubernetes/admin.conf", "%s/auth/kubeconfig" % clusterdir
    scpcmd = scp(firstmaster,
                 ip=firstmasterip,
                 user='******',
                 source=source,
                 destination=destination,
                 tunnel=config.tunnel,
                 tunnelhost=config.tunnelhost,
                 tunnelport=config.tunnelport,
                 tunneluser=config.tunneluser,
                 download=True,
                 insecure=True,
                 vmport=firstmastervmport)
    os.system(scpcmd)
    workers = data.get('workers', 0)
    if workers > 0:
        pprint("Deploying workers")
        if 'name' in data:
            del data['name']
        os.chdir(os.path.expanduser("~/.kcli"))
        config.plan(plan, inputfile='%s/workers.yml' % plandir, overrides=data)
    success("Kubernetes cluster %s deployed!!!" % cluster)
    masters = data.get('masters', 1)
    info2("export KUBECONFIG=$HOME/.kcli/clusters/%s/auth/kubeconfig" %
          cluster)
    info2("export PATH=$PWD:$PATH")
    prefile = 'pre_ubuntu.sh' if data['ubuntu'] else 'pre_el.sh'
    predata = config.process_inputfile(plan,
                                       "%s/%s" % (plandir, prefile),
                                       overrides=data)
    with open("%s/pre.sh" % clusterdir, 'w') as f:
        f.write(predata)
    os.environ['KUBECONFIG'] = "%s/auth/kubeconfig" % clusterdir
    apps = data.get('apps', [])
    if apps:
        os.environ["PATH"] += ":%s" % os.getcwd()
        for app in apps:
            appdir = "%s/apps/%s" % (plandir, app)
            if not os.path.exists(appdir):
                warning("Skipping unsupported app %s" % app)
            else:
                pprint("Adding app %s" % app)
                if '%s_version' % app not in overrides:
                    data['%s_version' % app] = 'latest'
                kube_create_app(config, appdir, overrides=data)
Exemplo n.º 7
0
def create(config, plandir, cluster, overrides):
    platform = config.type
    data = {'kubetype': 'k3s'}
    data.update(overrides)
    data['cluster'] = overrides.get('cluster', cluster if cluster is not None else 'testk')
    plan = cluster if cluster is not None else data['cluster']
    data['kube'] = data['cluster']
    masters = data.get('masters', 1)
    network = data.get('network', 'default')
    token = data.get('token', 'supersecret')
    api_ip = data.get('api_ip')
    if masters > 1:
        if platform in cloudplatforms:
            domain = data.get('domain', 'karmalabs.com')
            api_ip = "%s-master.%s" % (cluster, domain)
        elif api_ip is None:
            if network == 'default' and platform == 'kvm':
                warning("Using 192.168.122.253 as api_ip")
                data['api_ip'] = "192.168.122.253"
                api_ip = "192.168.122.253"
            elif platform == 'kubevirt':
                selector = {'kcli/plan': plan, 'kcli/role': 'master'}
                api_ip = config.k.create_service("%s-api" % cluster, config.k.namespace, selector,
                                                 _type="LoadBalancer", ports=[6443])
                if api_ip is None:
                    os._exit(1)
                else:
                    pprint("Using api_ip %s" % api_ip)
                    data['api_ip'] = api_ip
            else:
                error("You need to define api_ip in your parameters file")
                os._exit(1)
    version = data.get('version', 'stable')
    if version not in ['stable', 'latest', 'testing']:
        error("Invalid version %s" % version)
        os._exit(1)
    data['basedir'] = '/workdir' if os.path.exists("/i_am_a_container") else '.'
    cluster = data.get('cluster')
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    firstmaster = "%s-master-0" % cluster
    if os.path.exists(clusterdir):
        error("Please remove existing directory %s first..." % clusterdir)
        sys.exit(1)
    if find_executable('kubectl') is None:
        get_kubectl()
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        os.mkdir("%s/auth" % clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam = overrides.copy()
            installparam['api_ip'] = api_ip
            installparam['plan'] = plan
            yaml.safe_dump(installparam, p, default_flow_style=False, encoding='utf-8', allow_unicode=True)
    if os.path.exists("manifests") and os.path.isdir("manifests"):
        data['files'] = [{"path": "/root/manifests", "currentdir": True, "origin": "manifests"}]
    k = config.k
    result = config.plan(plan, inputfile='%s/bootstrap.yml' % plandir, overrides=data)
    if result['result'] != "success":
        os._exit(1)
    if masters > 1:
        pprint("Deploying extra masters")
        if 'name' in data:
            del data['name']
        config.plan(plan, inputfile='%s/masters.yml' % plandir, overrides=data)
    firstmasterip, firstmastervmport = _ssh_credentials(k, firstmaster)[1:]
    with open("%s/join.sh" % clusterdir, 'w') as f:
        if api_ip is None:
            api_ip = k.info(firstmaster)['ip']
        joincmd = "curl -sfL https://get.k3s.io | K3S_URL=https://%s:6443 K3S_TOKEN=%s" % (api_ip, token)
        if data['sdn'] != "flannel":
            joincmd += " INSTALL_K3S_EXEC='--no-flannel'"
        f.write("%s sh -\n" % joincmd)
    source, destination = "/root/kubeconfig", "%s/auth/kubeconfig" % clusterdir
    scpcmd = scp(firstmaster, ip=firstmasterip, user='******', source=source, destination=destination,
                 tunnel=config.tunnel, tunnelhost=config.tunnelhost, tunnelport=config.tunnelport,
                 tunneluser=config.tunneluser, download=True, insecure=True, vmport=firstmastervmport)
    os.system(scpcmd)
    workers = data.get('workers', 0)
    if workers > 0:
        pprint("Deploying workers")
        if 'name' in data:
            del data['name']
        os.chdir(os.path.expanduser("~/.kcli"))
        config.plan(plan, inputfile='%s/workers.yml' % plandir, overrides=data)
    success("K3s cluster %s deployed!!!" % cluster)
    info2("export KUBECONFIG=$HOME/.kcli/clusters/%s/auth/kubeconfig" % cluster)
    info2("export PATH=$PWD:$PATH")
Exemplo n.º 8
0
def create(config, plandir, cluster, overrides):
    log_level = 'debug' if config.debug else 'info'
    os.environ["PATH"] += ":%s" % os.getcwd()
    k = config.k
    platform = config.type
    arch = k.get_capabilities()['arch'] if config.type == 'kvm' else 'x86_64'
    arch_tag = 'arm64' if arch in ['aarch64', 'arm64'] else 'latest'
    overrides['arch_tag'] = arch_tag
    if 'KUBECONFIG' not in os.environ:
        error("Missing KUBECONFIG...")
        sys.exit(1)
    elif not os.path.isabs(os.environ['KUBECONFIG']):
        os.environ['KUBECONFIG'] = "%s/%s" % (os.getcwd(),
                                              os.environ['KUBECONFIG'])
    data = {
        'kubetype': 'hypershift',
        'domain': 'karmalabs.com',
        'network': 'default',
        'workers': 2,
        'async': False,
        'tag': OPENSHIFT_TAG,
        'version': 'nightly',
        'namespace': 'mynamespace',
        'pub_key': os.path.expanduser('~/.ssh/id_rsa.pub'),
        'pull_secret': 'openshift_pull.json'
    }
    data.update(overrides)
    if 'cluster' in overrides:
        clustervalue = overrides.get('cluster')
    elif cluster is not None:
        clustervalue = cluster
    else:
        clustervalue = 'testk'
    data['cluster'] = clustervalue
    data['kube'] = data['cluster']
    pprint("Deploying cluster %s" % clustervalue)
    plan = cluster if cluster is not None else clustervalue
    domain = data.get('domain')
    version = data.get('version')
    tag = data.get('tag')
    if str(tag) == '4.1':
        tag = '4.10'
        data['tag'] = tag
    data['basedir'] = '/workdir' if container_mode() else '.'
    api_ip = os.popen(
        "oc get node -o wide | grep master | head -1 | awk '{print $6}'").read(
        ).strip()
    data['api_ip'] = api_ip
    cluster = data.get('cluster')
    namespace = data.get('namespace')
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    if os.path.exists(clusterdir):
        error("Please remove existing directory %s first..." % clusterdir)
        sys.exit(1)
    if find_executable('oc') is None:
        get_oc()
    pub_key = data.get('pub_key')
    pull_secret = pwd_path(data.get('pull_secret'))
    pull_secret = os.path.expanduser(pull_secret)
    if not os.path.exists(pull_secret):
        error("Missing pull secret file %s" % pull_secret)
        sys.exit(1)
    data['pull_secret'] = re.sub(r"\s", "", open(pull_secret).read())
    if not os.path.exists(pub_key):
        if os.path.exists(os.path.expanduser('~/.kcli/id_rsa.pub')):
            pub_key = os.path.expanduser('~/.kcli/id_rsa.pub')
        else:
            error("Missing public key file %s" % pub_key)
            sys.exit(1)
    data['pub_key'] = open(pub_key).read().strip()
    ingress_ip = data.get('ingress_ip')
    cidr = '192.168.122.0/24'
    if config.type in virtplatforms:
        if ingress_ip is None:
            network = data.get('network')
            networkinfo = k.info_network(network)
            if config.type == 'kvm' and networkinfo['type'] == 'routed':
                cidr = networkinfo['cidr']
                ingress_index = 3 if ':' in cidr else -4
                ingress_ip = str(ip_network(cidr)[ingress_index])
                warning("Using %s as ingress_ip" % ingress_ip)
                overrides['ingress_ip'] = ingress_ip
            else:
                error("You need to define ingress_ip in your parameters file")
                sys.exit(1)
        if data.get('virtual_router_id') is None:
            overrides['virtual_router_id'] = hash(cluster) % 254 + 1
            pprint("Using keepalived virtual_router_id %s" %
                   overrides['virtual_router_id'])
        pprint(f"Using {ingress_ip} for ingress vip....")
        ipv6 = True if ':' in cidr else False
        data['ipv6'] = ipv6
    assetdata = data.copy()
    if version == 'cluster':
        release_image = os.popen(
            "oc get clusterversion version -o jsonpath={'.status.history[-1].image'}"
        ).read()
        version = os.popen(
            "oc get clusterversion version -o jsonpath={'.status.history[-1].version'}"
        ).read()
        minor = version[:3].replace('.', '')
        image = f'rhcos{minor}'
        data['image'] = image
    else:
        if os.path.exists('openshift-install'):
            pprint("Removing old openshift-install")
            os.remove('openshift-install')
        if find_executable('openshift-install') is None:
            if version == 'ci':
                run = get_ci_installer(pull_secret, tag=tag)
            elif version == 'nightly':
                run = get_downstream_installer(nightly=True,
                                               tag=tag,
                                               pull_secret=pull_secret)
            else:
                run = get_downstream_installer(tag=tag,
                                               pull_secret=pull_secret)
            if run != 0:
                error("Couldn't download openshift-install")
                sys.exit(run)
            pprint(
                "Move downloaded openshift-install somewhere in your PATH if you want to reuse it"
            )
        else:
            warning("Using existing openshift-install found in your PATH")
        INSTALLER_VERSION = get_installer_version()
        pprint("Using installer version %s" % INSTALLER_VERSION)
        release_image = os.popen(
            "openshift-install version | grep 'release image' | cut -f3 -d' '"
        ).read().strip()
        image = data.get('image')
        if image is None:
            image_type = 'openstack' if data.get(
                'kvm_openstack',
                False) and config.type == 'kvm' else config.type
            region = config.k.region if config.type == 'aws' else None
            image_url = get_installer_rhcos(_type=image_type,
                                            region=region,
                                            arch=arch)
            if platform in ['aws', 'gcp']:
                image = image_url
            else:
                image = os.path.basename(os.path.splitext(image_url)[0])
                if platform == 'ibm':
                    image = image.replace('.', '-').replace('_', '-').lower()
                images = [v for v in k.volumes() if image in v]
                if not images:
                    result = config.handle_host(
                        pool=config.pool,
                        image=image,
                        download=True,
                        update_profile=False,
                        url=image_url,
                        size=data.get('kubevirt_disk_size'))
                    if result['result'] != 'success':
                        sys.exit(1)
            pprint("Using image %s" % image)
            data['image'] = image
        else:
            pprint("Checking if image %s is available" % image)
            images = [v for v in k.volumes() if image in v]
            if not images:
                error(
                    "Missing %s. Indicate correct image in your parameters file..."
                    % image)
                sys.exit(1)
    assetdata['release_image'] = release_image
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        os.mkdir("%s/auth" % clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam = overrides.copy()
            installparam['plan'] = plan
            installparam['kubetype'] = 'hypershift'
            installparam['api_ip'] = api_ip
            installparam['ingress_ip'] = ingress_ip
            installparam['image'] = image
            installparam['ipv6'] = ipv6
            yaml.safe_dump(installparam,
                           p,
                           default_flow_style=False,
                           encoding='utf-8',
                           allow_unicode=True)
    assetdata['cidr'] = cidr
    pprint("Creating control plane assets")
    cmcmd = f"oc create ns {namespace} -o yaml --dry-run=client | oc apply -f -"
    call(cmcmd, shell=True)
    assetfile = config.process_inputfile(cluster,
                                         f"{plandir}/assets.yaml",
                                         overrides=assetdata)
    with open(f"{clusterdir}/assets.yaml", 'w') as f:
        f.write(assetfile)
    cmcmd = f"oc create -f {clusterdir}/assets.yaml"
    call(cmcmd, shell=True)
    assetdata['clusterdir'] = clusterdir
    ignitionscript = config.process_inputfile(cluster,
                                              f"{plandir}/ignition.sh",
                                              overrides=assetdata)
    with open(f"{clusterdir}/ignition.sh", 'w') as f:
        f.write(ignitionscript)
    # TODO: monitor when ignition server is around
    pprint("Waiting 2mn for ignition server to be usable")
    time.sleep(120)
    call(f'bash {clusterdir}/ignition.sh', shell=True)
    pprint("Deploying workers")
    if 'name' in data:
        del data['name']
    if data.get('baremetal', False):
        result = config.plan(plan,
                             inputfile=f'{plandir}/kcli_plan.yml',
                             overrides=data,
                             onlyassets=True)
        iso_data = result['assets'][0]
        with open('iso.ign', 'w') as f:
            f.write(iso_data)
        ignitionfile = f'{cluster}-worker.ign'
        with open(ignitionfile, 'w') as f:
            f.write(iso_data)
        iso_pool = data['pool'] or config.pool
        generate_rhcos_iso(k, f"{cluster}-worker", iso_pool, installer=True)
    else:
        worker_threaded = data.get('threaded', False) or data.get(
            'workers_threaded', False)
        config.plan(plan,
                    inputfile=f'{plandir}/kcli_plan.yml',
                    overrides=data,
                    threaded=worker_threaded)
    if data.get('ignore_hosts', False):
        warning("Not updating /etc/hosts as per your request")
    else:
        update_etc_hosts(cluster, domain, api_ip, ingress_ip)
    kubeconfigpath = f'{clusterdir}/auth/kubeconfig'
    kubeconfig = os.popen(
        f"oc extract -n {namespace} secret/{cluster}-admin-kubeconfig --to=-"
    ).read()
    with open(kubeconfigpath, 'w') as f:
        f.write(kubeconfig)
    kubeadminpath = f'{clusterdir}/auth/kubeadmin-password'
    kubeadmin = os.popen(
        f"oc extract -n {namespace} secret/{cluster}-kubeadmin-password --to=-"
    ).read()
    with open(kubeadminpath, 'w') as f:
        f.write(kubeadmin)
    autoapproverpath = f'{clusterdir}/autoapprovercron.yml'
    autoapprover = config.process_inputfile(cluster,
                                            f"{plandir}/autoapprovercron.yml",
                                            overrides=data)
    with open(autoapproverpath, 'w') as f:
        f.write(autoapprover)
    call(f"oc apply -f {autoapproverpath}", shell=True)
    async_install = data.get('async')
    if async_install or find_executable('openshift-install') is None:
        success(f"Kubernetes cluster {cluster} deployed!!!")
        info2(
            f"export KUBECONFIG=$HOME/.kcli/clusters/{cluster}/auth/kubeconfig"
        )
        info2("export PATH=$PWD:$PATH")
    else:
        installcommand = 'openshift-install --dir=%s --log-level=%s wait-for install-complete' % (
            clusterdir, log_level)
        installcommand += " || %s" % installcommand
        pprint(
            "Launching install-complete step. It will be retried one extra time in case of timeouts"
        )
        call(installcommand, shell=True)
    os.environ['KUBECONFIG'] = f"{clusterdir}/auth/kubeconfig"
    apps = overrides.get('apps', [])
    process_apps(config, clusterdir, apps, overrides)
Exemplo n.º 9
0
def create(config, plandir, cluster, overrides):
    k = config.k
    bootstrap_helper_ip = None
    client = config.client
    platform = config.type
    pprint("Deploying on client %s" % client)
    data = {
        'helper_image': 'CentOS-7-x86_64-GenericCloud.qcow2',
        'domain': 'karmalabs.com',
        'network': 'default',
        'masters': 1,
        'workers': 0,
        'tag': DEFAULT_TAG,
        'ipv6': False,
        'pub_key': os.path.expanduser('~/.ssh/id_rsa.pub'),
        'pull_secret': 'openshift_pull.json',
        'version': 'nightly',
        'macosx': False,
        'upstream': False,
        'fips': False,
        'apps': [],
        'minimal': False,
        'dualstack': False,
        'sno': False,
        'sno_baremetal': False,
        'sno_disk': 'vda'
    }
    data.update(overrides)
    if 'cluster' in overrides:
        clustervalue = overrides.get('cluster')
    elif cluster is not None:
        clustervalue = cluster
    else:
        clustervalue = 'testk'
    data['cluster'] = clustervalue
    domain = data.get('domain')
    pprint("Deploying cluster %s" % clustervalue)
    plan = cluster if cluster is not None else clustervalue
    overrides['kubetype'] = 'openshift'
    apps = overrides.get('apps', [])
    if ('localstorage' in apps or 'ocs' in apps) and 'extra_disks' not in overrides\
            and 'extra_master_disks' not in overrides and 'extra_worker_disks' not in overrides:
        warning("Storage apps require extra disks to be set")
    overrides['kube'] = data['cluster']
    installparam = overrides.copy()
    sno = data.get('sno', False)
    ignore_hosts = data.get('ignore_hosts', False)
    if sno:
        sno_baremetal = data.get('sno_baremetal', False)
        sno_disk = data.get('sno_disk', 'vda')
        if sno_baremetal and 'vda' in sno_disk:
            error("You need to define correct sno_disk for baremetal")
            os._exit(1)
        # tag = 'registry.svc.ci.openshift.org/sno-dev/openshift-bip:0.5.0'
        masters = 1
        workers = 0
        data['mdns'] = False
        data['kubetype'] = 'openshift'
        data['kube'] = data['cluster']
    masters = data.get('masters', 1)
    if masters == 0:
        error("Invalid number of masters")
        os._exit(1)
    network = data.get('network')
    ipv6 = data['ipv6']
    disconnected_deploy = data.get('disconnected_deploy', False)
    disconnected_reuse = data.get('disconnected_reuse', False)
    disconnected_url = data.get('disconnected_url')
    disconnected_user = data.get('disconnected_user')
    disconnected_password = data.get('disconnected_password')
    disconnected_prefix = data.get('disconnected_prefix', 'ocp4')
    dualstack = data.get('dualstack')
    upstream = data.get('upstream')
    version = data.get('version')
    tag = data.get('tag')
    if os.path.exists('openshift-install'):
        pprint("Removing old openshift-install")
        os.remove('openshift-install')
    minimal = data.get('minimal')
    if version not in ['ci', 'nightly']:
        pprint("Using stable version")
    else:
        pprint("Using %s version" % version)
    cluster = data.get('cluster')
    helper_image = data.get('helper_image')
    image = data.get('image')
    api_ip = data.get('api_ip')
    if platform in virtplatforms and not sno and api_ip is None:
        if network == 'default' and platform == 'kvm':
            warning("Using 192.168.122.253 as api_ip")
            overrides['api_ip'] = "192.168.122.253"
            api_ip = "192.168.122.253"
        else:
            error("You need to define api_ip in your parameters file")
            os._exit(1)
    if not sno and ':' in api_ip:
        ipv6 = True
    if ipv6:
        data['network_type'] = 'OVNKubernetes'
        data['ipv6'] = True
        overrides['ipv6'] = True
        if not disconnected_deploy and disconnected_url is None:
            warning(
                "Forcing disconnected_deploy to True as no disconnected_url was provided"
            )
            data['disconnected_deploy'] = True
            disconnected_deploy = True
    ingress_ip = data.get('ingress_ip')
    if ingress_ip is not None and api_ip is not None and ingress_ip == api_ip:
        ingress_ip = None
        overrides['ingress_ip'] = None
    public_api_ip = data.get('public_api_ip')
    network = data.get('network')
    if platform == 'packet':
        if network == 'default':
            error("You need to indicate a specific vlan network")
            os._exit(1)
        else:
            facilities = [
                n['domain'] for n in k.list_networks().values()
                if str(n['cidr']) == network
            ]
            if not facilities:
                error("Vlan network %s not found in any facility" % network)
                os._exit(1)
            elif k.facility not in facilities:
                error("Vlan network %s not found in facility %s" %
                      (network, k.facility))
                os._exit(1)
    masters = data.get('masters')
    workers = data.get('workers')
    tag = data.get('tag')
    pub_key = data.get('pub_key')
    pull_secret = pwd_path(data.get(
        'pull_secret')) if not upstream else "%s/fake_pull.json" % plandir
    pull_secret = os.path.expanduser(pull_secret)
    macosx = data.get('macosx')
    if macosx and not os.path.exists('/i_am_a_container'):
        macosx = False
    if platform == 'openstack' and (api_ip is None or public_api_ip is None):
        error(
            "You need to define both api_ip and public_api_ip in your parameters file"
        )
        os._exit(1)
    if not os.path.exists(pull_secret):
        error("Missing pull secret file %s" % pull_secret)
        sys.exit(1)
    if not os.path.exists(pub_key):
        if os.path.exists(os.path.expanduser('~/.kcli/id_rsa.pub')):
            pub_key = os.path.expanduser('~/.kcli/id_rsa.pub')
        else:
            error("Missing public key file %s" % pub_key)
            sys.exit(1)
    clusterdir = os.path.expanduser("~/.kcli/clusters/%s" % cluster)
    if os.path.exists(clusterdir):
        if [v for v in config.k.list() if v.get('plan', 'kvirt') == cluster]:
            error("Please remove existing directory %s first..." % clusterdir)
            sys.exit(1)
        else:
            pprint("Removing directory %s" % clusterdir)
            rmtree(clusterdir)
    os.environ['KUBECONFIG'] = "%s/auth/kubeconfig" % clusterdir
    if find_executable('oc') is None:
        get_oc(macosx=macosx)
    if version == 'ci':
        if '/' not in str(tag):
            basetag = 'ocp' if not upstream else 'origin'
            tag = 'registry.ci.openshift.org/%s/release:%s' % (basetag, tag)
        os.environ['OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE'] = tag
        pprint("Setting OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE to %s" % tag)
    if find_executable('openshift-install') is None:
        if version == 'ci':
            run = get_ci_installer(pull_secret, tag=tag, upstream=upstream)
        elif version == 'nightly':
            run = get_downstream_installer(nightly=True, tag=tag)
        elif upstream:
            run = get_upstream_installer(tag=tag)
        else:
            run = get_downstream_installer(tag=tag)
        if run != 0:
            error("Couldn't download openshift-install")
            os._exit(run)
        pprint(
            "Move downloaded openshift-install somewhere in your path if you want to reuse it"
        )
    os.environ["PATH"] += ":%s" % os.getcwd()
    if disconnected_url is not None:
        if '/' not in str(tag):
            tag = '%s/%s/release:%s' % (disconnected_url, disconnected_prefix,
                                        tag)
            os.environ['OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE'] = tag
        pprint("Setting OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE to %s" % tag)
    INSTALLER_VERSION = get_installer_version()
    COMMIT_ID = os.popen('openshift-install version').readlines()[1].replace(
        'built from commit', '').strip()
    if platform == 'packet' and not upstream:
        overrides['commit_id'] = COMMIT_ID
    pprint("Using installer version %s" % INSTALLER_VERSION)
    OPENSHIFT_VERSION = INSTALLER_VERSION[0:3].replace('.', '')
    curl_header = "Accept: application/vnd.coreos.ignition+json; version=3.1.0"
    if upstream:
        curl_header = "User-Agent: Ignition/2.3.0"
    elif OPENSHIFT_VERSION.isdigit() and int(OPENSHIFT_VERSION) < 46:
        curl_header = "User-Agent: Ignition/0.35.0"
    overrides['curl_header'] = curl_header
    if sno:
        pass
    elif image is None:
        if upstream:
            fcos_base = 'stable' if version == 'stable' else 'testing'
            fcos_url = "https://builds.coreos.fedoraproject.org/streams/%s.json" % fcos_base
            image_url = get_latest_fcos(fcos_url, _type=config.type)
        else:
            image_url = get_commit_rhcos(COMMIT_ID, _type=config.type)
        image = os.path.basename(os.path.splitext(image_url)[0])
        images = [v for v in k.volumes() if image in v]
        if not images:
            result = config.handle_host(pool=config.pool,
                                        image=image,
                                        download=True,
                                        update_profile=False,
                                        url=image_url)
            if result['result'] != 'success':
                os._exit(1)
        else:
            pprint("Using image %s" % image)
    elif platform != 'packet':
        pprint("Checking if image %s is available" % image)
        images = [v for v in k.volumes() if image in v]
        if not images:
            error(
                "Missing %s. Indicate correct image in your parameters file..."
                % image)
            os._exit(1)
    else:
        error(
            "Missing image in your parameters file. This is required for packet"
        )
        os._exit(1)
    overrides['image'] = image
    overrides['cluster'] = cluster
    if not os.path.exists(clusterdir):
        os.makedirs(clusterdir)
        with open("%s/kcli_parameters.yml" % clusterdir, 'w') as p:
            installparam['plan'] = plan
            yaml.safe_dump(installparam,
                           p,
                           default_flow_style=False,
                           encoding='utf-8',
                           allow_unicode=True)
    data['pub_key'] = open(pub_key).read().strip()
    if platform in virtplatforms and disconnected_deploy:
        if platform == 'kvm' and network in [
                n for n in k.list_networks()
                if k.list_networks()[n]['type'] == 'routed'
        ]:
            data['disconnected_dns'] = True
        disconnected_vm = "%s-disconnecter" % cluster
        pprint("Deploying disconnected vm %s" % disconnected_vm)
        data['pull_secret'] = re.sub(r"\s", "", open(pull_secret).read())
        disconnected_plan = "%s-reuse" % plan if disconnected_reuse else plan
        if version == 'ci' and 'disconnected_origin' not in overrides:
            warning("Forcing disconnected_origin to registry.ci.openshift.org")
            data['disconnected_origin'] = "registry.ci.openshift.org"
        result = config.plan(disconnected_plan,
                             inputfile='%s/disconnected.yml' % plandir,
                             overrides=data)
        if result['result'] != 'success':
            os._exit(1)
        disconnected_ip, disconnected_vmport = _ssh_credentials(
            k, disconnected_vm)[1:]
        cacmd = "cat /opt/registry/certs/domain.crt"
        cacmd = ssh(disconnected_vm,
                    ip=disconnected_ip,
                    user='******',
                    tunnel=config.tunnel,
                    tunnelhost=config.tunnelhost,
                    tunnelport=config.tunnelport,
                    tunneluser=config.tunneluser,
                    insecure=True,
                    cmd=cacmd,
                    vmport=disconnected_vmport)
        disconnected_ca = os.popen(cacmd).read().strip()
        if data['ca'] is not None:
            data['ca'] += disconnected_ca
        else:
            data['ca'] = disconnected_ca
        urlcmd = "cat /root/url.txt"
        urlcmd = ssh(disconnected_vm,
                     ip=disconnected_ip,
                     user='******',
                     tunnel=config.tunnel,
                     tunnelhost=config.tunnelhost,
                     tunnelport=config.tunnelport,
                     tunneluser=config.tunneluser,
                     insecure=True,
                     cmd=urlcmd,
                     vmport=disconnected_vmport)
        disconnected_url = os.popen(urlcmd).read().strip()
        overrides['disconnected_url'] = disconnected_url
        data['disconnected_url'] = disconnected_url
        if disconnected_user is None:
            disconnected_user = '******'
        if disconnected_password is None:
            disconnected_password = '******'
        versioncmd = "cat /root/version.txt"
        versioncmd = ssh(disconnected_vm,
                         ip=disconnected_ip,
                         user='******',
                         tunnel=config.tunnel,
                         tunnelhost=config.tunnelhost,
                         tunnelport=config.tunnelport,
                         tunneluser=config.tunneluser,
                         insecure=True,
                         cmd=versioncmd,
                         vmport=disconnected_vmport)
        disconnected_version = os.popen(versioncmd).read().strip()
        os.environ[
            'OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE'] = disconnected_version
        pprint("Setting OPENSHIFT_INSTALL_RELEASE_IMAGE_OVERRIDE to %s" %
               disconnected_version)
    if disconnected_url is not None and disconnected_user is not None and disconnected_password is not None:
        key = "%s:%s" % (disconnected_user, disconnected_password)
        key = str(b64encode(key.encode('utf-8')), 'utf-8')
        auths = {
            'auths': {
                disconnected_url: {
                    'auth': key,
                    'email': '*****@*****.**'
                }
            }
        }
        data['pull_secret'] = json.dumps(auths)
    else:
        data['pull_secret'] = re.sub(r"\s", "", open(pull_secret).read())
    installconfig = config.process_inputfile(cluster,
                                             "%s/install-config.yaml" %
                                             plandir,
                                             overrides=data)
    with open("%s/install-config.yaml" % clusterdir, 'w') as f:
        f.write(installconfig)
    with open("%s/install-config.yaml.bck" % clusterdir, 'w') as f:
        f.write(installconfig)
    autoapprover = config.process_inputfile(cluster,
                                            "%s/autoapprovercron.yml" %
                                            plandir,
                                            overrides=data)
    with open("%s/autoapprovercron.yml" % clusterdir, 'w') as f:
        f.write(autoapprover)
    run = call('openshift-install --dir=%s create manifests' % clusterdir,
               shell=True)
    if run != 0:
        error("Leaving environment for debugging purposes")
        error("You can delete it with kcli delete kube --yes %s" % cluster)
        os._exit(run)
    if minimal:
        warning("Deploying cvo overrides to provide a minimal install")
        with open("%s/cvo-overrides.yaml" % plandir) as f:
            cvo_override = f.read()
        with open("%s/manifests/cvo-overrides.yaml" % clusterdir, "a") as f:
            f.write(cvo_override)
    if ipv6:
        for role in ['master', 'worker']:
            blacklist = config.process_inputfile(cluster,
                                                 "%s/99-blacklist-ipi.yaml" %
                                                 plandir,
                                                 overrides={'role': role})
            with open(
                    "%s/openshift/99-blacklist-ipi-%s.yaml" %
                (clusterdir, role), 'w') as f:
                f.write(blacklist)
    for f in glob("%s/customisation/*.yaml" % plandir):
        if '99-ingress-controller.yaml' in f:
            ingressrole = 'master' if workers == 0 else 'worker'
            replicas = masters if workers == 0 else workers
            ingressconfig = config.process_inputfile(cluster,
                                                     f,
                                                     overrides={
                                                         'replicas': replicas,
                                                         'role': ingressrole
                                                     })
            with open("%s/openshift/99-ingress-controller.yaml" % clusterdir,
                      'w') as f:
                f.write(ingressconfig)
        else:
            copy2(f, "%s/openshift" % clusterdir)
    manifestsdir = pwd_path("manifests")
    if os.path.exists(manifestsdir) and os.path.isdir(manifestsdir):
        for f in glob("%s/*.yaml" % manifestsdir):
            copy2(f, "%s/openshift" % clusterdir)
    if 'network_type' in data and data['network_type'] == 'Calico':
        for asset in calicoassets:
            fetch(asset, manifestsdir)
    if 'network_type' in data and data['network_type'] == 'Contrail':
        pprint("Fetching contrail assets")
        for asset in contrail_manifests:
            fetch(asset, "%s/manifests" % clusterdir)
        for asset in contrail_openshifts:
            fetch(asset, "%s/openshift" % clusterdir)
        contrail_registry = data.get('contrail_registry', "hub.juniper.net")
        contrail_user = data.get('contrail_user')
        contrail_password = data.get('contrail_password')
        if contrail_user is None:
            error("Missing contrail_user")
            os._exit(1)
        if contrail_password is None:
            error("Missing contrail_password")
            os._exit(1)
        contrail_creds = "%s:%s" % (contrail_user, contrail_password)
        contrail_auth = b64encode(contrail_creds.encode()).decode("UTF-8")
        contrail_auth = {
            "auths": {
                contrail_registry: {
                    "username": contrail_user,
                    "password": contrail_password,
                    "auth": contrail_auth
                }
            }
        }
        contrail_auth = json.dumps(contrail_auth)
        contrail_data = {
            'contrail_auth': b64encode(contrail_auth.encode()).decode("UTF-8")
        }
        contrail_secret = config.process_inputfile(
            cluster,
            "%s/contrail_registry_secret.j2" % plandir,
            overrides=contrail_data)
        with open(
                "%s/manifests/00-contrail-02-registry-secret.yaml" %
                clusterdir, 'w') as f:
            f.write(contrail_secret)
    if dualstack:
        copy2("%s/dualstack.yml" % plandir, "%s/openshift" % clusterdir)
    if sno:
        sno_name = "%s-sno" % cluster
        sno_dns = data.get('sno_dns', True)
        run = call(
            'openshift-install --dir=%s create single-node-ignition-config' %
            clusterdir,
            shell=True)
        if run != 0:
            error("Hit issue.Leaving")
            os._exit(run)
        os.rename("%s/bootstrap-in-place-for-live-iso.ign" % clusterdir,
                  "./%s.ign" % sno_name)
        with open("iso.ign", 'w') as f:
            if sno_dns:
                _files = [{
                    "path": "/root/sno-finish.service",
                    "origin": "%s/sno-finish.service" % plandir
                }, {
                    "path": "/usr/local/bin/sno-finish.sh",
                    "origin": "%s/sno-finish.sh" % plandir,
                    "mode": 700
                }, {
                    "path": "/root/coredns.yml",
                    "origin": "%s/staticpods/coredns.yml" % plandir
                }, {
                    "path": "/root/Corefile",
                    "origin": "%s/Corefile" % plandir
                }, {
                    "path": "/root/99-forcedns",
                    "origin": "%s/99-forcedns" % plandir
                }]
                iso_overrides = {'files': _files}
            else:
                iso_overrides = {}
            iso_overrides.update(data)
            result = config.create_vm(sno_name,
                                      'rhcos46',
                                      overrides=iso_overrides,
                                      onlyassets=True)
            pprint("Writing iso.ign to current dir")
            f.write(result['data'])
        if config.type != 'kvm':
            pprint("Additional workflow not available on %s" % config.type)
            pprint("Embed iso.ign in rhcos live iso")
            os._exit(0)
        else:
            generate_rhcos_iso(k, cluster, data['pool'])
            if not sno_baremetal:
                pprint("Deploying sno")
                result = config.plan(plan,
                                     inputfile='%s/sno.yml' % plandir,
                                     overrides=data)
                if result['result'] != 'success':
                    os._exit(1)
                if ignore_hosts:
                    warning("Not updating /etc/hosts as per your request")
                else:
                    while api_ip is None:
                        api_ip = k.info(sno_name).get('ip')
                        pprint("Waiting 5s to retrieve sno ip...")
                        sleep(5)
                    update_etc_hosts(cluster, domain, api_ip)
                installcommand = 'openshift-install --dir=%s --log-level=debug wait-for install-complete' % clusterdir
                installcommand += " || %s" % installcommand
                pprint(
                    "Launching install-complete step. It will be retried one extra time in case of timeouts"
                )
                call(installcommand, shell=True)
            else:
                warning(
                    "You might need to create manual entries in /etc/hosts to reach the sno installation"
                )
        os._exit(0)
    call('openshift-install --dir=%s create ignition-configs' % clusterdir,
         shell=True)
    for role in ['master', 'worker']:
        ori = "%s/%s.ign" % (clusterdir, role)
        copy2(ori, "%s.ori" % ori)
    if masters < 3:
        version_match = re.match("4.([0-9]*).*", INSTALLER_VERSION)
        COS_VERSION = "4%s" % version_match.group(
            1) if version_match is not None else '45'
        if not upstream and int(COS_VERSION) > 43:
            bootstrap_patch = open('%s/bootstrap_patch.sh' % plandir).read()
            bootstrap_service = open('%s/bootstrap_patch.service' %
                                     plandir).read()
            patch_bootstrap("%s/bootstrap.ign" % clusterdir, bootstrap_patch,
                            bootstrap_service)
    staticdata = gather_dhcp(data, platform)
    if staticdata:
        pprint("Deploying helper dhcp node" % image)
        staticdata.update({
            'network': network,
            'dhcp_image': helper_image,
            'prefix': cluster,
            domain: '%s.%s' % (cluster, domain)
        })
        result = config.plan(plan,
                             inputfile='%s/dhcp.yml' % plandir,
                             overrides=staticdata)
        if result['result'] != 'success':
            os._exit(1)
    if platform in virtplatforms:
        if data.get('virtual_router_id') is None:
            overrides['virtual_router_id'] = hash(cluster) % 254 + 1
        pprint("Using keepalived virtual_router_id %s" %
               overrides['virtual_router_id'])
        pprint("Using %s for api vip...." % api_ip)
        host_ip = api_ip if platform != "openstack" else public_api_ip
        if ignore_hosts:
            warning("Ignoring /etc/hosts")
        else:
            update_etc_hosts(cluster, domain, host_ip, ingress_ip)
        if platform in [
                'openstack', 'vsphere'
        ] or (platform == 'packet' and config.k.tunnelhost is None):
            # bootstrap ignition is too big in those platforms so we deploy a temporary web server to serve it
            helper_overrides = {}
            if helper_image is None:
                images = [
                    v for v in k.volumes()
                    if 'centos' in v.lower() or 'fedora' in v.lower()
                ]
                if images:
                    image = os.path.basename(images[0])
                else:
                    helper_image = "CentOS-7-x86_64-GenericCloud.qcow2"
                    pprint("Downloading centos helper image")
                    result = config.handle_host(pool=config.pool,
                                                image="centos7",
                                                download=True,
                                                update_profile=False)
                pprint("Using helper image %s" % helper_image)
            else:
                images = [v for v in k.volumes() if helper_image in v]
                if not images:
                    error(
                        "Missing image %s. Indicate correct helper image in your parameters file"
                        % helper_image)
                    os._exit(1)
            if platform == 'openstack':
                helper_overrides['flavor'] = "m1.medium"
            helper_overrides['nets'] = [network]
            helper_overrides['plan'] = cluster
            bootstrap_helper_name = "%s-bootstrap-helper" % cluster
            cmds = ["iptables -F", "yum -y install httpd", "setenforce 0"]
            if platform == 'packet':
                config.k.tunnelhost = bootstrap_helper_ip
                cmds.append(
                    "sed -i 's/apache/root/' /etc/httpd/conf/httpd.conf")
            cmds.append("systemctl enable --now httpd")
            helper_overrides['cmds'] = cmds
            config.create_vm("%s-bootstrap-helper" % cluster,
                             helper_image,
                             overrides=helper_overrides,
                             wait=True)
            bootstrap_helper_ip, bootstrap_helper_vmport = _ssh_credentials(
                bootstrap_helper_name)[1:]
            source, destination = "%s/bootstrap.ign" % clusterdir, "/var/www/html/bootstrap"
            scpcmd = scp(bootstrap_helper_name,
                         ip=bootstrap_helper_ip,
                         user='******',
                         source=source,
                         destination=destination,
                         tunnel=config.tunnel,
                         tunnelhost=config.tunnelhost,
                         tunnelport=config.tunnelport,
                         tunneluser=config.tunneluser,
                         download=False,
                         insecure=True,
                         vmport=bootstrap_helper_vmport)
            os.system(scpcmd)
            cmd = "chown apache.apache /var/www/html/bootstrap"
            sshcmd = ssh(bootstrap_helper_name,
                         ip=bootstrap_helper_ip,
                         user='******',
                         tunnel=config.tunnel,
                         tunnelhost=config.tunnelhost,
                         tunnelport=config.tunnelport,
                         tunneluser=config.tunneluser,
                         insecure=True,
                         cmd=cmd,
                         vmport=bootstrap_helper_vmport)
            os.system(sshcmd)
            sedcmd = 'sed "s@https://api-int.%s.%s:22623/config/master@http://%s/bootstrap@" ' % (
                cluster, domain, bootstrap_helper_ip)
            sedcmd += '%s/master.ign' % clusterdir
            sedcmd += ' > %s/bootstrap.ign' % clusterdir
            call(sedcmd, shell=True)
            sedcmd = 'sed "s@https://api-int.%s.%s:22623/config/master@http://%s/worker@" ' % (
                cluster, domain, bootstrap_helper_ip)
            sedcmd += '%s/master.ign' % clusterdir
            sedcmd += ' > %s/worker.ign' % clusterdir
            call(sedcmd, shell=True)
        new_api_ip = api_ip if not ipv6 else "[%s]" % api_ip
        sedcmd = 'sed -i "s@https://api-int.%s.%s:22623/config@http://%s:22624/config@"' % (
            cluster, domain, new_api_ip)
        sedcmd += ' %s/master.ign %s/worker.ign' % (clusterdir, clusterdir)
        call(sedcmd, shell=True)
    if platform in cloudplatforms:
        bootstrap_helper_name = "%s-bootstrap-helper" % cluster
        helper_overrides = {
            'reservedns': True,
            'domain': '%s.%s' % (cluster, domain),
            'tags': [tag],
            'plan': cluster,
            'nets': [network]
        }
        config.create_vm("%s-bootstrap-helper" % cluster,
                         helper_image,
                         overrides=helper_overrides)
        status = ""
        while status != "running":
            status = k.info(bootstrap_helper_name).get('status')
            pprint("Waiting 5s for bootstrap helper node to be running...")
            sleep(5)
        sleep(5)
        bootstrap_helper_ip, bootstrap_helper_vmport = _ssh_credentials(
            k, bootstrap_helper_name)[1:]
        cmd = "iptables -F ; yum -y install httpd ; systemctl start httpd"
        sshcmd = ssh(bootstrap_helper_name,
                     ip=bootstrap_helper_ip,
                     user='******',
                     tunnel=config.tunnel,
                     tunnelhost=config.tunnelhost,
                     tunnelport=config.tunnelport,
                     tunneluser=config.tunneluser,
                     insecure=True,
                     cmd=cmd,
                     vmport=bootstrap_helper_vmport)
        os.system(sshcmd)
        source, destination = "%s/bootstrap.ign" % clusterdir, "/var/www/html/bootstrap"
        scpcmd = scp(bootstrap_helper_name,
                     ip=bootstrap_helper_ip,
                     user='******',
                     source=source,
                     destination=destination,
                     tunnel=config.tunnel,
                     tunnelhost=config.tunnelhost,
                     tunnelport=config.tunnelport,
                     tunneluser=config.tunneluser,
                     download=False,
                     insecure=True,
                     vmport=bootstrap_helper_vmport)
        os.system(scpcmd)
        sedcmd = 'sed "s@https://api-int.%s.%s:22623/config/master@' % (
            cluster, domain)
        sedcmd += 'http://%s-bootstrap-helper.%s.%s/bootstrap@ "' % (
            cluster, cluster, domain)
        sedcmd += '%s/master.ign' % clusterdir
        sedcmd += ' > %s/bootstrap.ign' % clusterdir
        call(sedcmd, shell=True)
    if platform in virtplatforms:
        pprint("Deploying bootstrap")
        result = config.plan(plan,
                             inputfile='%s/bootstrap.yml' % plandir,
                             overrides=overrides)
        if result['result'] != 'success':
            os._exit(1)
        pprint("Deploying masters")
        result = config.plan(plan,
                             inputfile='%s/masters.yml' % plandir,
                             overrides=overrides)
        if result['result'] != 'success':
            os._exit(1)
        if platform == 'packet':
            allnodes = ["%s-bootstrap" % cluster] + [
                "%s-master-%s" % (cluster, num) for num in range(masters)
            ]
            for node in allnodes:
                try:
                    k.add_nic(node, network)
                except Exception as e:
                    error("Hit %s. Continuing still" % str(e))
                    continue
        bootstrapcommand = 'openshift-install --dir=%s wait-for bootstrap-complete' % clusterdir
        bootstrapcommand += ' || %s' % bootstrapcommand
        run = call(bootstrapcommand, shell=True)
        if run != 0:
            error("Leaving environment for debugging purposes")
            error("You can delete it with kcli delete cluster --yes %s" %
                  cluster)
            os._exit(run)
        todelete = [] if 'network_type' in data and data[
            'network_type'] == 'Contrail' else ["%s-bootstrap" % cluster]
        if platform in ['openstack', 'vsphere', 'packet']:
            todelete.append("%s-bootstrap-helper" % cluster)
    else:
        pprint("Deploying bootstrap")
        result = config.plan(plan,
                             inputfile='%s/cloud_bootstrap.yml' % plandir,
                             overrides=overrides)
        if result['result'] != 'success':
            os._exit(1)
        pprint("Deploying masters")
        result = config.plan(plan,
                             inputfile='%s/cloud_masters.yml' % plandir,
                             overrides=overrides)
        if result['result'] != 'success':
            os._exit(1)
        call('openshift-install --dir=%s wait-for bootstrap-complete || exit 1'
             % clusterdir,
             shell=True)
        todelete = [] if 'network_type' in data and data[
            'network_type'] == 'Contrail' else ["%s-bootstrap" % cluster]
        todelete.append("%s-bootstrap-helper" % cluster)
    if platform in virtplatforms:
        if workers > 0:
            pprint("Deploying workers")
            if 'name' in overrides:
                del overrides['name']
            if platform in virtplatforms:
                result = config.plan(plan,
                                     inputfile='%s/workers.yml' % plandir,
                                     overrides=overrides)
            elif platform in cloudplatforms:
                result = config.plan(plan,
                                     inputfile='%s/cloud_workers.yml' %
                                     plandir,
                                     overrides=overrides)
            if result['result'] != 'success':
                os._exit(1)
            if platform == 'packet':
                allnodes = [
                    "%s-worker-%s" % (cluster, num) for num in range(workers)
                ]
                for node in allnodes:
                    k.add_nic(node, network)
    if 'network_type' in data and data['network_type'] == 'Contrail':
        pprint("Waiting 7mn on install to be stable")
        sleep(420)
    call(
        "oc adm taint nodes -l node-role.kubernetes.io/master node-role.kubernetes.io/master:NoSchedule-",
        shell=True)
    pprint("Deploying certs autoapprover cronjob")
    autoapprovercmd = 'oc create -f %s/autoapprovercron.yml' % clusterdir
    call(autoapprovercmd, shell=True)
    if not minimal:
        installcommand = 'openshift-install --dir=%s wait-for install-complete' % clusterdir
        installcommand += " || %s" % installcommand
        pprint(
            "Launching install-complete step. It will be retried one extra time in case of timeouts"
        )
        call(installcommand, shell=True)
    else:
        kubeconf = os.environ['KUBECONFIG']
        kubepassword = open("%s/auth/auth/kubeadmin-password" %
                            clusterdir).read()
        success("Minimal Cluster ready to be used")
        success("INFO Install Complete")
        info2(
            "To access the cluster as the system:admin user when running 'oc', run export KUBECONFIG=%s"
            % kubeconf)
        info2(
            "Access the Openshift web-console here: https://console-openshift-console.apps.%s.%s"
            % (cluster, domain))
        info2("Login to the console with user: kubeadmin, password: %s" %
              kubepassword)
    for vm in todelete:
        pprint("Deleting %s" % vm)
        k.delete(vm)
    os.environ['KUBECONFIG'] = "%s/auth/kubeconfig" % clusterdir
    if apps:
        overrides['openshift_version'] = INSTALLER_VERSION[0:3]
        for app in apps:
            appdir = "%s/apps/%s" % (plandir, app)
            if not os.path.exists(appdir):
                warning("Skipping unsupported app %s" % app)
            else:
                pprint("Adding app %s" % app)
                kube_create_app(config, appdir, overrides=overrides)