def deploy(self, deployment_tpl_path, conf_file_path, bucket_name): """Deploy Forseti using the deployment template Args: deployment_tpl_path (str): Deployment template path conf_file_path (str): Configuration file path bucket_name (str): Name of the GCS bucket Returns: bool: Whether or not the deployment was successful str: Deployment name """ deployment_name = gcloud.create_deployment( self.project_id, self.organization_id, deployment_tpl_path, self.config.installation_type, self.config.identifier) status_checker = (lambda: gcloud.check_deployment_status( deployment_name, constants.DeploymentStatus.DONE)) loading_message = 'Waiting for deployment to be completed...' deployment_completed = utils.start_loading( max_loading_time=900, exit_condition_checker=status_checker, message=loading_message) if not deployment_completed: # If after 15 mins and the deployment is still not completed, there # is something wrong with the deployment. print('Deployment failed.') sys.exit(1) if deployment_completed: # If deployed successfully, make sure the VM has been initialized, # copy configuration file, deployment template file and # rule files to the GCS bucket utils.print_banner('Backing Up Important Files To GCS') conf_output_path = constants.FORSETI_CONF_PATH.format( bucket_name=bucket_name, installation_type=self.config.installation_type) print('Copying the Forseti {} configuration file to:\n\t{}'.format( self.config.installation_type, conf_output_path)) files.copy_file_to_destination(conf_file_path, conf_output_path, is_directory=False) deployment_tpl_output_path = ( constants.DEPLOYMENT_TEMPLATE_OUTPUT_PATH.format(bucket_name)) print( 'Copying the Forseti {} deployment template to:\n\t{}'.format( self.config.installation_type, deployment_tpl_output_path)) files.copy_file_to_destination(deployment_tpl_path, deployment_tpl_output_path, is_directory=False) return deployment_completed, deployment_name
def wait_until_vm_initialized(self, vm_name): """Check vm init status. Args: vm_name (str): Name of the VM instance. """ installation_type = self.config.installation_type utils.print_banner('Forseti {} VM Initialization'.format( installation_type.capitalize())) _, zone, name = gcloud.get_vm_instance_info(vm_name) status_checker = (lambda: gcloud.check_vm_init_status(name, zone)) loading_message = ('Waiting for Forseti {} to be initialized...'. format(installation_type)) try: _ = utils.start_loading( max_loading_time=constants.MAXIMUM_LOADING_TIME_IN_SECONDS, exit_condition_checker=status_checker, message=loading_message) except installer_errors.SSHError: # There is problem when SSHing to the VM, maybe there is a # firewall rule setting that is blocking the SSH from the # cloud shell. We will skip waiting for the VM to be initialized. pass
def get_email_settings(self): """Ask user for specific install values.""" utils.print_banner('Configuring GSuite Admin Information') if not self.config.gsuite_superadmin_email: # Ask for GSuite Superadmin email. print(constants.MESSAGE_ASK_GSUITE_SUPERADMIN_EMAIL) self.config.gsuite_superadmin_email = raw_input( constants.QUESTION_GSUITE_SUPERADMIN_EMAIL).strip() if self.config.skip_sendgrid_config: print(constants.MESSAGE_SKIP_SENDGRID_API_KEY) return utils.print_banner('Configuring Forseti Email Settings') if not self.config.sendgrid_api_key: # Ask for SendGrid API Key. print(constants.MESSAGE_ASK_SENDGRID_API_KEY) self.config.sendgrid_api_key = raw_input( constants.QUESTION_SENDGRID_API_KEY).strip() if self.config.sendgrid_api_key: if not self.config.notification_sender_email: self.config.notification_sender_email = ( constants.NOTIFICATION_SENDER_EMAIL) # Ask for notification recipient email. if not self.config.notification_recipient_email: self.config.notification_recipient_email = raw_input( constants.QUESTION_NOTIFICATION_RECIPIENT_EMAIL).strip()
def create_or_reuse_service_accts(self): """Create or reuse service accounts.""" utils.print_banner('Creating/Reusing Service Account(s)') gcp_service_acct_email, gcp_service_acct_name = ( self.format_gcp_service_acct_id()) self.gcp_service_acct_email = gcloud.create_or_reuse_service_acct( 'GCP Service Account', gcp_service_acct_name, gcp_service_acct_email)
def run_setup(self, setup_continuation=False, final_setup=True, previous_instructions=None): """Run the setup steps. If setup_continuation is True, we don't need to run the pre-flight checks any more because it has been done in the previous installation. Args: setup_continuation (bool): If this is a continuation of the previous setup. final_setup (bool): The final setup. previous_instructions (ForsetiInstructions): Post installation instructions from previous installation. Returns: ForsetiInstructions: Forseti instructions. """ utils.print_installation_header('Installing Forseti {}'.format( self.config.installation_type.capitalize())) if not setup_continuation: self.preflight_checks() # Create/Reuse service account(s). self.create_or_reuse_service_accts() # Create configuration file and deployment template. (conf_file_path, deployment_tpl_path) = self.create_resource_files() # Deployment. bucket_name = self.generate_bucket_name() deploy_success, _ = self.deploy(deployment_tpl_path, conf_file_path, bucket_name) # After deployment. instructions = self.post_install_instructions(deploy_success, bucket_name) if previous_instructions is not None: instructions.merge_head(previous_instructions) if final_setup: utils.print_banner('Forseti Post-Setup Instructions') print(instructions) return instructions
def determine_access_target(self): """Determine where to enable Forseti access. Allow only org level access since IAM explain requires org level access. """ utils.print_banner('Forseti Installation Configuration') if self.composite_root_resources: # split element 0 into type and id rtype, rid = self.composite_root_resources[0].split('/') self.access_target = rtype self.target_id = rid else: self.access_target = constants.RESOURCE_TYPES[0] self.target_id = self.organization_id while not self.target_id: if self.setup_explain: # If user wants to setup Explain, they must setup # access on an organization. choice_index = 1 else: try: print(constants.MESSAGE_FORSETI_CONFIGURATION_ACCESS_LEVEL) for (i, choice) in enumerate(constants.RESOURCE_TYPES): print('[%s] %s' % (i+1, choice)) choice_input = raw_input( constants.QUESTION_FORSETI_CONFIGURATION_ACCESS_LEVEL ).strip() choice_index = int(choice_input) except ValueError: print('Invalid choice, try again.') continue if choice_index and choice_index <= len(constants.RESOURCE_TYPES): self.access_target = constants.RESOURCE_TYPES[choice_index-1] if self.access_target == 'organizations': self.target_id = gcloud.choose_organization() elif self.access_target == 'folders': self.target_id = gcloud.choose_folder(self.organization_id) else: self.target_id = gcloud.choose_project() self.resource_root_id = utils.format_resource_id( self.access_target, self.target_id)
def preflight_checks(self): """Pre-flight checks""" utils.print_banner('Pre-installation checks') self.version = utils.infer_version() self.composite_root_resources = self.config.composite_root_resources service_account_key_file = self.config.service_account_key_file if self.config.project_id: gcloud.set_project_id(self.config.project_id) self.project_id, authed_user, is_cloudshell = gcloud.get_gcloud_info() gcloud.verify_gcloud_information(self.project_id, authed_user, self.config.force_no_cloudshell, is_cloudshell) self.organization_id = gcloud.lookup_organization(self.project_id) self.config.generate_identifier(self.organization_id) if not service_account_key_file: self.check_if_authed_user_in_domain(self.organization_id, authed_user) else: gcloud.activate_service_account(service_account_key_file) gcloud.check_billing_enabled(self.project_id, self.organization_id)