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))
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']))
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']))
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")
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")
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)
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")
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)
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)